stub-cache-x64.cc revision 9413bcbe2192ed4d701281130490e0ba336debdc
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_X64) 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 // The offset is scaled by 4, based on 493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // kHeapObjectTagSize, which is two bits 50a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register offset) { 513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We need to scale up the pointer by 2 because the offset is scaled by less 523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // than the pointer size. 533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(kPointerSizeLog2 == kHeapObjectTagSize + 1); 543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ScaleFactor scale_factor = times_2; 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT_EQ(24, sizeof(StubCache::Entry)); 573ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // The offset register holds the entry offset times four (due to masking 583ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // and shifting optimizations). 5944f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); 603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); 61a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 62a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Multiply by 3 because there are 3 fields per entry (name, code, map). 643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(offset, Operand(offset, offset, times_2, 0)); 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadAddress(kScratchRegister, key_offset); 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 68a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the key in the entry matches the name. 693ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // Multiply entry offset by 16 to get the entry address. Since the 703ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // offset register already holds the entry offset times four, multiply 713ce2e2076e8e3e60cf1810eec160ea2d8557e9e7Steve Block // by a further four. 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpl(name, Operand(kScratchRegister, offset, scale_factor, 0)); 735d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch __ j(not_equal, &miss); 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the map entry from the cache. 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Use key_offset + kPointerSize * 2, rather than loading map_offset. 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(kScratchRegister, 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(kScratchRegister, offset, scale_factor, kPointerSize * 2)); 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(kScratchRegister, FieldOperand(receiver, HeapObject::kMapOffset)); 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss); 813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 82a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the code entry from the cache. 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadAddress(kScratchRegister, value_offset); 84a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(kScratchRegister, 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(kScratchRegister, offset, scale_factor, 0)); 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 87a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the flags match what we're looking for. 88a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movl(offset, FieldOperand(kScratchRegister, Code::kFlagsOffset)); 89a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(offset, Immediate(~Code::kFlagsNotUsedInLookup)); 90a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpl(offset, Immediate(flags)); 91a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 92a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { 953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 101a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the first instruction in the code stub. 102a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addq(kScratchRegister, Immediate(Code::kHeaderSize - kHeapObjectTag)); 103a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ jmp(kScratchRegister); 104a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 105a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 106a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 107a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 108a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1093bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Helper function used to check that the dictionary doesn't contain 1103bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// the property. This function may return false negatives, so miss_label 1113bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// must always call a backup property check that is complete. 1123bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// This function is safe to call if the receiver has fast properties. 1133bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch// Name must be a symbol and receiver must be a heap object. 1143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 1153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss_label, 1163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 1173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register r0, 1193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register r1) { 1203bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch ASSERT(name->IsSymbol()); 12144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 12244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->negative_lookups(), 1); 12344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->negative_lookups_miss(), 1); 1243bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ movq(r0, FieldOperand(receiver, HeapObject::kMapOffset)); 1263bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1273bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch const int kInterceptorOrAccessCheckNeededMask = 1283bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 1293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1303bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Bail out if the receiver has a named interceptor or requires access checks. 1313bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ testb(FieldOperand(r0, Map::kBitFieldOffset), 1323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Immediate(kInterceptorOrAccessCheckNeededMask)); 1333bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ j(not_zero, miss_label); 1343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1353bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check that receiver is a JSObject. 1363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ CmpInstanceType(r0, FIRST_SPEC_OBJECT_TYPE); 1373bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ j(below, miss_label); 1383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Load properties array. 1403bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register properties = r0; 1413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ movq(properties, FieldOperand(receiver, JSObject::kPropertiesOffset)); 1423bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1433bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch // Check that the properties array is a dictionary. 1443bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ CompareRoot(FieldOperand(properties, HeapObject::kMapOffset), 1453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Heap::kHashTableMapRootIndex); 1463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ j(not_equal, miss_label); 1473bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 1493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringDictionaryLookupStub::GenerateNegativeLookup(masm, 1503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss_label, 1513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done, 1523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch properties, 1533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 1543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch r1); 1553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch __ bind(&done); 15644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->negative_lookups_miss(), 1); 1573bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch} 1583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 1593bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 160a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCache::GenerateProbe(MacroAssembler* masm, 161a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Code::Flags flags, 162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register name, 164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 1653e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register extra, 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register extra2, 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register extra3) { 16844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = masm->isolate(); 169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1703e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu USE(extra); // The register extra is not used on the X64 platform. 1713e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu USE(extra2); // The register extra2 is not used on the X64 platform. 1723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch USE(extra3); // The register extra2 is not used on the X64 platform. 1733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that code is valid. The multiplying code relies on the 1743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // entry size being 24. 1753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(sizeof(Entry) == 24); 176a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 177a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure the flags do not name a specific type. 178a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(Code::ExtractTypeFromFlags(flags) == 0); 179a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 180a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Make sure that there are no register conflicts. 181a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(receiver)); 182a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(!scratch.is(name)); 183a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1843e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu // Check scratch register is valid, extra and extra2 are unused. 1853e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(!scratch.is(no_reg)); 1863e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu ASSERT(extra2.is(no_reg)); 1873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(extra3.is(no_reg)); 1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Counters* counters = masm->isolate()->counters(); 1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1); 1913e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu 192a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 193a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ JumpIfSmi(receiver, &miss); 194a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 195a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Get the map of the receiver and compute the hash. 196d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movl(scratch, FieldOperand(name, String::kHashFieldOffset)); 197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use only the low 32 bits of the map pointer. 198a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ xor_(scratch, Immediate(flags)); 2003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We mask out the last two bits because they are not part of the hash and 2013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // they are always 01 for maps. Also in the two 'and' instructions below. 202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize)); 203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the primary table. 2053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ProbeTable(isolate, masm, flags, kPrimary, receiver, name, scratch); 206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Primary miss: Compute hash for secondary probe. 208d0582a6c46733687d045e4188a1bcd0123c758a1Steve Block __ movl(scratch, FieldOperand(name, String::kHashFieldOffset)); 209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addl(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ xor_(scratch, Immediate(flags)); 211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, Immediate((kPrimaryTableSize - 1) << kHeapObjectTagSize)); 212a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ subl(scratch, name); 213a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ addl(scratch, Immediate(flags)); 214a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ and_(scratch, Immediate((kSecondaryTableSize - 1) << kHeapObjectTagSize)); 215a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 216a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Probe the secondary table. 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ProbeTable(isolate, masm, flags, kSecondary, receiver, name, scratch); 218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cache miss: Fall-through and let caller handle the miss by 220a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // entering the runtime system. 221a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1); 223a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 224a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 225a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, 2279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index, 2289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register prototype) { 2299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load the global or builtins object from the current context. 2309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(prototype, 2319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX))); 2329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load the global context from the global or builtins object. 2339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(prototype, 2349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block FieldOperand(prototype, GlobalObject::kGlobalContextOffset)); 2359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load the function from the global context. 2369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(prototype, Operand(prototype, Context::SlotOffset(index))); 2379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load the initial map. The global functions all have initial maps. 2389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(prototype, 2399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block FieldOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); 2409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load the prototype from the initial map. 2419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 2429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 243a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 244a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index, 2483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register prototype, 2493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 25044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Isolate* isolate = masm->isolate(); 2519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check we're still in the same context. 25244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(prototype, isolate->global()); 2539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ cmpq(Operand(rsi, Context::SlotOffset(Context::GLOBAL_INDEX)), 2549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block prototype); 2559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, miss); 2569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the global function with the given index. 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function( 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSFunction::cast(isolate->global_context()->get(index))); 2599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load its initial map. The global functions all have initial maps. 2609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Move(prototype, Handle<Map>(function->initial_map())); 2619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load the prototype from the initial map. 2629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(prototype, FieldOperand(prototype, Map::kPrototypeOffset)); 263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 264a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 268a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 271a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ JumpIfSmi(receiver, miss_label); 272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a JS array. 274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(receiver, JS_ARRAY_TYPE, scratch); 275a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, miss_label); 276a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 277a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the JS array. 278a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, FieldOperand(receiver, JSArray::kLengthOffset)); 279a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 280a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 281a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 282a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 283a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Generate code to check if an object is a string. If the object is 284a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// a string, the map's instance type is left in the scratch register. 285a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockstatic void GenerateStringCheck(MacroAssembler* masm, 286a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 287a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register scratch, 288a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* smi, 289a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* non_string_object) { 290a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object isn't a smi. 291a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ JumpIfSmi(receiver, smi); 292a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 293a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the object is a string. 294a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(scratch, FieldOperand(receiver, HeapObject::kMapOffset)); 295a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbq(scratch, FieldOperand(scratch, Map::kInstanceTypeOffset)); 29669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kNotStringTag != 0); 297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ testl(scratch, Immediate(kNotStringTag)); 298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_zero, non_string_object); 299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 300a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 304402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch1, 305402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register scratch2, 3061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block Label* miss, 3071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block bool support_wrappers) { 308402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Label check_wrapper; 309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the object is a string leaving the instance type in the 311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // scratch register. 3121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateStringCheck(masm, receiver, scratch1, miss, 3131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block support_wrappers ? &check_wrapper : miss); 314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load length directly from the string. 3166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(rax, FieldOperand(receiver, String::kLengthOffset)); 317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block if (support_wrappers) { 3201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check if the object is a JSValue wrapper. 3211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&check_wrapper); 3221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cmpl(scratch1, Immediate(JS_VALUE_TYPE)); 3231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(not_equal, miss); 324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check if the wrapped value is a string and load the length 3261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // directly if it is. 3271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(scratch2, FieldOperand(receiver, JSValue::kValueOffset)); 3281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateStringCheck(masm, scratch2, scratch1, miss, miss); 3291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, FieldOperand(scratch2, String::kLengthOffset)); 3301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 3311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 332a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 3369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register receiver, 3379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register result, 3389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch, 3399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label* miss_label) { 3409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ TryGetFunctionPrototype(receiver, result, miss_label); 3419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!result.is(rax)) __ movq(rax, result); 3429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(0); 3439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 3449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 3459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 3469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// Load a fast property out of a holder object (src). In-object properties 3479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// are loaded directly otherwise the property is loaded from the properties 3489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// fixed array. 3499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 3503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst, 3513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src, 3523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 3533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index) { 3549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Adjust for the number of properties stored in the holder. 3559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block index -= holder->map()->inobject_properties(); 3569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (index < 0) { 3579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the property straight out of the holder. 3589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int offset = holder->map()->instance_size() + (index * kPointerSize); 3599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(dst, FieldOperand(src, offset)); 3609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 3619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Calculate the offset into the properties array. 3629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 3639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(dst, FieldOperand(src, JSObject::kPropertiesOffset)); 3649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(dst, FieldOperand(dst, offset)); 3659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 3669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 3679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 3689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 3699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockstatic void PushInterceptorArguments(MacroAssembler* masm, 3709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register receiver, 3719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register holder, 3729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register name, 3733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj) { 3749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(name); 3753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 3763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); 3773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(kScratchRegister, interceptor); 3789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(kScratchRegister); 3799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(receiver); 3809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(holder); 3819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(FieldOperand(kScratchRegister, InterceptorInfo::kDataOffset)); 3829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 3839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 3849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 3853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CompileCallLoadPropertyWithInterceptor( 3863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 3873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 3883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register holder, 3893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register name, 3903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj) { 391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 393a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference ref = 39444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), 39544f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()); 3968b112d2025046f85ef7f6be087c6129c872ebad2Ben Murdoch __ Set(rax, 5); 39744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ LoadAddress(rbx, ref); 398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block CEntryStub stub(1); 400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CallStub(&stub); 401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4048a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Number of pointers to be reserved on stack for fast API call. 4058a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wangstatic const int kFastApiCallArguments = 3; 406a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 4079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 4088a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Reserves space for the extra arguments to API function in the 4096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// caller's frame. 4106ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// 4116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// These arguments are set by CheckPrototypes and GenerateFastApiCall. 4126ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 4136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 4146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- rsp[0] : return address 4156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- rsp[8] : last argument in the internal frame of the caller 4166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 4176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(scratch, Operand(rsp, 0)); 4188a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 4196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(Operand(rsp, 0), scratch); 4206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Move(scratch, Smi::FromInt(0)); 4218a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang for (int i = 1; i <= kFastApiCallArguments; i++) { 4228a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(Operand(rsp, i * kPointerSize), scratch); 4238a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang } 4246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// Undoes the effects of ReserveSpaceForFastApiCall. 4286ded16be15dd865a9b21ea304d5273c8be299c87Steve Blockstatic void FreeSpaceForFastApiCall(MacroAssembler* masm, Register scratch) { 4296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 4308a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- rsp[0] : return address. 4318a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- rsp[8] : last fast api call extra argument. 4326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ... 4338a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- rsp[kFastApiCallArguments * 8] : first fast api call extra argument. 4348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- rsp[kFastApiCallArguments * 8 + 8] : last argument in the internal 4358a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // frame. 4366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 4376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(scratch, Operand(rsp, 0)); 4388a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(Operand(rsp, kFastApiCallArguments * kPointerSize), scratch); 4398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ addq(rsp, Immediate(kPointerSize * kFastApiCallArguments)); 4406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 4416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4438a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang// Generates call to API function. 4443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateFastApiCall(MacroAssembler* masm, 4453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const CallOptimization& optimization, 4463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int argc) { 4476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------- S t a t e ------------- 4486ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- rsp[0] : return address 4496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- rsp[8] : object passing the type check 4506ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // (last fast api call extra argument, 4516ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // set by CheckPrototypes) 4528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- rsp[16] : api function 4536ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // (first fast api call extra argument) 4548a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- rsp[24] : api call data 4558a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- rsp[32] : last argument 4566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // -- ... 4578a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- rsp[(argc + 3) * 8] : first argument 4588a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // -- rsp[(argc + 4) * 8] : receiver 4596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // ----------------------------------- 4606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the function and setup the context. 4613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function = optimization.constant_function(); 4623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(rdi, function); 4636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 4646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4658a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Pass the additional arguments. 4668a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(Operand(rsp, 2 * kPointerSize), rdi); 4673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 4683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> call_data(api_call_info->data()); 4693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (masm->isolate()->heap()->InNewSpace(*call_data)) { 4703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rcx, api_call_info); 4716ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(rbx, FieldOperand(rcx, CallHandlerInfo::kDataOffset)); 4728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(Operand(rsp, 3 * kPointerSize), rbx); 4736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 4743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(Operand(rsp, 3 * kPointerSize), call_data); 4756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 4766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4778a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Prepare arguments. 4788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ lea(rbx, Operand(rsp, 3 * kPointerSize)); 4796ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 4808a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#ifdef _WIN64 4818a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Win64 uses first register--rcx--for returned value. 4828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register arguments_arg = rdx; 4838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#else 4848a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang Register arguments_arg = rdi; 4858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang#endif 4868a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 4878a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // Allocate the v8::Arguments structure in the arguments' space since 4888a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // it's not controlled by GC. 4898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang const int kApiStackSpace = 4; 4908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 4918a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ PrepareCallApiFunction(kApiStackSpace); 4928a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 4938a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(StackSpaceOperand(0), rbx); // v8::Arguments::implicit_args_. 4948a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ addq(rbx, Immediate(argc * kPointerSize)); 4958a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ movq(StackSpaceOperand(1), rbx); // v8::Arguments::values_. 4968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Set(StackSpaceOperand(2), argc); // v8::Arguments::length_. 4978a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // v8::Arguments::is_construct_call_. 4988a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ Set(StackSpaceOperand(3), 0); 4998a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 5008a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang // v8::InvocationCallback's argument. 5018a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang __ lea(arguments_arg, StackSpaceOperand(0)); 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Function address is a foreign pointer outside V8's heap. 5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address function_address = v8::ToCData<Address>(api_call_info->callback()); 5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallApiFunctionAndReturn(function_address, 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch argc + kFastApiCallArguments + 1); 5076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 5086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5096ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 510a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Blockclass CallInterceptorCompiler BASE_EMBEDDED { 511a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block public: 5126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CallInterceptorCompiler(StubCompiler* stub_compiler, 5136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block const ParameterCount& arguments, 514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register name, 515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Code::ExtraICState extra_ic_state) 5166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block : stub_compiler_(stub_compiler), 5176ded16be15dd865a9b21ea304d5273c8be299c87Steve Block arguments_(arguments), 518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch name_(name), 519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch extra_ic_state_(extra_ic_state) {} 5206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Compile(MacroAssembler* masm, 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 5233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 5243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 5253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult* lookup, 5263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 5283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 5293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 5303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 5316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(holder->HasNamedInterceptor()); 5326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 5336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Check that the receiver isn't a smi. 5356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ JumpIfSmi(receiver, miss); 5366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block CallOptimization optimization(lookup); 5386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (optimization.is_constant_call()) { 5393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, 5403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder, lookup, name, optimization, miss); 5416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 5423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, 5433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, holder, miss); 5446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 5456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 546a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block private: 5483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CompileCacheable(MacroAssembler* masm, 5493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 5503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 5513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 5523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 5533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 5543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 5553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult* lookup, 5563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 5573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const CallOptimization& optimization, 5583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss_label) { 5596ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(optimization.is_constant_call()); 5606ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(!lookup->holder()->IsGlobalObject()); 5616ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 5626ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int depth1 = kInvalidProtoDepth; 5636ded16be15dd865a9b21ea304d5273c8be299c87Steve Block int depth2 = kInvalidProtoDepth; 5646ded16be15dd865a9b21ea304d5273c8be299c87Steve Block bool can_do_fast_api_call = false; 5656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (optimization.is_simple_api_call() && 5666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block !lookup->holder()->IsGlobalObject()) { 5673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth1 = optimization.GetPrototypeDepthOfExpectedType( 5683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, interceptor_holder); 5696ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (depth1 == kInvalidProtoDepth) { 5703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth2 = optimization.GetPrototypeDepthOfExpectedType( 5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder, Handle<JSObject>(lookup->holder())); 572a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch can_do_fast_api_call = 5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; 575a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 576a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 57744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = masm->isolate()->counters(); 57844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_interceptor(), 1); 579a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 5806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 58144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1); 5826ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ReserveSpaceForFastApiCall(masm, scratch1); 5836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 584402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 585f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from receiver to interceptor's holder 586f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // haven't changed and thus we can invoke interceptor. 5876ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label miss_cleanup; 5886ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 5896ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register holder = 5903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 5913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 5923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth1, miss); 593a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 594f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke an interceptor and if it provides a value, 595f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // branch to |regular_invoke|. 5966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label regular_invoke; 597f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke LoadWithInterceptor(masm, receiver, holder, interceptor_holder, 598f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke ®ular_invoke); 599a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 600f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Interceptor returned nothing for this property. Try to use cached 601f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // constant function. 602a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 603f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Check that the maps from interceptor's holder to constant function's 604f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // holder haven't changed and thus we can use cached constant function. 6053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*interceptor_holder != lookup->holder()) { 6067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch stub_compiler_->CheckPrototypes(interceptor_holder, receiver, 6073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 6083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 6093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth2, miss); 6107f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } else { 6117f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // CheckPrototypes has a side effect of fetching a 'holder' 6127f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // for API (object which is instanceof for the signature). It's 6137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // safe to omit it here, as if present, it should be fetched 6147f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch // by the previous CheckPrototypes. 6157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch ASSERT(depth2 == kInvalidProtoDepth); 6167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 617a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 618f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke function. 6196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 6203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiCall(masm, optimization, arguments_.immediate()); 6216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } else { 622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) 623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 6256ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ InvokeFunction(optimization.constant_function(), arguments_, 626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch JUMP_FUNCTION, NullCallWrapper(), call_kind); 6276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 628a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 629f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Deferred code for fast API call case---clean preallocated space. 6306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 6316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss_cleanup); 6326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FreeSpaceForFastApiCall(masm, scratch1); 6336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ jmp(miss_label); 6346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 635a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 636f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // Invoke a regular function. 6376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(®ular_invoke); 6386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block if (can_do_fast_api_call) { 6396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block FreeSpaceForFastApiCall(masm, scratch1); 6406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 641a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 643a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block void CompileRegular(MacroAssembler* masm, 6443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 645a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Register receiver, 6466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch1, 6476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register scratch2, 6483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch Register scratch3, 6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 6503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label* miss_label) { 6526ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register holder = 653f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 6543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 6553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, miss_label); 6566ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 658402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Save the name_ register across the call. 659402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ push(name_); 660a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); 662a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 663402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ CallExternalReference( 66444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorForCall), 66544f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 666402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu 5); 667a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6686ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Restore the name_ register. 669402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu __ pop(name_); 6703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 672a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 673a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 6746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block void LoadWithInterceptor(MacroAssembler* masm, 6756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register receiver, 6766ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Register holder, 6773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj, 6786ded16be15dd865a9b21ea304d5273c8be299c87Steve Block Label* interceptor_succeeded) { 6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 6813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(holder); // Save the holder. 6823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(name_); // Save the name. 6833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm, 6853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 6863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder, 6873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_, 6883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_obj); 6893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 6903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_); // Restore the name. 6913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); // Restore the holder. 6923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 6933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 6946ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); 6966ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, interceptor_succeeded); 6976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 6986ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 6996ded16be15dd865a9b21ea304d5273c8be299c87Steve Block StubCompiler* stub_compiler_; 700a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const ParameterCount& arguments_; 701402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu Register name_; 702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Code::ExtraICState extra_ic_state_; 703a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block}; 704a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 7069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 7079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 7083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = (kind == Code::LOAD_IC) 7093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? masm->isolate()->builtins()->LoadIC_Miss() 7103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : masm->isolate()->builtins()->KeyedLoadIC_Miss(); 7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 7129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 7139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid StubCompiler::GenerateKeyedLoadMissForceGeneric(MacroAssembler* masm) { 7163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 7173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 7183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 7229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// Both name_reg and receiver_reg are preserved on jumps to miss_label, 7239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// but may be destroyed if store is successful. 7249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Blockvoid StubCompiler::GenerateStoreField(MacroAssembler* masm, 7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 7269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index, 7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 7289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register receiver_reg, 7299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register name_reg, 7309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch, 7319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label* miss_label) { 7329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the map of the object hasn't changed. 7338f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS 7348f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch : REQUIRE_EXACT_MAP; 7353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(receiver_reg, Handle<Map>(object->map()), 7368f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch miss_label, DO_SMI_CHECK, mode); 7379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Perform global security token check if needed. 7399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (object->IsJSGlobalProxy()) { 7409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 7419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 7429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Stub never generated for non-global objects that require access 7449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // checks. 7459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 7469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Perform map transition for the receiver if necessary. 7483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { 7499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // The properties must be extended before we can store the value. 7509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // We jump to a runtime call that extends the properties array. 7519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ pop(scratch); // Return address. 7529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(receiver_reg); 7533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(transition); 7549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(rax); 7559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(scratch); 7569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ TailCallExternalReference( 75744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 75844f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()), 75944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3, 76044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 7619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return; 7629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 7639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition.is_null()) { 7659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Update the map of the object; no write barrier updating is 7669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // needed because the map is never in new space. 7673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(receiver_reg, HeapObject::kMapOffset), transition); 7689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 7699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Adjust for the number of properties stored in the object. Even in the 7719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // face of a transition we can use the old map here because the size of the 7729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // object and the number of in-object properties is not going to change. 7739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block index -= object->map()->inobject_properties(); 7749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (index < 0) { 7769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Set the property straight into the object. 7779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int offset = object->map()->instance_size() + (index * kPointerSize); 7789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(FieldOperand(receiver_reg, offset), rax); 7799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Update the write barrier for the array address. 7819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Pass the value being stored in the now unused name_reg. 7829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(name_reg, rax); 7833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField( 7843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, offset, name_reg, scratch, kDontSaveFPRegs); 7859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 7869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Write to the properties array. 7879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int offset = index * kPointerSize + FixedArray::kHeaderSize; 7889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the properties array (optimistically). 7899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(scratch, FieldOperand(receiver_reg, JSObject::kPropertiesOffset)); 7909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(FieldOperand(scratch, offset), rax); 7919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Update the write barrier for the array address. 7939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Pass the value being stored in the now unused name_reg. 7949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(name_reg, rax); 7953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField( 7963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, offset, name_reg, receiver_reg, kDontSaveFPRegs); 7979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 7989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 7999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the value (register rax). 8009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(0); 8019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 8029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 8039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 8049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// Generate code to check that a global property cell is empty. Create 8059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block// the property cell at compilation time if no cell exists for the 8066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block// property. 8073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm, 8083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> global, 8093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 8123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 8133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GlobalObject::EnsurePropertyCell(global, name); 8146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block ASSERT(cell->value()->IsTheHole()); 8153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(scratch, cell); 8166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ Cmp(FieldOperand(scratch, JSGlobalPropertyCell::kValueOffset), 81744f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm->isolate()->factory()->the_hole_value()); 8186ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ j(not_equal, miss); 8196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 8206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8216ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Calls GenerateCheckPropertyCell for each global object in the prototype chain 8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// from object to (but not including) holder. 8243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm, 8253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 8263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 8303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> current = object; 8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!current.is_identical_to(holder)) { 8323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (current->IsGlobalObject()) { 8333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell(masm, 8343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject>::cast(current), 8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 8363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 8373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss); 8383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); 8403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 8413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch} 8423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 843a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 844a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#define __ ACCESS_MASM((masm())) 845a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 8469dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 8473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object, 8489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register object_reg, 8493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 8509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register holder_reg, 8519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch1, 8529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch2, 8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int save_at_depth, 8559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label* miss) { 8569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Make sure there's no overlap between holder and object registers. 8579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 8589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 8599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block && !scratch2.is(scratch1)); 8609dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 8619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Keep track of the current object in register reg. On the first 8629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // iteration, reg is an alias for object_reg, on later iterations, 8639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // it is an alias for holder_reg. 8649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register reg = object_reg; 8659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int depth = 0; 8669dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 8679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (save_at_depth == depth) { 8689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rsp, kPointerSize), object_reg); 8699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 87059151504615d929945dc59db37bf1166937748c6Steve Block 8719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check the maps in the prototype chain. 8729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Traverse the prototype chain from the object and do map checks. 8733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> current = object; 8743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!current.is_identical_to(holder)) { 8753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++depth; 87659151504615d929945dc59db37bf1166937748c6Steve Block 8779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Only global objects and objects that do not require access 8789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // checks are allowed in stubs. 8799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 88059151504615d929945dc59db37bf1166937748c6Steve Block 8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); 8829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!current->HasFastProperties() && 8839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block !current->IsJSGlobalObject() && 8849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block !current->IsJSGlobalProxy()) { 8859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!name->IsSymbol()) { 8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name = factory()->LookupSymbol(name); 8879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 8883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(current->property_dictionary()->FindEntry(*name) == 8899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block StringDictionary::kNotFound); 89059151504615d929945dc59db37bf1166937748c6Steve Block 8913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, 8923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2); 893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 8949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 8953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 8969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 8973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 8983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool in_new_space = heap()->InNewSpace(*prototype); 8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> current_map(current->map()); 9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (in_new_space) { 9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save the map in scratch1 for later. 9029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(scratch1, FieldOperand(reg, HeapObject::kMapOffset)); 9039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(reg, Handle<Map>(current_map), 9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 906c7cc028aaeedbbfa11c11d0b7b243b3d9e837ed9Ben Murdoch 9073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check access rights to the global object. This has to happen after 9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the map check so that we know that the object is actually a global 9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object. 9109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (current->IsJSGlobalProxy()) { 9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckAccessGlobalProxy(reg, scratch2, miss); 9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 9133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (in_new_space) { 9163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The prototype is in new space; we cannot store a reference to it 9173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in the code. Load it from the map. 9183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(reg, FieldOperand(scratch1, Map::kPrototypeOffset)); 9193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 9203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The prototype is in old space; load it directly. 9213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(reg, prototype); 9229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 9239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 92459151504615d929945dc59db37bf1166937748c6Steve Block 9259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (save_at_depth == depth) { 9269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rsp, kPointerSize), reg); 9279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 92859151504615d929945dc59db37bf1166937748c6Steve Block 9299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Go to the next object in the prototype chain. 9309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block current = prototype; 93159151504615d929945dc59db37bf1166937748c6Steve Block } 9323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(current.is_identical_to(holder)); 933592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 934592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch // Log the check depth. 935592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch LOG(isolate(), IntEvent("check-maps-depth", depth + 1)); 93659151504615d929945dc59db37bf1166937748c6Steve Block 9373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check the holder map. 9383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(reg, Handle<Map>(holder->map()), 9393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss, DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 9403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 9413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Perform security check for access to the global object. 9429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 9439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (current->IsJSGlobalProxy()) { 9449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CheckAccessGlobalProxy(reg, scratch1, miss); 945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we've skipped any global objects, it's not enough to verify that 9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // their maps haven't changed. We also need to check that the property 9493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // cell for the property is still empty. 9503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the register containing the holder. 9539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return reg; 954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object, 9583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 9599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register receiver, 9609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch1, 9619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch2, 9629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch3, 9639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index, 9643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 9659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label* miss) { 966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the receiver isn't a smi. 9679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(receiver, miss); 968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check the prototype chain. 9703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = CheckPrototypes( 9713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the value from the properties. 9749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateFastPropertyLoad(masm(), rax, reg, holder, index); 9759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(0); 976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 9793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object, 9803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 9813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 9823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register name_reg, 9833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 9843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 9853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 9863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 9873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 9883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 9899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 9909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(receiver, miss); 9916ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 9933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = CheckPrototypes(object, receiver, holder, scratch1, 9943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2, scratch3, name, miss); 9956ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 9969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Insert additional parameters into the stack frame above return address. 9979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(!scratch2.is(reg)); 9989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ pop(scratch2); // Get return address to place it below. 9999dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 10009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(receiver); // receiver 10019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(reg); // holder 10023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (heap()->InNewSpace(callback->data())) { 10033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(scratch1, callback); 10049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(FieldOperand(scratch1, AccessorInfo::kDataOffset)); // data 10059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 10063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(Handle<Object>(callback->data())); 10079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 10089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(name_reg); // name 10099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Save a pointer to where we pushed the arguments pointer. 10109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // This will be passed as the const AccessorInfo& to the C++ callback. 10116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block#ifdef _WIN64 10139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Win64 uses first register--rcx--for returned value. 10149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register accessor_info_arg = r8; 10159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register name_arg = rdx; 10169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block#else 10179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register accessor_info_arg = rsi; 10189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register name_arg = rdi; 10199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block#endif 10206ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(!name_arg.is(scratch2)); 10229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(name_arg, rsp); 10239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(scratch2); // Restore return address. 10246ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // 3 elements array for v8::Arguments::values_ and handler for name. 10269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int kStackSpace = 4; 10276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Allocate v8::AccessorInfo in non-GCed stack space. 10299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int kArgStackSpace = 1; 10306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ PrepareCallApiFunction(kArgStackSpace); 10329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ lea(rax, Operand(name_arg, 3 * kPointerSize)); 10336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // v8::AccessorInfo::args_. 10359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(StackSpaceOperand(0), rax); 10366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // The context register (rsi) has been saved in PrepareCallApiFunction and 10389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // could be used to pass arguments. 10399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ lea(accessor_info_arg, StackSpaceOperand(0)); 10406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address getter_address = v8::ToCData<Address>(callback->getter()); 10423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallApiFunctionAndReturn(getter_address, kStackSpace); 10439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 10446ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 10473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 10489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register receiver, 10499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch1, 10509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch2, 10519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch3, 10523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 10533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 10549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label* miss) { 10559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 10569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(receiver, miss); 10576ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 10593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 10603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 10619dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 10629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the constant value. 10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(rax, value); 10649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(0); 10659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 10666ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10676ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 10693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 10709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block LookupResult* lookup, 10719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register receiver, 10729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register name_reg, 10739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch1, 10749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch2, 10759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register scratch3, 10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 10779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label* miss) { 10789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(interceptor_holder->HasNamedInterceptor()); 10799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 10806ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 10829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(receiver, miss); 10836ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 10849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // So far the most popular follow ups for interceptor loads are FIELD 10859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // and CALLBACKS, so inline only them, other cases may be added 10869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // later. 10879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block bool compile_followup_inline = false; 10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->IsFound() && lookup->IsCacheable()) { 10899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (lookup->type() == FIELD) { 10909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block compile_followup_inline = true; 10919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else if (lookup->type() == CALLBACKS && 10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetCallbackObject()->IsAccessorInfo()) { 10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compile_followup_inline = 10943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; 10959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 10969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 10979dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 10989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (compile_followup_inline) { 10999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Compile the interceptor call, followed by inline code to load the 11009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // property from further up the prototype chain if the call fails. 11019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 11029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 11039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block scratch1, scratch2, scratch3, 11049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name, miss); 11059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); 11066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Save necessary data before invoking an interceptor. 11089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Requires a frame to make GC aware of pushed pointers. 11093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 11103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 11116ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 11133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CALLBACKS case needs a receiver to be passed into C++ callback. 11143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(receiver); 11153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(holder_reg); 11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(name_reg); 1118592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // interceptor's holder has been compiled before (see a caller 11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of this method.) 11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm(), 11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_reg, 11253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder); 11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if interceptor provided a value for property. If it's 11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the case, return immediately. 11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label interceptor_failed; 11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); 11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &interceptor_failed); 11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_scope.GenerateLeaveFrame(); 11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&interceptor_failed); 11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_reg); 11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(holder_reg); 11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); 11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 114585b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 11469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps from interceptor's holder to lookup's holder 11479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // haven't changed. And load lookup's holder into |holder| register. 11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*interceptor_holder != lookup->holder()) { 11499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block holder_reg = CheckPrototypes(interceptor_holder, 11509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block holder_reg, 11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 11529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block scratch1, 11539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block scratch2, 11549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block scratch3, 11559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name, 11569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block miss); 11579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 11586ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (lookup->type() == FIELD) { 11609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // We found FIELD property in prototype chain of interceptor's holder. 11619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Retrieve a field from field's holder. 11629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateFastPropertyLoad(masm(), rax, holder_reg, 11633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 11643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetFieldIndex()); 11659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(0); 11669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 11679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // We found CALLBACKS property in prototype chain of interceptor's 11689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // holder. 11699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(lookup->type() == CALLBACKS); 11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback( 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())); 11729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(callback->getter() != NULL); 1173756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 11749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Tail call to runtime. 11759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Important invariant in CALLBACKS case: the code above must be 11769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // structured to never clobber |receiver| register. 11779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ pop(scratch2); // return address 11789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(receiver); 11799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(holder_reg); 11803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(holder_reg, callback); 11819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); 11829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(holder_reg); 11839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(name_reg); 11849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(scratch2); // restore return address 1185756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 11869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ExternalReference ref = 118744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadCallbackProperty), 118844f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 11899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ TailCallExternalReference(ref, 5, 1); 11906ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { // !compile_followup_inline 11929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Call the runtime system to load the interceptor. 11939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 11949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 11959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block scratch1, scratch2, scratch3, 11969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name, miss); 11979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ pop(scratch2); // save old return address 11989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block PushInterceptorArguments(masm(), receiver, holder_reg, 11999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name_reg, interceptor_holder); 12009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(scratch2); // restore old return address 12016ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ExternalReference ref = ExternalReference( 120344f0eee88ff00398ff7f715fab053374d808c90dSteve Block IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); 12049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ TailCallExternalReference(ref, 5, 1); 12055913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 12066ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12076ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 12109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (kind_ == Code::KEYED_CALL_IC) { 12113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rcx, name); 12129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, miss); 12139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 12149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12166ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 12209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label* miss) { 12219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(holder->IsGlobalObject()); 12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the number of arguments. 12249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 12259dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 12266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 12276ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 12286ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 12313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rdx, miss); 12329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); 12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell( 12373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 12409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the value from the cell. 12413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rdi, cell); 12429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); 124380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the cell contains the same function. 12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (heap()->InNewSpace(*function)) { 12469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // We can't embed a pointer to a function in new space so we have 12479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // to verify that the shared function info is unchanged. This has 12489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // the nice side effect that multiple closures based on the same 12499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // function can all use this call IC. Before we load through the 12509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // function, we have to verify that it still is a function. 12519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdi, miss); 12529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); 12539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, miss); 125480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check the shared function info. Make sure it hasn't changed. 12569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); 12579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); 125880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rdi, function); 126080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 12613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, miss); 12629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 126380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 126480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() { 12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), 1268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kind_, 12693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra_state_); 12703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 12717f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 12727f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12737f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12743ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, 12753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 12769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index, 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 127880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------- S t a t e ------------- 12799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx : function name 12809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[0] : return address 12819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[8] : argument argc 12829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[16] : argument argc - 1 12839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ... 12849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[argc * 8] : argument 1 12859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[(argc + 1) * 8] : argument 0 = receiver 128680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------------------------------- 128780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label miss; 12889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 128980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenerateNameCheck(name, &miss); 129080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the receiver from the stack. 12929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 12939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 129480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 12969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &miss); 129780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Do the right check and compute the holder register. 12999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi, 13009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name, &miss); 130180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 13029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateFastPropertyLoad(masm(), rdi, reg, holder, index); 130380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 13049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the function really is a function. 13059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdi, &miss); 13069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); 13079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 13089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 13099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Patch the receiver on the stack with the global proxy if 13109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // necessary. 13119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (object->IsGlobalObject()) { 13129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 13139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 13149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 13159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 13169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Invoke the function. 13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, 1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 13227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Handle call cache miss. 132480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&miss); 13253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 132680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 132780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return the generated code. 13289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(FIELD, name); 132980d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 13306ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall( 13333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 13343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 13353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 133859151504615d929945dc59db37bf1166937748c6Steve Block // ----------- S t a t e ------------- 13399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 134059151504615d929945dc59db37bf1166937748c6Steve Block // -- rsp[0] : return address 134159151504615d929945dc59db37bf1166937748c6Steve Block // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 134259151504615d929945dc59db37bf1166937748c6Steve Block // -- ... 134359151504615d929945dc59db37bf1166937748c6Steve Block // -- rsp[(argc + 1) * 8] : receiver 134459151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 134559151504615d929945dc59db37bf1166937748c6Steve Block 13469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If object is not an array, bail out to regular call. 13473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 134859151504615d929945dc59db37bf1166937748c6Steve Block 134959151504615d929945dc59db37bf1166937748c6Steve Block Label miss; 135059151504615d929945dc59db37bf1166937748c6Steve Block GenerateNameCheck(name, &miss); 135159151504615d929945dc59db37bf1166937748c6Steve Block 13529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the receiver from the stack. 13539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 13549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 135559151504615d929945dc59db37bf1166937748c6Steve Block 13569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 13579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &miss); 135859151504615d929945dc59db37bf1166937748c6Steve Block 13593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 13603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 13619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 13629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (argc == 0) { 13639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Noop, return the length. 13649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); 13659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 136659151504615d929945dc59db37bf1166937748c6Steve Block } else { 13679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label call_builtin; 136859151504615d929945dc59db37bf1166937748c6Steve Block 13693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (argc == 1) { // Otherwise fall through to call builtin. 13703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label attempt_to_grow_elements, with_write_barrier; 137159151504615d929945dc59db37bf1166937748c6Steve Block 13723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements array of the object. 13733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset)); 13745d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 13753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the elements are in fast mode and writable. 13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset), 13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch factory()->fixed_array_map()); 13783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &call_builtin); 13795d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 13809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the array's length into rax and calculate new length. 13819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset)); 13829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); 13839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ addl(rax, Immediate(argc)); 138459151504615d929945dc59db37bf1166937748c6Steve Block 13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements' length into rcx. 13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 138759151504615d929945dc59db37bf1166937748c6Steve Block 13889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check if we could survive without allocation. 13899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ cmpl(rax, rcx); 13909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(greater, &attempt_to_grow_elements); 13919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if value is a smi. 13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, Operand(rsp, argc * kPointerSize)); 13943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(rcx, &with_write_barrier); 13953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 13969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Save new length. 13979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); 13989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdi, 14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, 14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_pointer_size, 14033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - argc * kPointerSize), 14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rcx); 14059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Integer32ToSmi(rax, rax); // Return new length as smi. 140785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ ret((argc + 1) * kPointerSize); 14089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 140985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ bind(&with_write_barrier); 14109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); 14123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { 14143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_object, not_fast_object; 14153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(rbx, ¬_fast_object, Label::kNear); 14163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&fast_object); 14173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // In case of fast smi-only, convert to fast object, otherwise bail out. 14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_fast_object); 14193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastSmiOnlyElements(rbx, &call_builtin); 14203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: receiver 14213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rbx: map 14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(r9, rdi); // Backup rdi as it is going to be trashed. 14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_ELEMENTS, 14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rbx, 14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi, 14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_builtin); 14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm()); 14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, r9); 14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_object); 14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(rbx, &call_builtin); 14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save new length. 14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); 14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rdx, FieldOperand(rdi, 14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, times_pointer_size, 14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - argc * kPointerSize)); 14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(Operand(rdx, 0), rcx); 1443592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 1446592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Integer32ToSmi(rax, rax); // Return new length as smi. 14489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 14499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&attempt_to_grow_elements); 14519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!FLAG_inline_new) { 14529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ jmp(&call_builtin); 14539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 14549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, Operand(rsp, argc * kPointerSize)); 14563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Growing elements that are SMI-only requires special handling in case 14573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the new element is non-Smi. For now, delegate to the builtin. 14583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label no_fast_elements_check; 14593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rbx, &no_fast_elements_check); 14603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); 14613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); 14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&no_fast_elements_check); 14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ExternalReference new_space_allocation_top = 146544f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 14669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ExternalReference new_space_allocation_limit = 146744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 14689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int kAllocationDelta = 4; 14709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load top. 147144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Load(rcx, new_space_allocation_top); 14729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check if it's the end of elements. 14743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rdx, FieldOperand(rdi, 14759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block rax, times_pointer_size, 14769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block FixedArray::kHeaderSize - argc * kPointerSize)); 14779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ cmpq(rdx, rcx); 14789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &call_builtin); 14799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ addq(rcx, Immediate(kAllocationDelta * kPointerSize)); 148044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand limit_operand = 148144f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->ExternalOperand(new_space_allocation_limit); 148244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpq(rcx, limit_operand); 14839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(above, &call_builtin); 14849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // We fit and could grow elements. 148644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Store(new_space_allocation_top, rcx); 14879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Push the argument... 14893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(Operand(rdx, 0), rbx); 14909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ... and fill the rest with holes. 14919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 14929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = 1; i < kAllocationDelta; i++) { 14939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rdx, i * kPointerSize), kScratchRegister); 14949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 14959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We know the elements array is in new space so we don't need the 14973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // remembered set, but we just pushed a value onto it so we may have to 14983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // tell the incremental marker to rescan the object that we just grew. We 14993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // don't need to worry about the holes because they are in old space and 15003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // already marked black. 15013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); 15023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Restore receiver to rdx as finish sequence assumes it's here. 15049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 15059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 15069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Increment element's and array's sizes. 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset), 15089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Smi::FromInt(kAllocationDelta)); 15099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 15109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Make new length a smi before returning it. 15119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Integer32ToSmi(rax, rax); 15129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); 15139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 15149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 15159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 15169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 15179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&call_builtin); 151844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, 151944f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()), 15209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block argc + 1, 15219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 1); 15229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 152359151504615d929945dc59db37bf1166937748c6Steve Block 152459151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&miss); 15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 152659151504615d929945dc59db37bf1166937748c6Steve Block 152759151504615d929945dc59db37bf1166937748c6Steve Block // Return the generated code. 15289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(function); 15290d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 15300d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 15310d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall( 15333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 15343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 15353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 15363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 15373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1538f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------- S t a t e ------------- 15399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 1540f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- rsp[0] : return address 1541f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 1542f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ... 1543f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- rsp[(argc + 1) * 8] : receiver 1544f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------------------------------- 1545f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If object is not an array, bail out to regular call. 15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 1548f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss, return_undefined, call_builtin; 1550f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateNameCheck(name, &miss); 1551f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the receiver from the stack. 15539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 15549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1555f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 15579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &miss); 1558f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 1561f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the elements array of the object. 15639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); 1564f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the elements are in fast mode and writable. 15669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 15679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Heap::kFixedArrayMapRootIndex); 15689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &call_builtin); 1569f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the array's length into rcx and calculate new length. 15719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 15729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ subl(rcx, Immediate(1)); 15739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(negative, &return_undefined); 1574f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the last element. 15769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(r9, Heap::kTheHoleValueRootIndex); 15779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rax, FieldOperand(rbx, 15789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block rcx, times_pointer_size, 15799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block FixedArray::kHeaderSize)); 15809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check if element is already the hole. 15819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ cmpq(rax, r9); 15829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If so, call slow-case to also check prototypes for value. 15839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(equal, &call_builtin); 1584f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Set the array's length. 15869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx); 1587f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Fill with the hole and return original value. 15899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(FieldOperand(rbx, 15909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block rcx, times_pointer_size, 15919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block FixedArray::kHeaderSize), 15929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block r9); 15939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 1594f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&return_undefined); 15969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 15979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 1598f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&call_builtin); 160044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference( 160144f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(Builtins::c_ArrayPop, isolate()), 160244f0eee88ff00398ff7f715fab053374d808c90dSteve Block argc + 1, 160344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 1604f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1605f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&miss); 16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1607f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1608f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Return the generated code. 16099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(function); 1610f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 1611f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1612f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall( 16143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 16153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 16163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 16173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 16183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1619a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 16209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : function name 16219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 16229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 16239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- ... 16249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc + 1) * 8] : receiver 1625a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If object is not a string, bail out to regular call. 16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 16299dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1630a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1631a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 1633b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 16349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label index_out_of_range; 1635b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 1636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 16373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1639b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1641b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 1642a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps starting from the prototype haven't changed. 16449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateDirectLoadGlobalFunctionPrototype(masm(), 16459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Context::STRING_FUNCTION_INDEX, 16469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block rax, 16479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block &miss); 16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 16493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 16503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, holder, rbx, rdx, rdi, name, &miss); 1651a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register receiver = rbx; 16539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register index = rdi; 16549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register result = rax; 16559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); 16569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (argc > 0) { 16579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); 16589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 16599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 16609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 1661a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharCodeAtGenerator generator(receiver, 16633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 16643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 16653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 16663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 16673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 16683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 16709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 1671a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block StubRuntimeCallHelper call_helper; 16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 1674a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1675b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1676b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 1677b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ LoadRoot(rax, Heap::kNanValueRootIndex); 1678b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ ret((argc + 1) * kPointerSize); 1679b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1680a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in rcx. 16833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rcx, name); 1684b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 16853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1686a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 16889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(function); 1689a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1690a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1691a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall( 16933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 16943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 16953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 16963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 16973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 16999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : function name 17009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 17019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 17029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- ... 17039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc + 1) * 8] : receiver 170459151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 170559151504615d929945dc59db37bf1166937748c6Steve Block 17069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If object is not a string, bail out to regular call. 17073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 17089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 17099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 1710a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1711b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 17129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label index_out_of_range; 1713b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 17153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1717b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1718b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1719b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 17209dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 17219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps starting from the prototype haven't changed. 17229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateDirectLoadGlobalFunctionPrototype(masm(), 17239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Context::STRING_FUNCTION_INDEX, 17249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block rax, 17259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block &miss); 17263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 17273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 17283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, holder, rbx, rdx, rdi, name, &miss); 1729a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register receiver = rax; 17319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register index = rdi; 17323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = rdx; 17339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register result = rax; 17349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); 17359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (argc > 0) { 17369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); 17379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 17389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 1739a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1740a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharAtGenerator generator(receiver, 17423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 17433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 17443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 17453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 17463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 17473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 17483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 17493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 17509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 17519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 17529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block StubRuntimeCallHelper call_helper; 17533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 1754a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1755b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1756b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 1757b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ LoadRoot(rax, Heap::kEmptyStringRootIndex); 1758b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ ret((argc + 1) * kPointerSize); 1759b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1760a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1761b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in rcx. 17623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rcx, name); 1763b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 17643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1765a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1766a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 17679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(function); 1768a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1769a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1770a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall( 17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 17733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 17789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : function name 17799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 17809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 17819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- ... 17829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc + 1) * 8] : receiver 1783a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the object is not a JSObject or we got an unexpected number of 17869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // arguments, bail out to the regular call. 17873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int argc = arguments().immediate(); 17883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 1789a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 17919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateNameCheck(name, &miss); 1792a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 17949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 17959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &miss); 17963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 17973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 17989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 17993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 18003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 18013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 18029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 18039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 1804a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load the char code argument. 18069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register code = rbx; 18079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(code, Operand(rsp, 1 * kPointerSize)); 18086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check the code is a smi. 18109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label slow; 18119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfNotSmi(code, &slow); 18126ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Convert the smi code to uint16. 18149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); 18156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharFromCodeGenerator generator(code, rax); 18173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 18189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(2 * kPointerSize); 18196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block StubRuntimeCallHelper call_helper; 18213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 18229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 18239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Tail call the full function. We do not have to patch the receiver 18249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // because the function makes no use of it. 18259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&slow); 18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 1830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 18316ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18326ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 18339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx: function name. 18343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 18356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 18373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 18386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 18396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18413ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall( 18423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 18433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 18453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 18463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 18479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // TODO(872): implement this. 18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 1849a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1850a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1851a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall( 18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 18543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 18599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : function name 18609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 18619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 18629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- ... 18639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc + 1) * 8] : receiver 1864a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 18659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 18669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the object is not a JSObject or we got an unexpected number of 18679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // arguments, bail out to the regular call. 18683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int argc = arguments().immediate(); 18693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 18709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 18729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateNameCheck(name, &miss); 1873a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 18759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 18769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &miss); 18773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 18799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 18803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 18823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 18839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 18849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 18859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load the (only) argument into rax. 18869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rax, Operand(rsp, 1 * kPointerSize)); 1887a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check if the argument is a smi. 18899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label not_smi; 18909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block STATIC_ASSERT(kSmiTag == 0); 18919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfNotSmi(rax, ¬_smi); 18929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ SmiToInteger32(rax, rax); 1893a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 18959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // otherwise. 18969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movl(rbx, rax); 18979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ sarl(rbx, Immediate(kBitsPerInt - 1)); 1898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Do bitwise not or do nothing depending on ebx. 19009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ xorl(rax, rbx); 1901a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Add 1 or do nothing depending on ebx. 19039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ subl(rax, rbx); 19049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 19059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the result is still negative, go to the slow case. 19069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // This only happens for the most negative smi. 19079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label slow; 19089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(negative, &slow); 19099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 19109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Smi case done. 19119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Integer32ToSmi(rax, rax); 19129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(2 * kPointerSize); 19139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 19149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check if the argument is a heap number and load its value. 19159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(¬_smi); 1916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); 19179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset)); 1918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check the sign of the argument. If the argument is positive, 19209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // just return it. 19219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label negative_sign; 19229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int sign_mask_shift = 19239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte; 19249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift, 19259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block RelocInfo::NONE); 19269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ testq(rbx, rdi); 19279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_zero, &negative_sign); 19289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(2 * kPointerSize); 1929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the argument is negative, clear the sign, and return a new 19319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // number. We still have the sign mask in rdi. 19329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&negative_sign); 19339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ xor_(rbx, rdi); 19349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ AllocateHeapNumber(rax, rdx, &slow); 19359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx); 19369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(2 * kPointerSize); 1937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Tail call the full function. We do not have to patch the receiver 19399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // because the function makes no use of it. 19409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&slow); 19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 1945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 1946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 19489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx: function name. 19493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 19523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall( 195744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const CallOptimization& optimization, 19583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 19613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 19623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 196344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(optimization.is_simple_api_call()); 196444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bail out if object is a global object as we don't want to 196544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // repatch it to global receiver. 19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsGlobalObject()) return Handle<Code>::null(); 19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!cell.is_null()) return Handle<Code>::null(); 19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject()) return Handle<Code>::null(); 196944f0eee88ff00398ff7f715fab053374d808c90dSteve Block int depth = optimization.GetPrototypeDepthOfExpectedType( 19703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>::cast(object), holder); 19713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 197244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 197344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss, miss_before_stack_reserved; 197444f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss_before_stack_reserved); 197544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 197644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get the receiver from the stack. 197744f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int argc = arguments().immediate(); 197844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 197944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 198044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the receiver isn't a smi. 198144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfSmi(rdx, &miss_before_stack_reserved); 198244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 198344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 198444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const(), 1); 198544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_fast_api(), 1); 198644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 198744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Allocate space for v8::Arguments implicit values. Must be initialized 198844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // before calling any runtime function. 198944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 199044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 199144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the maps haven't changed and find a Holder as a side effect. 19923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth, &miss); 199444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 199544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Move the return address on top of the stack. 199644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(rax, Operand(rsp, 3 * kPointerSize)); 199744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(Operand(rsp, 0 * kPointerSize), rax); 199844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiCall(masm(), optimization, argc); 200044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 200144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss); 200244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 200344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 200444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss_before_stack_reserved); 20053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 200644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 200744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return the generated code. 200844f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetCode(function); 200944f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 201044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 201144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, 20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 20169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block CheckType check) { 2017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 20189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx : function name 20199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[0] : return address 20209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[8] : argument argc 20219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[16] : argument argc - 1 20229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ... 20239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[argc * 8] : argument 1 20249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[(argc + 1) * 8] : argument 0 = receiver 2025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 202744f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 20283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, 20293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell>::null(), 20303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, name); 20313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 20330d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 2034e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 203544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss; 203644f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss); 2037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the receiver from the stack. 20399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 20409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 2041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 20439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (check != NUMBER_CHECK) { 204444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfSmi(rdx, &miss); 20459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 2046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Make sure that it's okay not to patch the on stack receiver 20489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // unless we're doing a receiver map check. 20499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 205144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 20529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block switch (check) { 20539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block case RECEIVER_MAP_CHECK: 205444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const(), 1); 2055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 20573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, 20583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi, name, &miss); 2059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Patch the receiver on the stack with the global proxy if 20619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // necessary. 20629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (object->IsGlobalObject()) { 20639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 20649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 20659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 20669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block break; 2067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block case STRING_CHECK: 20693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 20709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the object is a two-byte string or a symbol. 20719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); 20729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(above_equal, &miss); 20739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps starting from the prototype haven't changed. 20749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateDirectLoadGlobalFunctionPrototype( 20759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); 20763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 20773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 20783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, holder, rbx, rdx, rdi, name, &miss); 20793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 208085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 208185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 208285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 20833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case NUMBER_CHECK: 20873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 20889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label fast; 20899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the object is a smi or a heap number. 20909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &fast); 20919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); 20929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 20939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&fast); 20949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps starting from the prototype haven't changed. 20959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateDirectLoadGlobalFunctionPrototype( 20969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); 20973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 20983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 20993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, holder, rbx, rdx, rdi, name, &miss); 21003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 210185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 210285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 210385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 21043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 21063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case BOOLEAN_CHECK: 21083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 21099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label fast; 21109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the object is a boolean. 21119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CompareRoot(rdx, Heap::kTrueValueRootIndex); 21129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(equal, &fast); 21139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CompareRoot(rdx, Heap::kFalseValueRootIndex); 21149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 21159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&fast); 21169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps starting from the prototype haven't changed. 21179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateDirectLoadGlobalFunctionPrototype( 21189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); 21193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 21203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 21213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, holder, rbx, rdx, rdi, name, &miss); 21223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 21233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calling non-strict non-builtins with a value as the receiver 21243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // requires boxing. 21253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 21269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 21279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block break; 21289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 2129a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 2135a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Handle call cache miss. 2137a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 21383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2139a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2140a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 21419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(function); 2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2143a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, 21463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 21473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2148a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 21499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx : function name 21509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[0] : return address 21519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[8] : argument argc 21529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[16] : argument argc - 1 21539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ... 21549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[argc * 8] : argument 1 21559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[(argc + 1) * 8] : argument 0 = receiver 2156a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2157a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 21589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateNameCheck(name, &miss); 2159a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the number of arguments. 21619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 2162a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 21659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the receiver from the stack. 21679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 21689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); 21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, 21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 21729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Restore receiver. 21749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 21759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the function really is a function. 21779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rax, &miss); 21789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 21799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 21809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Patch the receiver on the stack with the global proxy if 21829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // necessary. 21839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (object->IsGlobalObject()) { 21849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 21859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 21869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 21879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Invoke the function. 21899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdi, rax); 21903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, 2194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 21959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Handle load cache miss. 2197a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 21983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2199a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2200a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2201a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2202a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2203a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22053ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal( 22063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 22073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 22083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 22093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 22103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 22129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx : function name 22139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[0] : return address 22149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[8] : argument argc 22159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[16] : argument argc - 1 22169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ... 22179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[argc * 8] : argument 1 22189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[(argc + 1) * 8] : argument 0 = receiver 2219a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 22209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 222144f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 22223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); 22233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 22243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 22259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 22269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 2227a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 22289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateNameCheck(name, &miss); 2229a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the number of arguments. 22319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 22329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateGlobalReceiverCheck(object, holder, name, &miss); 22339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 22349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 22359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Patch the receiver on the stack with the global proxy. 22369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (object->IsGlobalObject()) { 22379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 22389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 22399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 22409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the context (function already in rdi). 22429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 22439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 22449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Jump to the cached code (tail call). 224544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 224644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline(), 1); 22479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ParameterCount expected(function->shared()->formal_parameter_count()); 22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We call indirectly through the code field in the function to 22523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allow recompilation to take effect without changing any of the 22533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // call sites. 22543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, 22563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NullCallWrapper(), call_kind); 22573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Handle call cache miss. 2259a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 226044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline_miss(), 1); 22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2262a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2263a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 22649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(NORMAL, name); 2265a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2267a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, 22699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index, 22703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 22713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2272b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 22739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : value 22749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 2275b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- rdx : receiver 22769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 2277b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 2278b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label miss; 2279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Generate store field code. Preserves receiver and name on jump to miss. 22813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss); 2282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Handle store cache miss. 2284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 228544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 22869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2287b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2288b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return the generated code. 22893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2290b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2292b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22933ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback( 22943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 22953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2297a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2298a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rax : value 2299a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rcx : name 23004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- rdx : receiver 2301a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 2302a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2303a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 23063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(rdx, Handle<Map>(object->map()), &miss, 23073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 23114515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(rdx, rbx, &miss); 2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2313a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2314a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2318a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rbx); // remove the return address 23199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(rdx); // receiver 23203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(callback); // callback info 23219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(rcx); // name 23229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(rax); // value 23239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(rbx); // restore return address 23249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Do tail-call to the runtime system. 23269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ExternalReference store_callback_property = 232744f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 23289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ TailCallExternalReference(store_callback_property, 4, 1); 2329a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2330a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2331a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 233244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2333a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2334a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2335a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 23369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2339a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor( 23413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 23423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2343a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rax : value 2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rcx : name 23464515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- rdx : receiver 2347a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 2348a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2349a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 23523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, 23533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (receiver->IsJSGlobalProxy()) { 23574515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(rdx, rbx, &miss); 2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2359a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2360a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2364a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rbx); // remove the return address 23654515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdx); // receiver 2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rcx); // name 2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rax); // value 2368e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(strict_mode_)); 2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rbx); // restore return address 2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2372a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_ic_property = 237344f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); 2374e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ TailCallExternalReference(store_ic_property, 4, 1); 2375a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 237844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2380a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2381a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2385a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal( 23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> object, 23883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 23893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rax : value 2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rcx : name 23934515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- rdx : receiver 2394a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 2395a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2396a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 23994515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2400a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Map>(object->map())); 2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the cell operand to use. 24043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rbx, cell); 24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset); 24063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 24071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the value in the cell is not the hole. If it is, this 24081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // cell could have been deleted and reintroducing the global needs 24091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to update the property details in the property dictionary of the 24101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // global object. We bail out to the runtime system to do that. 24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(cell_operand, Heap::kTheHoleValueRootIndex); 24121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, &miss); 24131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2414a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the value in the cell. 24153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(cell_operand, rax); 24163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cells are always rescanned, so no write barrier here. 2417a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2418a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register rax). 241944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 242044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline(), 1); 2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2422a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2423a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 242544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline_miss(), 1); 242644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2427a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2432a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2433a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24343ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, 24355913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 24363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 24373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rax : value 2440f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- rcx : key 2441f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- rdx : receiver 2442a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 2443a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2444a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 244644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 244744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_store_field(), 1); 2448a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 24503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rcx, name); 2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2453402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Generate store field code. Preserves receiver and name on jump to miss. 24543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss); 2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2457a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 245844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_store_field(), 1); 245944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2460a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2461a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 24633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2465a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2466a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement( 24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 2469b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 2470b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- rax : value 2471b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- rcx : key 2472b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- rdx : receiver 2473b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- rsp[0] : return address 2474b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2476589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 2477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 24793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode(); 24803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 24813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); 2482b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 2485b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 2488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2490b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 24913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( 24923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 24933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_stubs, 24943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* transitioned_maps) { 2495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : value 2497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rcx : key 2498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 2499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 2500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 25023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rdx, &miss, Label::kNear); 2503b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 25043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset)); 2505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 25063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < receiver_count; ++i) { 2507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check map and tail call if there's a match 25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rdi, receiver_maps->at(i)); 25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_maps->at(i).is_null()) { 25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET); 25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label next_map; 25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &next_map, Label::kNear); 25143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, transitioned_maps->at(i), RelocInfo::EMBEDDED_OBJECT); 25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); 25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&next_map); 25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2518b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2519b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2520b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 252144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2522e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 2523e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2524e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Return the generated code. 25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 2526e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2527e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2528e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 25293ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, 25303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 25313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> last) { 25329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 25339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 25349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 25359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 25369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 25379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 25387f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that receiver is not a smi. 25409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rax, &miss); 25417f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check the maps of the full prototype chain. Also check that 25439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // global property cells up to (but not including) the last object 25449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // in the prototype chain are empty. 25459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); 25469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the last object in the prototype chain is a global object, 25489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // check that the global property cell is empty. 25499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (last->IsGlobalObject()) { 25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell( 25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm(), Handle<GlobalObject>::cast(last), name, rdx, &miss); 25527f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 25537f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return undefined if maps of the full prototype chain are still the 25559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // same and no global property with this name contains a value. 25569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 25579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(0); 25589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 25609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 25619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NONEXISTENT, factory()->empty_string()); 25649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 25659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, 25683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 25699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index, 25703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 25719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 25729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 25739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 25749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 25759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 25769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 25779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss); 25799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 25809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 25819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 25839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(FIELD, name); 25849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 25859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25873ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback( 25883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 25893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 25903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 25913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 25929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 25939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 25949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 25959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 25969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 25979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, rdi, callback, 25993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 26009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 26019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 26029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 26049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 26059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 26069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26083ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, 26093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 26103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 26113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 26129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 26139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 26149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 26159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 26169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 26179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 26189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss); 26209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 26219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 26229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 26249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CONSTANT_FUNCTION, name); 26259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 26269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26283ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, 26293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 26303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 26319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 26329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 26339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 26349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 26359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 26369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 26389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block LookupPostInterceptor(holder, name, &lookup); 26399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // TODO(368): Compile in the whole chain: all the interceptors in 26419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // prototypes and ultimate answer. 26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, rax, rcx, rdx, rbx, rdi, 26433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 26449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 26459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 26469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 26489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(INTERCEPTOR, name); 26499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 26509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal( 26533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 26543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 26553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 26563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 26573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_dont_delete) { 26589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 26599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 26609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 26619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 26629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 26639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 26649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 26663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rax, &miss); 26679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss); 26689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the value from the cell. 26703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rbx, cell); 26719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); 26729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check for deleted property if property can actually be deleted. 26749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!is_dont_delete) { 26759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 26769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(equal, &miss); 26779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else if (FLAG_debug_code) { 26789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 26799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Check(not_equal, "DontDelete cells can't contain the hole"); 26809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 26819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 268244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 268344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub(), 1); 26849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rax, rbx); 26859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(0); 26869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 268844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub_miss(), 1); 26899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 26907f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 26919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 26929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(NORMAL, name); 26939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 26947f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 26957f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 26963ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, 26973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 26983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 26999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index) { 27009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 27019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 27029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 27039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 27049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 27059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 27067f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 270744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 270844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_field(), 1); 27097f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 27113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 27129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 27137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss); 27157f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 271744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_field(), 1); 27189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 27197f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 27219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(FIELD, name); 27229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 27237f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27247f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback( 27263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 27273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 27283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 27309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 27319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 27329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 27339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 27349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 27359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 273644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 273744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_callback(), 1); 2738a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 27419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 2742a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi, callback, 27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 27459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 274644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_callback(), 1); 27479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2748bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 27499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 27509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 27519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 27528a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2753bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 27543ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant( 27553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 27563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 27573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value) { 27599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 27609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 27619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 27629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 27639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 27649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 2765bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 276644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 276744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_constant_function(), 1); 2768bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 27699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 27703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 27719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 27728a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 27739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi, 27749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block value, name, &miss); 27759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 277644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_constant_function(), 1); 27779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 27788a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 27799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 27809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CONSTANT_FUNCTION, name); 27819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 27828a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 27838a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 27843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( 27853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 27863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 27889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 27899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 27909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 27919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 27929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 27939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 279444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 279544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_interceptor(), 1); 27968a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 27979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 27983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 27999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 28009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 28013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 28029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block LookupPostInterceptor(holder, name, &lookup); 28033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, rdx, rax, rcx, rbx, rdi, 28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 28059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 280644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_interceptor(), 1); 28079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 28089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 28099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 28109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(INTERCEPTOR, name); 2811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2812a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2813a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28143ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( 28153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 28169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 28179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 28189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 28199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 28209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 28219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 28223bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 282344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 282444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_array_length(), 1); 28253bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 28273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 28289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 28293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadArrayLength(masm(), rdx, rcx, &miss); 28319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 283244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_array_length(), 1); 28339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 28343bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 28369fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 28379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 28383bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28393bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( 28413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 28429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 28439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 28449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 28459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 28469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 28479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 28483bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 284944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 285044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_string_length(), 1); 28513bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 28533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 28549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 28553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true); 28579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 285844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_string_length(), 1); 28599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 28603bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 28629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 28639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 28643bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28653bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28663ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( 28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 28689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 28699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 28709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 28719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 28729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 28739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 28743bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 287544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 287644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_function_prototype(), 1); 2877a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 28793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 28809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 2881a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); 28839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 288444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 28859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 28869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 28879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 28889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 2889a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2890a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2891a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement( 28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 28949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 28959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 28969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 289744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // -- rsp[0] : return address 28989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 2899589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); 29013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); 2903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); 2905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 2906a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2910a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2911a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29123ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( 29133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 29143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_ics) { 2915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : key 2917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 2918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 2919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(rdx, &miss); 2922a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register map_reg = rbx; 2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset)); 2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 2926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int current = 0; current < receiver_count; ++current) { 2927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check map and tail call if there's a match 29283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(map_reg, receiver_maps->at(current)); 29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, handler_ics->at(current), RelocInfo::CODE_TARGET); 2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 29319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 2932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 29339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 29349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 29359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 2937a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2938a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2939a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2940a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only 2941a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body. 29423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub( 29433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function) { 2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rax : argc 2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rdi : constructor 2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[4] : last argument 2949a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2950a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_stub_call; 2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use r8 for holding undefined which is used in several places below. 295344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(r8, factory()->undefined_value()); 2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check to see whether there are any break points in the function code. If 2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // there are jump to the generic constructor stub which calls the actual 2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code for the function thereby hitting the break points. 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 2960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kDebugInfoOffset)); 2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rbx, r8); 2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &generic_stub_call); 2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Will both indicate a NULL and a Smi. 296869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ JumpIfSmi(rbx, &generic_stub_call); 2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(rbx, MAP_TYPE, rcx); 2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &generic_stub_call); 2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cannot construct functions this way. 2975a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdi: constructor 2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx: initial map 2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpInstanceType(rbx, JS_FUNCTION_TYPE); 2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(not_equal, "Function constructed by construct stub."); 2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject in new space. 2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdi: constructor 2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx: initial map 2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset)); 2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shl(rcx, Immediate(kPointerSizeLog2)); 29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(rcx, rdx, rcx, no_reg, 29873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &generic_stub_call, NO_ALLOCATION_FLAGS); 2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields and add the heap tag. 2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx: initial map 2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx: JSObject (untagged) 2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rdx, JSObject::kMapOffset), rbx); 299344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(rbx, factory()->empty_fixed_array()); 2994a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rdx, JSObject::kPropertiesOffset), rbx); 2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rdx, JSObject::kElementsOffset), rbx); 2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax: argc 2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx: JSObject (untagged) 2999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the address of the first in-object property into r9. 3000a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r9, Operand(rdx, JSObject::kHeaderSize)); 3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the first argument. The stack contains only the 3002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return address on top of the argc arguments. 3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rcx, Operand(rsp, rax, times_pointer_size, 0)); 3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax: argc 3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rcx: first argument 3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx: JSObject (untagged) 3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r8: undefined 3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r9: first in-object property of the JSObject 3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the initialized properties with a constant value or a passed argument 3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // depending on the this.x = ...; assignment in the function. 30123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> shared(function->shared()); 3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < shared->this_property_assignments_count(); i++) { 3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shared->IsThisPropertyAssignmentArgument(i)) { 3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the argument assigned to the property is actually passed. 3016e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If argument is not passed the property is set to undefined, 3017e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // otherwise find it on the stack. 3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int arg_number = shared->GetThisPropertyAssignmentArgument(i); 3019e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rbx, r8); 3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rax, Immediate(arg_number)); 3021e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmovq(above, rbx, Operand(rcx, arg_number * -kPointerSize)); 3022e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store value in the property. 3023a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(r9, i * kPointerSize), rbx); 3024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 3025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to the constant value. 3026a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Move(Operand(r9, i * kPointerSize), constant); 3028a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3029a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the unused in-object property fields with undefined. 30328a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(function->has_initial_map()); 3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = shared->this_property_assignments_count(); 30348a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang i < function->initial_map()->inobject_properties(); 3035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i++) { 3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(r9, i * kPointerSize), r8); 3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3039a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax: argc 3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx: JSObject (untagged) 3041a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move argc to rbx and the JSObject to return to rax and tag it. 3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, rax); 3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, rdx); 3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(rax, Immediate(kHeapObjectTag)); 3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax: JSObject 3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx: argc 3048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack and return. 3049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rcx); 3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rsp, Operand(rsp, rbx, times_pointer_size, 1 * kPointerSize)); 3051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rcx); 305244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects(), 1); 305444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects_stub(), 1); 3055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic stub in case the specialized code cannot handle the 3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // construction. 3059a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_stub_call); 30603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric(); 30613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 3062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(); 3065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3067a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __ 30693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm) 30703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 30713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 30723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement( 30733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 30741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 30751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rax : key 30761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rdx : receiver 30771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rsp[0] : return address 30781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 30793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label slow, miss_force_generic; 3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 30813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 30823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 30831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 30843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(rax, &miss_force_generic); 30853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger32(rbx, rax); 30863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 30871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 30883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check whether the elements is a number dictionary. 30893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rdx: receiver 30903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rax: key 30913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rbx: key as untagged int32 30923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rcx: elements 30933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax); 30943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 30953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 30963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow); 3097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 30983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rax : key 3099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 31003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rsp[0] : return address 3101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 31023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 31033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 31043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(slow_ic, RelocInfo::CODE_TARGET); 3105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 31063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 31073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 31083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rax : key 31093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rdx : receiver 31103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rsp[0] : return address 31113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 31123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 31133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 31143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray( 3118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3119589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 3120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : key 3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow, miss_force_generic; 3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 3131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(rax, &miss_force_generic); 31321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 3134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); 31351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiToInteger32(rcx, rax); 313669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(rax, FieldOperand(rbx, ExternalArray::kLengthOffset)); 31371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 3138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 31391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rax: index (as a smi) 31411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rdx: receiver (JSObject) 31421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rcx: untagged index 31431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rbx: elements array 31441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 31451e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rbx: base pointer of external storage 31463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3147589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 31481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); 31491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3150589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3151589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 31521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0)); 31531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3154589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 31551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0)); 31561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3157589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 31581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0)); 31591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3160589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 31611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0)); 31621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3163589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 31641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movl(rcx, Operand(rbx, rcx, times_4, 0)); 31651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3166589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 31671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0)); 31681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3169589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(xmm0, Operand(rbx, rcx, times_8, 0)); 3171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 31721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 31731e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 31741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 31751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 31761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rax: index 31781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rdx: receiver 31791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For integer array types: 31801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rcx: value 31811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For floating-point array type: 31821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // xmm0: value as double. 31831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(kSmiValueSize == 32); 3185589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { 31861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the UnsignedInt array type, we need to see whether 31871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value can be represented in a Smi. If not, we need to convert 31881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // it to a HeapNumber. 3189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label box_int; 31901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear); 31921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Integer32ToSmi(rax, rcx); 31941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 31951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int); 31971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the int and perform int-to-double 31991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversion. 32001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The value is zero-extended since we loaded the value from memory 32011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // with movl. 32021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvtqsi2sd(xmm0, rcx); 32031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(rcx, rbx, &slow); 32051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the value. 32061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); 32071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, rcx); 32081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 3209589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || 3210589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 32111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the floating-point array type, we need to always allocate a 32121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // HeapNumber. 32131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(rcx, rbx, &slow); 32141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the value. 32151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); 32161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, rcx); 32171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 32181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 32191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Integer32ToSmi(rax, rcx); 32201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 32211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 32221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case: Jump to runtime. 32241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 3225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 322644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 32271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 32291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rax : key 32301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rdx : receiver 32311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rsp[0] : return address 32321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 32331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); 3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 32361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss case: Jump to runtime. 3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 32391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : key 3242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 3243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 3244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 32481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 32491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray( 3252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3253589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 32541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 32551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rax : value 32561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rcx : key 32571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rdx : receiver 32581e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rsp[0] : return address 32591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 3260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow, miss_force_generic; 32611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 326444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 326544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the key is a smi. 3266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(rcx, &miss_force_generic); 32671e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); 32701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiToInteger32(rdi, rcx); // Untag the index. 327169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); 32721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 3273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 32741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 32761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // runtime for all other kinds of values. 32771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rax: value 32781e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rcx: key (a smi) 32791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rdx: receiver (a JSObject) 32801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rbx: elements array 32811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rdi: untagged key 3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check_heap_number; 3283589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { 328444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Float to pixel conversion is only implemented in the runtime for now. 328544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfNotSmi(rax, &slow); 328644f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 3287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(rax, &check_heap_number, Label::kNear); 328844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 32891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // No more branches to slow case on this path. Key and receiver not needed. 32901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiToInteger32(rdx, rax); 32911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 32921e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rbx: base pointer of external storage 32933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3294589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 329544f0eee88ff00398ff7f715fab053374d808c90dSteve Block { // Clamp the value to [0..255]. 3296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 329744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ testl(rdx, Immediate(0xFFFFFF00)); 3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &done, Label::kNear); 329944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ setcc(negative, rdx); // 1 if negative, 0 if positive. 330044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ decb(rdx); // 0 if negative, 255 if positive. 330144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 330244f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 330344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movb(Operand(rbx, rdi, times_1, 0), rdx); 330444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3305589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3306589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 33071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movb(Operand(rbx, rdi, times_1, 0), rdx); 33081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3309589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3310589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 33111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movw(Operand(rbx, rdi, times_2, 0), rdx); 33121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3313589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3314589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 33151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movl(Operand(rbx, rdi, times_4, 0), rdx); 33161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 33181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Need to perform int-to-float conversion. 33191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvtlsi2ss(xmm0, rdx); 33201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movss(Operand(rbx, rdi, times_4, 0), xmm0); 33211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3322589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Need to perform int-to-float conversion. 3324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvtlsi2sd(xmm0, rdx); 3325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); 3326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3327589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 33283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3330589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3331589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 33321e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 33331e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 33341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 33361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 333744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(danno): handle heap number -> pixel array conversion 3338589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { 333944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&check_heap_number); 334044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rax: value 334144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rcx: key (a smi) 334244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rdx: receiver (a JSObject) 334344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rbx: elements array 334444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rdi: untagged key 334544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister); 334644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &slow); 334744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // No more branches to slow case on this path. 334844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 334944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The WebGL specification leaves the behavior of storing NaN and 335044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // +/-Infinity into integer arrays basically undefined. For more 335144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // reproducible behavior, convert these to zero. 335244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); 335344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 33541e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rdi: untagged index 33551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rbx: base pointer of external storage 335644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // top of FPU stack: value 3357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 335844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvtsd2ss(xmm0, xmm0); 335944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movss(Operand(rbx, rdi, times_4, 0), xmm0); 336044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ret(0); 3361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); 3363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 336444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 336544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Perform float-to-int conversion with truncation (round-to-zero) 336644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // behavior. 336744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 336844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert to int32 and store the low byte/word. 336944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the value is NaN or +/-infinity, the result is 0x80000000, 337044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // which is automatically zero when taken mod 2^n, n < 32. 337144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rdx: value (converted to an untagged integer) 337244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rdi: untagged index 337344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rbx: base pointer of external storage 33743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3375589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3376589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 337744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvttsd2si(rdx, xmm0); 337844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movb(Operand(rbx, rdi, times_1, 0), rdx); 337944f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3380589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3381589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 338244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvttsd2si(rdx, xmm0); 338344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movw(Operand(rbx, rdi, times_2, 0), rdx); 338444f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3385589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3386589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 338744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert to int64, so that NaN and infinities become 338844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // 0x8000000000000000, which is zero mod 2^32. 338944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvttsd2siq(rdx, xmm0); 339044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(Operand(rbx, rdi, times_4, 0), rdx); 339144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3392589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3393589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3394589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3395589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 33963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3397589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3398589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 340044f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 340144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 34021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 340344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ret(0); 34041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case: call runtime. 34081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rax : value 34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rcx : key 34131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rdx : receiver 34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rsp[0] : return address 34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 3418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 3419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss case: call runtime. 3421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : value 3425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rcx : key 3426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 3427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 3428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { 3437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : key 3439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic; 34431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 34461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(rax, &miss_force_generic); 3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array. 3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AssertFastElements(rcx); 3453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); 3456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the result and make sure it's not the hole. 3459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2); 3460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rbx, FieldOperand(rcx, 3461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index.reg, 3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index.scale, 3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FixedArray::kHeaderSize)); 3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 3465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &miss_force_generic); 3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rax, rbx); 3467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Code* code = masm->isolate()->builtins()->builtin( 3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Builtins::kKeyedLoadIC_MissForceGeneric); 3472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic(code); 3473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 34773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( 34783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 34793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 34803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rax : key 34813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rdx : receiver 34823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rsp[0] : return address 34833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 34843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label miss_force_generic, slow_allocate_heapnumber; 34853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(rax, &miss_force_generic); 34913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 34933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 34943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AssertFastElements(rcx); 34953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 34973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); 34983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, &miss_force_generic); 34993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check for the hole 35013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger32(kScratchRegister, rax); 35023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); 35033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpl(FieldOperand(rcx, kScratchRegister, times_8, offset), 35043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Immediate(kHoleNanUpper32)); 35053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(equal, &miss_force_generic); 35063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Always allocate a heap number for the result. 35083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movsd(xmm0, FieldOperand(rcx, kScratchRegister, times_8, 35093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize)); 35103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber); 35113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Set the value. 35123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rax, rcx); 35133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); 35143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 35153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow_allocate_heapnumber); 35173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 35183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 35193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(slow_ic, RelocInfo::CODE_TARGET); 35203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 35223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 35233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 35243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 35253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 35263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement( 35293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 35303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 35313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind elements_kind, 35323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 3533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : value 3535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rcx : key 3536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 3537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 3538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 35393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, finish_store, grow; 35403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label check_capacity, slow; 3541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 3546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(rcx, &miss_force_generic); 3547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 35483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 35493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(rax, &transition_elements_kind); 35503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 35513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array and make sure it is a fast element array, not 'cow'. 3553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 3554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_js_array) { 3556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 35573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 35583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &grow); 35593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 35603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 35613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 35673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset), 35683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedArrayMapRootIndex); 35693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 35703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 35723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 35733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(rcx, rcx); 35743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize), 35753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax); 35763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 35773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do the store and update the write barrier. 35783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(elements_kind == FAST_ELEMENTS); 35793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(rcx, rcx); 35803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rcx, 35813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize)); 35823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(Operand(rcx, 0), rax); 35833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure to preserve the value in register rax. 35843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, rax); 35853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(rdi, rcx, rbx, kDontSaveFPRegs); 35863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Done. 3589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle store cache miss. 3592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic_force_generic = 3594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 35963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 35983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 35993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_miss, RelocInfo::CODE_TARGET); 36003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 36023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array by a single element if possible. 36033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 36043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 36063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags are already set by previous 36073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compare. 36083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 36113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 36123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 36133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rdi, Heap::kEmptyFixedArrayRootIndex); 36143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &check_capacity); 36153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); 36173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT); 36183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: value 36203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: key 36213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: receiver 36223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: elements 36233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 36243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdi, JSObject::kMapOffset), 36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->factory()->fixed_array_map()); 36263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdi, FixedArray::kLengthOffset), 36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(JSArray::kPreallocatedArrayElements)); 36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rbx, Heap::kTheHoleValueRootIndex); 36293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) { 36303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdi, FixedArray::SizeFor(i)), rbx); 36313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 36323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the element at index zero. 36343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdi, FixedArray::SizeFor(0)), rax); 36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 36373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi); 36383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx, 36393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 36403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 36423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1)); 36433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 36443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 36463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for cow elements, in general they are not handled by this stub. 36473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset), 36483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedCOWArrayMapRootIndex); 36493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &miss_force_generic); 36503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: value 36523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: key 36533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: receiver 36543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: elements 36553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 36563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 36573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &slow); 36583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 36603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset), 36613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(1)); 36623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 36633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 36653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 36663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_slow, RelocInfo::CODE_TARGET); 36673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 36681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 36691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 36713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 36723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm, 36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 36753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 36763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rax : value 36773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rcx : key 36783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rdx : receiver 36793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rsp[0] : return address 36803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 36813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, finish_store; 36823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label grow, slow, check_capacity; 36833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 36853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 36863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 36883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(rcx, &miss_force_generic); 36893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 36913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 36923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AssertFastElements(rdi); 36933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 36953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_js_array) { 36963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 36973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 36983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &grow); 36993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 37003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 37013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 37033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset)); 37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 37053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 37063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Handle smi values specially 37083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger32(rcx, rcx); 37103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, 37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &transition_elements_kind); 37123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 37133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 37153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> ic_force_generic = 37173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 37183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 37193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 37213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore smi-tagging of rcx. 37223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Integer32ToSmi(rcx, rcx); 37233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 37243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_miss, RelocInfo::CODE_TARGET); 37253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array by a single element if possible. 37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 37313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags are already set by previous 37323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compare. 37333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Transition on values that can't be stored in a FixedDoubleArray. 37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label value_is_smi; 37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rax, &value_is_smi); 37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kHeapNumberMapRootIndex); 37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &transition_elements_kind); 37413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&value_is_smi); 37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 37453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rdi, Heap::kEmptyFixedArrayRootIndex); 37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &check_capacity); 37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements); 37503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT); 37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: value 37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: key 37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: receiver 37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: elements 37563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the new FixedDoubleArray. Leave elements unitialized for 37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // efficiency, they are guaranteed to be initialized before use. 37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdi, JSObject::kMapOffset), 37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->factory()->fixed_double_array_map()); 37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdi, FixedDoubleArray::kLengthOffset), 37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(JSArray::kPreallocatedArrayElements)); 37623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 37643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi); 37653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx, 37663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 37673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 37693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1)); 37709413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 37713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 37743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: value 37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: key 37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: receiver 37773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: elements 37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset)); 37803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &slow); 37813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 37833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset), 37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(1)); 37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 37863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_slow, RelocInfo::CODE_TARGET); 37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 37923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3794a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 3795a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 3797f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3798f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 3799