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 11075710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // Preserve the receiver register explicitly whenever it is different from 11085710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // the holder and it is needed should the interceptor return without any 11095710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // result. The CALLBACKS case needs the receiver to be passed into C++ code, 11105710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch // the FIELD case might cause a miss during the prototype check. 11115710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch bool must_perfrom_prototype_check = *interceptor_holder != lookup->holder(); 11125710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch bool must_preserve_receiver_reg = !receiver.is(holder_reg) && 11135710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch (lookup->type() == CALLBACKS || must_perfrom_prototype_check); 11145710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch 11159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Save necessary data before invoking an interceptor. 11169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Requires a frame to make GC aware of pushed pointers. 11173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 11183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 11196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11205710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch if (must_preserve_receiver_reg) { 11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(receiver); 11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(holder_reg); 11243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ push(name_reg); 1125592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 11263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 11273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // interceptor's holder has been compiled before (see a caller 11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of this method.) 11293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm(), 11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_reg, 11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder); 11343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if interceptor provided a value for property. If it's 11363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the case, return immediately. 11373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label interceptor_failed; 11383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rax, Heap::kNoInterceptorResultSentinelRootIndex); 11393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &interceptor_failed); 11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_scope.GenerateLeaveFrame(); 11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 11423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&interceptor_failed); 11443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_reg); 11453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(holder_reg); 11465710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch if (must_preserve_receiver_reg) { 11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); 11483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 11496ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 11513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 115285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 11539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps from interceptor's holder to lookup's holder 11549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // haven't changed. And load lookup's holder into |holder| register. 11555710ceac03e2cf7a164ad7393b5a6b6114ea45e6Ben Murdoch if (must_perfrom_prototype_check) { 11569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block holder_reg = CheckPrototypes(interceptor_holder, 11579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block holder_reg, 11583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 11599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block scratch1, 11609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block scratch2, 11619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block scratch3, 11629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name, 11639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block miss); 11649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 11656ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 11669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (lookup->type() == FIELD) { 11679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // We found FIELD property in prototype chain of interceptor's holder. 11689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Retrieve a field from field's holder. 11699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateFastPropertyLoad(masm(), rax, holder_reg, 11703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 11713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetFieldIndex()); 11729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(0); 11739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 11749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // We found CALLBACKS property in prototype chain of interceptor's 11759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // holder. 11769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(lookup->type() == CALLBACKS); 11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback( 11783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())); 11799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(callback->getter() != NULL); 1180756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 11819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Tail call to runtime. 11829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Important invariant in CALLBACKS case: the code above must be 11839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // structured to never clobber |receiver| register. 11849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ pop(scratch2); // return address 11859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(receiver); 11869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(holder_reg); 11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(holder_reg, callback); 11889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(FieldOperand(holder_reg, AccessorInfo::kDataOffset)); 11899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(holder_reg); 11909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(name_reg); 11919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(scratch2); // restore return address 1192756813857a4c2a4d8ad2e805969d5768d3cf43a0Iain Merrick 11939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ExternalReference ref = 119444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kLoadCallbackProperty), 119544f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()); 11969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ TailCallExternalReference(ref, 5, 1); 11976ded16be15dd865a9b21ea304d5273c8be299c87Steve Block } 11989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { // !compile_followup_inline 11999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Call the runtime system to load the interceptor. 12009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 12019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 12029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block scratch1, scratch2, scratch3, 12039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name, miss); 12049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ pop(scratch2); // save old return address 12059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block PushInterceptorArguments(masm(), receiver, holder_reg, 12069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name_reg, interceptor_holder); 12079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(scratch2); // restore old return address 12086ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ExternalReference ref = ExternalReference( 121044f0eee88ff00398ff7f715fab053374d808c90dSteve Block IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), isolate()); 12119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ TailCallExternalReference(ref, 5, 1); 12125913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck } 12136ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12146ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 12179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (kind_ == Code::KEYED_CALL_IC) { 12183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rcx, name); 12199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, miss); 12209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 12219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 12226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12236ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 12253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 12263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 12279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label* miss) { 12289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(holder->IsGlobalObject()); 12296ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the number of arguments. 12319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 12329dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 12336ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Get the receiver from the stack. 12346ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 12356ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12366ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 12383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rdx, miss); 12399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block CheckPrototypes(object, rdx, holder, rbx, rax, rdi, name, miss); 12406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 12416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 12433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell( 12443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 12453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 12463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 12479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the value from the cell. 12483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rdi, cell); 12499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdi, FieldOperand(rdi, JSGlobalPropertyCell::kValueOffset)); 125080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the cell contains the same function. 12523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (heap()->InNewSpace(*function)) { 12539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // We can't embed a pointer to a function in new space so we have 12549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // to verify that the shared function info is unchanged. This has 12559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // the nice side effect that multiple closures based on the same 12569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // function can all use this call IC. Before we load through the 12579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // function, we have to verify that it still is a function. 12589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdi, miss); 12599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rax); 12609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, miss); 126180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check the shared function info. Make sure it hasn't changed. 12639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Move(rax, Handle<SharedFunctionInfo>(function->shared())); 12649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ cmpq(FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset), rax); 126580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } else { 12663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rdi, function); 126780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen } 12683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, miss); 12699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 127080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 127180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() { 12733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), 1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kind_, 12763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra_state_); 12773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 12787f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch} 12797f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12807f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, 12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 12839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index, 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 128580d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------- S t a t e ------------- 12869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx : function name 12879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[0] : return address 12889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[8] : argument argc 12899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[16] : argument argc - 1 12909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ... 12919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[argc * 8] : argument 1 12929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[(argc + 1) * 8] : argument 0 = receiver 129380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // ----------------------------------- 129480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen Label miss; 12959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 129680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen GenerateNameCheck(name, &miss); 129780d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 12989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the receiver from the stack. 12999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 13009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 130180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 13029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 13039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &miss); 130480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 13059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Do the right check and compute the holder register. 13069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register reg = CheckPrototypes(object, rdx, holder, rbx, rax, rdi, 13079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block name, &miss); 130880d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 13099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateFastPropertyLoad(masm(), rdi, reg, holder, index); 131080d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 13119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the function really is a function. 13129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdi, &miss); 13139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(rdi, JS_FUNCTION_TYPE, rbx); 13149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 13159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 13169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Patch the receiver on the stack with the global proxy if 13179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // necessary. 13189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (object->IsGlobalObject()) { 13199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 13209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 13219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 13229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 13239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Invoke the function. 13243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, 1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 13297f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 13309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Handle call cache miss. 133180d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen __ bind(&miss); 13323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 133380d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen 133480d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen // Return the generated code. 13359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(FIELD, name); 133680d68eab642096c1a48b6474d6ec33064b0ad1f5Kristian Monsen} 13376ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall( 13403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 13413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 13423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 13443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 134559151504615d929945dc59db37bf1166937748c6Steve Block // ----------- S t a t e ------------- 13469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 134759151504615d929945dc59db37bf1166937748c6Steve Block // -- rsp[0] : return address 134859151504615d929945dc59db37bf1166937748c6Steve Block // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 134959151504615d929945dc59db37bf1166937748c6Steve Block // -- ... 135059151504615d929945dc59db37bf1166937748c6Steve Block // -- rsp[(argc + 1) * 8] : receiver 135159151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 135259151504615d929945dc59db37bf1166937748c6Steve Block 13539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If object is not an array, bail out to regular call. 13543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 135559151504615d929945dc59db37bf1166937748c6Steve Block 135659151504615d929945dc59db37bf1166937748c6Steve Block Label miss; 135759151504615d929945dc59db37bf1166937748c6Steve Block GenerateNameCheck(name, &miss); 135859151504615d929945dc59db37bf1166937748c6Steve Block 13599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the receiver from the stack. 13609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 13619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 136259151504615d929945dc59db37bf1166937748c6Steve Block 13639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 13649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &miss); 136559151504615d929945dc59db37bf1166937748c6Steve Block 13663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 13673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 13689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 13699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (argc == 0) { 13709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Noop, return the length. 13719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rax, FieldOperand(rdx, JSArray::kLengthOffset)); 13729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 137359151504615d929945dc59db37bf1166937748c6Steve Block } else { 13749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label call_builtin; 137559151504615d929945dc59db37bf1166937748c6Steve Block 13763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (argc == 1) { // Otherwise fall through to call builtin. 13773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label attempt_to_grow_elements, with_write_barrier; 137859151504615d929945dc59db37bf1166937748c6Steve Block 13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements array of the object. 13803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, FieldOperand(rdx, JSArray::kElementsOffset)); 13815d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 13823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the elements are in fast mode and writable. 13833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(FieldOperand(rdi, HeapObject::kMapOffset), 13843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch factory()->fixed_array_map()); 13853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &call_builtin); 13865d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 13879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the array's length into rax and calculate new length. 13889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ SmiToInteger32(rax, FieldOperand(rdx, JSArray::kLengthOffset)); 13899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block STATIC_ASSERT(FixedArray::kMaxLength < Smi::kMaxValue); 13909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ addl(rax, Immediate(argc)); 139159151504615d929945dc59db37bf1166937748c6Steve Block 13923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements' length into rcx. 13933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 139459151504615d929945dc59db37bf1166937748c6Steve Block 13959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check if we could survive without allocation. 13969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ cmpl(rax, rcx); 13979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(greater, &attempt_to_grow_elements); 13989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if value is a smi. 14003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, Operand(rsp, argc * kPointerSize)); 14013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(rcx, &with_write_barrier); 14023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Save new length. 14049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); 14059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdi, 14083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, 14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch times_pointer_size, 14103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - argc * kPointerSize), 14113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rcx); 14129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Integer32ToSmi(rax, rax); // Return new length as smi. 141485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ ret((argc + 1) * kPointerSize); 14159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 141685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ bind(&with_write_barrier); 14179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, FieldOperand(rdx, HeapObject::kMapOffset)); 14193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { 14213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_object, not_fast_object; 14223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(rbx, ¬_fast_object, Label::kNear); 14233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&fast_object); 14243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // In case of fast smi-only, convert to fast object, otherwise bail out. 14253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_fast_object); 14263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastSmiOnlyElements(rbx, &call_builtin); 14273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: receiver 14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rbx: map 14293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(r9, rdi); // Backup rdi as it is going to be trashed. 14303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 14313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_ELEMENTS, 14323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rbx, 14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi, 14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_builtin); 14353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm()); 14363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, r9); 14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_object); 14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 14393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(rbx, &call_builtin); 14403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 14413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save new length. 14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rax); 14443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 14463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rdx, FieldOperand(rdi, 14473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, times_pointer_size, 14483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FixedArray::kHeaderSize - argc * kPointerSize)); 14493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(Operand(rdx, 0), rcx); 1450592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 14513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(rdi, rdx, rcx, kDontSaveFPRegs, EMIT_REMEMBERED_SET, 14523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 1453592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch 14543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Integer32ToSmi(rax, rax); // Return new length as smi. 14559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 14569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&attempt_to_grow_elements); 14589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!FLAG_inline_new) { 14599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ jmp(&call_builtin); 14609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 14619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, Operand(rsp, argc * kPointerSize)); 14633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Growing elements that are SMI-only requires special handling in case 14643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the new element is non-Smi. For now, delegate to the builtin. 14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label no_fast_elements_check; 14663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rbx, &no_fast_elements_check); 14673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rcx, FieldOperand(rdx, HeapObject::kMapOffset)); 14683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(rcx, &call_builtin, Label::kFar); 14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&no_fast_elements_check); 14703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 14719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ExternalReference new_space_allocation_top = 147244f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_top_address(isolate()); 14739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ExternalReference new_space_allocation_limit = 147444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference::new_space_allocation_limit_address(isolate()); 14759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int kAllocationDelta = 4; 14779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load top. 147844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Load(rcx, new_space_allocation_top); 14799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check if it's the end of elements. 14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rdx, FieldOperand(rdi, 14829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block rax, times_pointer_size, 14839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block FixedArray::kHeaderSize - argc * kPointerSize)); 14849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ cmpq(rdx, rcx); 14859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &call_builtin); 14869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ addq(rcx, Immediate(kAllocationDelta * kPointerSize)); 148744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Operand limit_operand = 148844f0eee88ff00398ff7f715fab053374d808c90dSteve Block masm()->ExternalOperand(new_space_allocation_limit); 148944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cmpq(rcx, limit_operand); 14909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(above, &call_builtin); 14919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // We fit and could grow elements. 149344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Store(new_space_allocation_top, rcx); 14949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 14959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Push the argument... 14963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(Operand(rdx, 0), rbx); 14979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ... and fill the rest with holes. 14989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(kScratchRegister, Heap::kTheHoleValueRootIndex); 14999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block for (int i = 1; i < kAllocationDelta; i++) { 15009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rdx, i * kPointerSize), kScratchRegister); 15019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 15029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 15033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We know the elements array is in new space so we don't need the 15043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // remembered set, but we just pushed a value onto it so we may have to 15053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // tell the incremental marker to rescan the object that we just grew. We 15063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // don't need to worry about the holes because they are in old space and 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // already marked black. 15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(rdi, rdx, rbx, kDontSaveFPRegs, OMIT_REMEMBERED_SET); 15093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Restore receiver to rdx as finish sequence assumes it's here. 15119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 15129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 15139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Increment element's and array's sizes. 15143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiAddConstant(FieldOperand(rdi, FixedArray::kLengthOffset), 15159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Smi::FromInt(kAllocationDelta)); 15169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 15179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Make new length a smi before returning it. 15189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Integer32ToSmi(rax, rax); 15199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(FieldOperand(rdx, JSArray::kLengthOffset), rax); 15209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 15219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 15229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 15239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 15249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&call_builtin); 152544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, 152644f0eee88ff00398ff7f715fab053374d808c90dSteve Block isolate()), 15279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block argc + 1, 15289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 1); 15299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 153059151504615d929945dc59db37bf1166937748c6Steve Block 153159151504615d929945dc59db37bf1166937748c6Steve Block __ bind(&miss); 15323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 153359151504615d929945dc59db37bf1166937748c6Steve Block 153459151504615d929945dc59db37bf1166937748c6Steve Block // Return the generated code. 15359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(function); 15360d5e116f6aee03185f237311a943491bb079a768Kristian Monsen} 15370d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 15380d5e116f6aee03185f237311a943491bb079a768Kristian Monsen 15393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall( 15403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 15413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 15423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 15433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1545f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------- S t a t e ------------- 15469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 1547f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- rsp[0] : return address 1548f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 1549f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- ... 1550f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // -- rsp[(argc + 1) * 8] : receiver 1551f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // ----------------------------------- 1552f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If object is not an array, bail out to regular call. 15543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 1555f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss, return_undefined, call_builtin; 1557f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch GenerateNameCheck(name, &miss); 1558f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the receiver from the stack. 15609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 15619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 1562f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 15649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &miss); 1565f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 1568f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the elements array of the object. 15709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rbx, FieldOperand(rdx, JSArray::kElementsOffset)); 1571f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the elements are in fast mode and writable. 15739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CompareRoot(FieldOperand(rbx, HeapObject::kMapOffset), 15749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Heap::kFixedArrayMapRootIndex); 15759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &call_builtin); 1576f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the array's length into rcx and calculate new length. 15789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ SmiToInteger32(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 15799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ subl(rcx, Immediate(1)); 15809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(negative, &return_undefined); 1581f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the last element. 15839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(r9, Heap::kTheHoleValueRootIndex); 15849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rax, FieldOperand(rbx, 15859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block rcx, times_pointer_size, 15869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block FixedArray::kHeaderSize)); 15879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check if element is already the hole. 15889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ cmpq(rax, r9); 15899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If so, call slow-case to also check prototypes for value. 15909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(equal, &call_builtin); 1591f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Set the array's length. 15939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Integer32ToSmiField(FieldOperand(rdx, JSArray::kLengthOffset), rcx); 1594f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 15959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Fill with the hole and return original value. 15969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(FieldOperand(rbx, 15979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block rcx, times_pointer_size, 15989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block FixedArray::kHeaderSize), 15999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block r9); 16009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 1601f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 16029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&return_undefined); 16039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 16049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 1605f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 16069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&call_builtin); 160744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ TailCallExternalReference( 160844f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(Builtins::c_ArrayPop, isolate()), 160944f0eee88ff00398ff7f715fab053374d808c90dSteve Block argc + 1, 161044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 1); 1611f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1612f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch __ bind(&miss); 16133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1614f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1615f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch // Return the generated code. 16169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(function); 1617f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch} 1618f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 1619f87a203d89e1bbb6708282e0b64dbd13d59b723dBen Murdoch 16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall( 16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1626a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 16279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : function name 16289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 16299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 16309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- ... 16319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc + 1) * 8] : receiver 1632a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1633a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If object is not a string, bail out to regular call. 16353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 16369dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 1637a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block const int argc = arguments().immediate(); 1638a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 1640b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 16419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label index_out_of_range; 1642b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 1643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 16443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1646b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1647b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1648b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 1649a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps starting from the prototype haven't changed. 16519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateDirectLoadGlobalFunctionPrototype(masm(), 16529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Context::STRING_FUNCTION_INDEX, 16539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block rax, 16549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block &miss); 16553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 16573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, holder, rbx, rdx, rdi, name, &miss); 1658a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register receiver = rbx; 16609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register index = rdi; 16619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register result = rax; 16629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); 16639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (argc > 0) { 16649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); 16659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 16669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 16679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 1668a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharCodeAtGenerator generator(receiver, 16703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 16713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 16723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 16733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 16743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 16753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 16763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 16779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 1678a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block StubRuntimeCallHelper call_helper; 16803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 1681a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1682b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1683b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 1684b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ LoadRoot(rax, Heap::kNanValueRootIndex); 1685b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ ret((argc + 1) * kPointerSize); 1686b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1687a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1688a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1689b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in rcx. 16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rcx, name); 1691b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 16923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1693a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1694a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 16959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(function); 1696a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1697a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1698a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 16993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall( 17003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 17023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 17033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 17043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1705a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 17069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : function name 17079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 17089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 17099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- ... 17109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc + 1) * 8] : receiver 171159151504615d929945dc59db37bf1166937748c6Steve Block // ----------------------------------- 171259151504615d929945dc59db37bf1166937748c6Steve Block 17139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If object is not a string, bail out to regular call. 17143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 17159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 17169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 1717a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 1718b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label name_miss; 17199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label index_out_of_range; 1720b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 17223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1724b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch index_out_of_range_label = &miss; 1725b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1726b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch GenerateNameCheck(name, &name_miss); 17279dcf7e2f83591d471e88bf7d230651900b8e424bKristian Monsen 17289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps starting from the prototype haven't changed. 17299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateDirectLoadGlobalFunctionPrototype(masm(), 17309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Context::STRING_FUNCTION_INDEX, 17319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block rax, 17329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block &miss); 17333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 17343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 17353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, holder, rbx, rdx, rdi, name, &miss); 1736a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register receiver = rax; 17389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register index = rdi; 17393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = rdx; 17409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register result = rax; 17419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(receiver, Operand(rsp, (argc + 1) * kPointerSize)); 17429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (argc > 0) { 17439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(index, Operand(rsp, (argc - 0) * kPointerSize)); 17449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 17459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 1746a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 1747a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharAtGenerator generator(receiver, 17493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 17503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 17513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 17523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 17533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 17543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 17553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 17563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 17579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret((argc + 1) * kPointerSize); 17589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 17599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block StubRuntimeCallHelper call_helper; 17603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 1761a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1762b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch if (index_out_of_range.is_linked()) { 1763b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&index_out_of_range); 1764b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ LoadRoot(rax, Heap::kEmptyStringRootIndex); 1765b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ ret((argc + 1) * kPointerSize); 1766b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch } 1767a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 1768b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch // Restore function name in rcx. 17693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rcx, name); 1770b8e0da25ee8efac3bb05cd6b2730aafbd96119f4Ben Murdoch __ bind(&name_miss); 17713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1772a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1773a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 17749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(function); 1775a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1776a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1777a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17783ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall( 17793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 17803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 17813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 17823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 17833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1784a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 17859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : function name 17869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 17879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 17889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- ... 17899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc + 1) * 8] : receiver 1790a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 1791a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 17929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the object is not a JSObject or we got an unexpected number of 17939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // arguments, bail out to the regular call. 17943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int argc = arguments().immediate(); 17953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 1796a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1797a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 17989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateNameCheck(name, &miss); 1799a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 18019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 18029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &miss); 18033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 18043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 18059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 18063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 18073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 18083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 18099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 18109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 1811a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load the char code argument. 18139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Register code = rbx; 18149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(code, Operand(rsp, 1 * kPointerSize)); 18156ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check the code is a smi. 18179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label slow; 18189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfNotSmi(code, &slow); 18196ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Convert the smi code to uint16. 18219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ SmiAndConstant(code, code, Smi::FromInt(0xffff)); 18226ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharFromCodeGenerator generator(code, rax); 18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 18259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(2 * kPointerSize); 18266ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block StubRuntimeCallHelper call_helper; 18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 18299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 18309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Tail call the full function. We do not have to patch the receiver 18319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // because the function makes no use of it. 18329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&slow); 18333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 1837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 18386ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block __ bind(&miss); 18409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx: function name. 18413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 18426ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18436ded16be15dd865a9b21ea304d5273c8be299c87Steve Block // Return the generated code. 18443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 18456ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 18466ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18476ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall( 18493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 18503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 18513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 18523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 18533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 18549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // TODO(872): implement this. 18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 1856a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1857a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1858a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall( 18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 18613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 18623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 18633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 18643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1865a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 18669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : function name 18679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 18689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc - n) * 8] : arg[n] (zero-based) 18699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- ... 18709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[(argc + 1) * 8] : receiver 1871a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 18729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 18739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the object is not a JSObject or we got an unexpected number of 18749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // arguments, bail out to the regular call. 18753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int argc = arguments().immediate(); 18763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 18779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 1878a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 18799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateNameCheck(name, &miss); 1880a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 18829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, 2 * kPointerSize)); 18839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &miss); 18843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 18853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 18869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else { 18873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 18883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 18909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 18919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 18929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Load the (only) argument into rax. 18939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rax, Operand(rsp, 1 * kPointerSize)); 1894a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 18959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check if the argument is a smi. 18969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label not_smi; 18979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block STATIC_ASSERT(kSmiTag == 0); 18989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfNotSmi(rax, ¬_smi); 18999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ SmiToInteger32(rax, rax); 1900a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Set ebx to 1...1 (== -1) if the argument is negative, or to 0...0 19029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // otherwise. 19039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movl(rbx, rax); 19049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ sarl(rbx, Immediate(kBitsPerInt - 1)); 1905a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Do bitwise not or do nothing depending on ebx. 19079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ xorl(rax, rbx); 1908a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Add 1 or do nothing depending on ebx. 19109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ subl(rax, rbx); 19119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 19129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the result is still negative, go to the slow case. 19139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // This only happens for the most negative smi. 19149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label slow; 19159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(negative, &slow); 19169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 19179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Smi case done. 19189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Integer32ToSmi(rax, rax); 19199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(2 * kPointerSize); 19209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 19219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check if the argument is a heap number and load its value. 19229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(¬_smi); 1923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(rax, factory()->heap_number_map(), &slow, DONT_DO_SMI_CHECK); 19249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rbx, FieldOperand(rax, HeapNumber::kValueOffset)); 1925a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check the sign of the argument. If the argument is positive, 19279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // just return it. 19289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label negative_sign; 19299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int sign_mask_shift = 19309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block (HeapNumber::kExponentOffset - HeapNumber::kValueOffset) * kBitsPerByte; 19319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdi, static_cast<int64_t>(HeapNumber::kSignMask) << sign_mask_shift, 19329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block RelocInfo::NONE); 19339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ testq(rbx, rdi); 19349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_zero, &negative_sign); 19359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(2 * kPointerSize); 1936a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the argument is negative, clear the sign, and return a new 19389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // number. We still have the sign mask in rdi. 19399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&negative_sign); 19409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ xor_(rbx, rdi); 19419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ AllocateHeapNumber(rax, rdx, &slow); 19429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(FieldOperand(rax, HeapNumber::kValueOffset), rbx); 19439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(2 * kPointerSize); 1944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Tail call the full function. We do not have to patch the receiver 19469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // because the function makes no use of it. 19479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&slow); 19483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 1949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 1950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 1951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 1952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 1953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 19559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx: function name. 19563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 19593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 1960a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 1961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 1962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 19633ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall( 196444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const CallOptimization& optimization, 19653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 19683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 197044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ASSERT(optimization.is_simple_api_call()); 197144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Bail out if object is a global object as we don't want to 197244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // repatch it to global receiver. 19733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsGlobalObject()) return Handle<Code>::null(); 19743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!cell.is_null()) return Handle<Code>::null(); 19753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject()) return Handle<Code>::null(); 197644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int depth = optimization.GetPrototypeDepthOfExpectedType( 19773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>::cast(object), holder); 19783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 197944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 198044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss, miss_before_stack_reserved; 198144f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss_before_stack_reserved); 198244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 198344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Get the receiver from the stack. 198444f0eee88ff00398ff7f715fab053374d808c90dSteve Block const int argc = arguments().immediate(); 198544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 198644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 198744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the receiver isn't a smi. 198844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfSmi(rdx, &miss_before_stack_reserved); 198944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 199044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 199144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const(), 1); 199244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const_fast_api(), 1); 199344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 199444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Allocate space for v8::Arguments implicit values. Must be initialized 199544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // before calling any runtime function. 199644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ subq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 199744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 199844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the maps haven't changed and find a Holder as a side effect. 19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, rdi, 20003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth, &miss); 200144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 200244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Move the return address on top of the stack. 200344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(rax, Operand(rsp, 3 * kPointerSize)); 200444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(Operand(rsp, 0 * kPointerSize), rax); 200544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiCall(masm(), optimization, argc); 200744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 200844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss); 200944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ addq(rsp, Immediate(kFastApiCallArguments * kPointerSize)); 201044f0eee88ff00398ff7f715fab053374d808c90dSteve Block 201144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&miss_before_stack_reserved); 20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 201344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 201444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Return the generated code. 201544f0eee88ff00398ff7f715fab053374d808c90dSteve Block return GetCode(function); 201644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 201744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 201844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 20193ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, 20203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 20213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 20223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 20239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block CheckType check) { 2024a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 20259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx : function name 20269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[0] : return address 20279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[8] : argument argc 20289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[16] : argument argc - 1 20299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ... 20309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[argc * 8] : argument 1 20319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[(argc + 1) * 8] : argument 0 = receiver 2032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 203444f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 20353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, 20363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell>::null(), 20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, name); 20383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 20393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 20400d5e116f6aee03185f237311a943491bb079a768Kristian Monsen } 2041e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke 204244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label miss; 204344f0eee88ff00398ff7f715fab053374d808c90dSteve Block GenerateNameCheck(name, &miss); 2044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the receiver from the stack. 20469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 20479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 2048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the receiver isn't a smi. 20509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (check != NUMBER_CHECK) { 205144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfSmi(rdx, &miss); 20529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 2053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Make sure that it's okay not to patch the on stack receiver 20559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // unless we're doing a receiver map check. 20569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 205844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 20599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block switch (check) { 20609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block case RECEIVER_MAP_CHECK: 206144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_const(), 1); 2062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 20643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), rdx, holder, rbx, rax, 20653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rdi, name, &miss); 2066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Patch the receiver on the stack with the global proxy if 20689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // necessary. 20699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (object->IsGlobalObject()) { 20709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 20719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 20729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 20739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block break; 2074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 20759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block case STRING_CHECK: 20763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 20779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the object is a two-byte string or a symbol. 20789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(rdx, FIRST_NONSTRING_TYPE, rax); 20799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(above_equal, &miss); 20809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps starting from the prototype haven't changed. 20819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateDirectLoadGlobalFunctionPrototype( 20829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block masm(), Context::STRING_FUNCTION_INDEX, rax, &miss); 20833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 20843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 20853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, holder, rbx, rdx, rdi, name, &miss); 20863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 208785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 208885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 208985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 20903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 20913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 20923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 20933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case NUMBER_CHECK: 20943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 20959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label fast; 20969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the object is a smi or a heap number. 20979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rdx, &fast); 20989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(rdx, HEAP_NUMBER_TYPE, rax); 20999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 21009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&fast); 21019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps starting from the prototype haven't changed. 21029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateDirectLoadGlobalFunctionPrototype( 21039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block masm(), Context::NUMBER_FUNCTION_INDEX, rax, &miss); 21043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 21053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 21063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, holder, rbx, rdx, rdi, name, &miss); 21073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 210885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 210985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 211085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 21113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 21123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 21133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 21143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case BOOLEAN_CHECK: 21153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 21169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label fast; 21179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the object is a boolean. 21189fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CompareRoot(rdx, Heap::kTrueValueRootIndex); 21199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(equal, &fast); 21209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CompareRoot(rdx, Heap::kFalseValueRootIndex); 21219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 21229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&fast); 21239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps starting from the prototype haven't changed. 21249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateDirectLoadGlobalFunctionPrototype( 21259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block masm(), Context::BOOLEAN_FUNCTION_INDEX, rax, &miss); 21263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 21273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 21283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax, holder, rbx, rdx, rdi, name, &miss); 21293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 21303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calling non-strict non-builtins with a value as the receiver 21313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // requires boxing. 21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 21339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 21349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block break; 21359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 2136a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(function, arguments(), JUMP_FUNCTION, 2141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 2142a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Handle call cache miss. 2144a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2146a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2147a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 21489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(function); 2149a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2150a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2151a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21523ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, 21533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 21543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2155a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 21569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx : function name 21579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[0] : return address 21589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[8] : argument argc 21599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[16] : argument argc - 1 21609fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ... 21619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[argc * 8] : argument 1 21629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[(argc + 1) * 8] : argument 0 = receiver 2163a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2164a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 21659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateNameCheck(name, &miss); 2166a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the number of arguments. 21689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 2169a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2171a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block LookupPostInterceptor(holder, name, &lookup); 21729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the receiver from the stack. 21749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 21759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallInterceptorCompiler compiler(this, arguments(), rcx, extra_state_); 21773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compiler.Compile(masm(), object, holder, name, &lookup, rdx, rbx, rdi, rax, 21783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 21799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Restore receiver. 21819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, Operand(rsp, (argc + 1) * kPointerSize)); 21829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the function really is a function. 21849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rax, &miss); 21859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CmpObjectType(rax, JS_FUNCTION_TYPE, rbx); 21869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 21879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Patch the receiver on the stack with the global proxy if 21899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // necessary. 21909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (object->IsGlobalObject()) { 21919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 21929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 21939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 21949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 21959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Invoke the function. 21969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdi, rax); 21973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 2200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(rdi, arguments(), JUMP_FUNCTION, 2201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch NullCallWrapper(), call_kind); 22029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 22039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Handle load cache miss. 2204a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 22053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2206a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2207a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2208a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2209a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2210a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2211a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22123ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal( 22133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 22143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 22153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 22163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 22173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2218a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 22199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rcx : function name 22209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[0] : return address 22219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[8] : argument argc 22229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[16] : argument argc - 1 22239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ... 22249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[argc * 8] : argument 1 22259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // rsp[(argc + 1) * 8] : argument 0 = receiver 2226a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 22279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 222844f0eee88ff00398ff7f715fab053374d808c90dSteve Block if (HasCustomCallGenerator(function)) { 22293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); 22303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 22313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 22329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 22339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 2234a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 22359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateNameCheck(name, &miss); 2236a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the number of arguments. 22389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block const int argc = arguments().immediate(); 22399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateGlobalReceiverCheck(object, holder, name, &miss); 22409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadFunctionFromCell(cell, function, &miss); 22419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 22429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Patch the receiver on the stack with the global proxy. 22439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (object->IsGlobalObject()) { 22449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rdx, FieldOperand(rdx, GlobalObject::kGlobalReceiverOffset)); 22459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(Operand(rsp, (argc + 1) * kPointerSize), rdx); 22469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 22479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the context (function already in rdi). 22499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rsi, FieldOperand(rdi, JSFunction::kContextOffset)); 22509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 22519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Jump to the cached code (tail call). 225244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 225344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline(), 1); 22549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ParameterCount expected(function->shared()->formal_parameter_count()); 22553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We call indirectly through the code field in the function to 22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allow recompilation to take effect without changing any of the 22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // call sites. 22613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdx, FieldOperand(rdi, JSFunction::kCodeEntryOffset)); 22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeCode(rdx, expected, arguments(), JUMP_FUNCTION, 22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NullCallWrapper(), call_kind); 22643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 22659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Handle call cache miss. 2266a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 226744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->call_global_inline_miss(), 1); 22683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2269a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2270a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 22719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(NORMAL, name); 2272a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2273a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2274a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 22753ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, 22769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index, 22773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 22783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2279b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 22809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : value 22819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 2282b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- rdx : receiver 22839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 2284b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 2285b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch Label miss; 2286b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Generate store field code. Preserves receiver and name on jump to miss. 22883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss); 2289b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 22909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Handle store cache miss. 2291b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 229244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 22939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2294b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2295b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // Return the generated code. 22963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2297b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch} 2298b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2299b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback( 23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 23023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 23033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2304a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2305a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rax : value 2306a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rcx : name 23074515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- rdx : receiver 2308a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 2309a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2310a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2311a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2312a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 23133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(rdx, Handle<Map>(object->map()), &miss, 23143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2315a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2316a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2317a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (object->IsJSGlobalProxy()) { 23184515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(rdx, rbx, &miss); 2319a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2320a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2321a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2322a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2323a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2324a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2325a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rbx); // remove the return address 23269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(rdx); // receiver 23273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(callback); // callback info 23289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(rcx); // name 23299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(rax); // value 23309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ push(rbx); // restore return address 23319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 23329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Do tail-call to the runtime system. 23339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block ExternalReference store_callback_property = 233444f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreCallbackProperty), isolate()); 23359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ TailCallExternalReference(store_callback_property, 4, 1); 2336a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2337a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2338a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 233944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2340a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2341a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2342a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 23439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 2344a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2345a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2346a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor( 23483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2350a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2351a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rax : value 2352a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rcx : name 23534515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- rdx : receiver 2354a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 2355a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2356a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2357a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2358a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the object hasn't changed. 23593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(rdx, Handle<Map>(receiver->map()), &miss, 23603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2361a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2362a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Perform global security token check if needed. 2363a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (receiver->IsJSGlobalProxy()) { 23644515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ CheckAccessGlobalProxy(rdx, rbx, &miss); 2365a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 2366a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2367a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Stub never generated for non-global objects that require access 2368a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // checks. 2369a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2370a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2371a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rbx); // remove the return address 23724515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ push(rdx); // receiver 2373a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rcx); // name 2374a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rax); // value 2375e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ Push(Smi::FromInt(strict_mode_)); 2376a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rbx); // restore return address 2377a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2378a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Do tail-call to the runtime system. 2379a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block ExternalReference store_ic_property = 238044f0eee88ff00398ff7f715fab053374d808c90dSteve Block ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), isolate()); 2381e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ TailCallExternalReference(store_ic_property, 4, 1); 2382a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2383a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2384a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 238544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2386a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2387a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2388a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2389a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(INTERCEPTOR, name); 2390a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2391a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2392a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 23933ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal( 23943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> object, 23953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 23963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2397a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2398a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rax : value 2399a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rcx : name 24004515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke // -- rdx : receiver 2401a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 2402a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2403a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2404a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2405a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the map of the global has not changed. 24064515c472dc3e5ed2448a564600976759e569a0a8Leon Clarke __ Cmp(FieldOperand(rdx, HeapObject::kMapOffset), 2407a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Map>(object->map())); 2408a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 2409a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Compute the cell operand to use. 24113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rbx, cell); 24123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand cell_operand = FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset); 24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 24141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the value in the cell is not the hole. If it is, this 24151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // cell could have been deleted and reintroducing the global needs 24161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // to update the property details in the property dictionary of the 24171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // global object. We bail out to the runtime system to do that. 24183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(cell_operand, Heap::kTheHoleValueRootIndex); 24191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ j(equal, &miss); 24201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 2421a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Store the value in the cell. 24223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(cell_operand, rax); 24233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cells are always rescanned, so no write barrier here. 2424a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2425a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the value (register rax). 242644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 242744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline(), 1); 2428a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 2429a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2430a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2431a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 243244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_store_global_inline_miss(), 1); 243344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->StoreIC_Miss(); 2434a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2435a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2436a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 2437a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(NORMAL, name); 2438a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2439a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2440a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24413ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, 24425913587db4c6bab03d97bfe44b06289fd6d7270dJohn Reck int index, 24433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 24443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2445a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2446a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rax : value 2447f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- rcx : key 2448f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke // -- rdx : receiver 2449a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 2450a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2451a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label miss; 2452a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 245344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 245444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_store_field(), 1); 2455a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2456a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check that the name has not changed. 24573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rcx, name); 2458a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &miss); 2459a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2460402d937239b0e2fd11bf2f4fe972ad78aa9fd481Andrei Popescu // Generate store field code. Preserves receiver and name on jump to miss. 24613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, rdx, rcx, rbx, &miss); 2462a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2463a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Handle store cache miss. 2464a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&miss); 246544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_store_field(), 1); 246644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2467a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Jump(ic, RelocInfo::CODE_TARGET); 2468a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2469a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 2471a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2472a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2473a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 24743ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement( 24753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 2476b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------- S t a t e ------------- 2477b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- rax : value 2478b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- rcx : key 2479b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- rdx : receiver 2480b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // -- rsp[0] : return address 2481b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch // ----------------------------------- 24823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2483589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 2484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 24853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 24863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode(); 24873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 24883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); 2489b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 2492b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 24943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 2495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2496b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2497b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 24983ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( 24993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 25003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_stubs, 25013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* transitioned_maps) { 2502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : value 2504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rcx : key 2505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 2506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 2507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rdx, &miss, Label::kNear); 2510b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, FieldOperand(rdx, HeapObject::kMapOffset)); 2512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < receiver_count; ++i) { 2514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check map and tail call if there's a match 25153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rdi, receiver_maps->at(i)); 25163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_maps->at(i).is_null()) { 25173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, handler_stubs->at(i), RelocInfo::CODE_TARGET); 25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 25193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label next_map; 25203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &next_map, Label::kNear); 25213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, transitioned_maps->at(i), RelocInfo::EMBEDDED_OBJECT); 25223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(handler_stubs->at(i), RelocInfo::CODE_TARGET); 25233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&next_map); 25243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 2525b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch } 2526b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch 2527b0fe1620dcb4135ac3ab2d66ff93072373911299Ben Murdoch __ bind(&miss); 252844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 2529e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 2530e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2531e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch // Return the generated code. 25323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 2533e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch} 2534e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 2535e0cee9b3ed82e2391fd85d118aeaa4ea361c687dBen Murdoch 25363ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, 25373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 25383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> last) { 25399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 25409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 25419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 25429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 25439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 25449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 25457f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 2546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that receiver is not a smi. 25479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ JumpIfSmi(rax, &miss); 25487f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check the maps of the full prototype chain. Also check that 25509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // global property cells up to (but not including) the last object 25519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // in the prototype chain are empty. 25529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block CheckPrototypes(object, rax, last, rbx, rdx, rdi, name, &miss); 25539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // If the last object in the prototype chain is a global object, 25559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // check that the global property cell is empty. 25569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (last->IsGlobalObject()) { 25573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell( 25583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm(), Handle<GlobalObject>::cast(last), name, rdx, &miss); 25597f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch } 25607f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 25619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return undefined if maps of the full prototype chain are still the 25629fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // same and no global property with this name contains a value. 25639fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ LoadRoot(rax, Heap::kUndefinedValueRootIndex); 25649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(0); 25659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 25679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 25689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 25703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NONEXISTENT, factory()->empty_string()); 25719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 25729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25739fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25743ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, 25753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 25769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index, 25773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 25789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 25799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 25809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 25819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 25829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 25839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 25849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadField(object, holder, rax, rbx, rdx, rdi, index, name, &miss); 25869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 25879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 25889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 25909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(FIELD, name); 25919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 25929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 25943ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback( 25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 25973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 25983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 25999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 26009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 26019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 26029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 26039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 26049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 26053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(object, holder, rax, rcx, rdx, rbx, rdi, callback, 26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 26079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 26089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 26099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 26119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 26129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 26139fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26153ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, 26163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 26173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 26183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 26199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 26209fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 26219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 26229fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 26239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 26249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 26259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadConstant(object, holder, rax, rbx, rdx, rdi, value, name, &miss); 26279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 26289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 26299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26309fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 26319fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CONSTANT_FUNCTION, name); 26329fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 26339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26349fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26353ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> receiver, 26363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 26373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 26389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 26399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 26409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 26419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 26429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 26439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 26443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 26459fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block LookupPostInterceptor(holder, name, &lookup); 26469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26479fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // TODO(368): Compile in the whole chain: all the interceptors in 26489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // prototypes and ultimate answer. 26493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, rax, rcx, rdx, rbx, rdi, 26503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 26519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 26529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 26539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 26559fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(INTERCEPTOR, name); 26569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 26579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal( 26603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 26613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 26623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 26633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 26643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_dont_delete) { 26659fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 26669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : receiver 26679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rcx : name 26689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 26699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 26709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 26719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26729fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the maps haven't changed. 26733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rax, &miss); 26749fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block CheckPrototypes(object, rax, holder, rbx, rdx, rdi, name, &miss); 26759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Get the value from the cell. 26773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(rbx, cell); 26789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rbx, FieldOperand(rbx, JSGlobalPropertyCell::kValueOffset)); 26799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check for deleted property if property can actually be deleted. 26819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block if (!is_dont_delete) { 26829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 26839fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(equal, &miss); 26849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } else if (FLAG_debug_code) { 26859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 26869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ Check(not_equal, "DontDelete cells can't contain the hole"); 26879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block } 26889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 268944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 269044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub(), 1); 26919fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ movq(rax, rbx); 26929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ ret(0); 26939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 26949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 269544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->named_load_global_stub_miss(), 1); 26969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::LOAD_IC); 26977f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 26989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 26999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(NORMAL, name); 27009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 27017f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27027f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, 27043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 27053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block int index) { 27079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 27089fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 27099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 27109fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 27119fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 27129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 27137f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 271444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 271544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_field(), 1); 27167f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 27199fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 27207f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27219fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadField(receiver, holder, rdx, rbx, rcx, rdi, index, name, &miss); 27227f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 272444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_field(), 1); 27259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 27267f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 27289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(FIELD, name); 27299fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 27307f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27317f4d5bd8c03935e2c0cd412e561b8fc5a6a880aeBen Murdoch 27323ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback( 27333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 27343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 27353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 27379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 27389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 27399fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 27409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 27419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 27429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 274344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 274444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_callback(), 1); 2745a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27469fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 27473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 27489fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 2749a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 27503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(receiver, holder, rdx, rax, rbx, rcx, rdi, callback, 27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 27529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 275344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_callback(), 1); 27549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2755bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 27569fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 27579fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 27589fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 27598a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 2760bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant( 27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value) { 27669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 27679fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 27689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 27699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 27709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 27719fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 2772bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 277344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 277444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_constant_function(), 1); 2775bb769b257e753aafcbd96767abb2abc645eaa20cBen Murdoch 27769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 27773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 27789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 27798a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 27809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadConstant(receiver, holder, rdx, rbx, rcx, rdi, 27819fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block value, name, &miss); 27829fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 278344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_constant_function(), 1); 27849fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 27858a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 27869fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 27879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CONSTANT_FUNCTION, name); 27889fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 27898a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 27908a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 27913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( 27923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 27933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 27959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 27969fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 27979fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 27989fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 27999fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 28009fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 280144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 280244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_interceptor(), 1); 28038a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang 28049fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 28069fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 28079fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 28099fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block LookupPostInterceptor(holder, name, &lookup); 28103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, rdx, rax, rcx, rbx, rdi, 28113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 28129fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 281344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_interceptor(), 1); 28149fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 28159fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 28169fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 28179fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(INTERCEPTOR, name); 2818a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2819a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2820a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28213ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( 28223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 28239fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 28249fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 28259fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 28269fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 28279fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 28289fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 28293bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 283044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 283144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_array_length(), 1); 28323bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28339fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 28343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 28359fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 28363bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28379fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadArrayLength(masm(), rdx, rcx, &miss); 28389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 283944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_array_length(), 1); 28409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 28413bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 28439fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 28449fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 28453bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28463bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28473ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( 28483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 28499fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 28509fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 28519fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 28529fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 28539fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 28549fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 28553bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 285644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 285744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_string_length(), 1); 28583bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28599fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 28603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 28619fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 28623bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block GenerateLoadStringLength(masm(), rdx, rcx, rbx, &miss, true); 28649fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 286544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_string_length(), 1); 28669fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 28673bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28689fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 28699fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 28709fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block} 28713bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28723bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 28733ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( 28743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 28759fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 28769fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 28779fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 28789fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rsp[0] : return address 28799fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 28809fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block Label miss; 28813bec4d28b1f388dbc06a9c4276e1a03e86c52b04Ben Murdoch 288244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 288344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_function_prototype(), 1); 2884a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28859fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Check that the name has not changed. 28863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(rax, name); 28879fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ j(not_equal, &miss); 2888a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28899fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadFunctionPrototype(masm(), rdx, rcx, rbx, &miss); 28909fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block __ bind(&miss); 289144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ DecrementCounter(counters->keyed_load_function_prototype(), 1); 28929fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 28939fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 28949fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 28959fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block return GetCode(CALLBACKS, name); 2896a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2897a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2898a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 28993ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement( 29003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 29019fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------- S t a t e ------------- 29029fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rax : key 29039fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // -- rdx : receiver 290444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // -- rsp[0] : return address 29059fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // ----------------------------------- 2906589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 29073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); 29083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 29093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(rdx, receiver_map, stub, DO_SMI_CHECK); 2910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); 2912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 2913a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 29153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 2916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 2917a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2918a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 29193ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( 29203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 29213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_ics) { 2922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : key 2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 2926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(rdx, &miss); 2929a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register map_reg = rbx; 2931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(map_reg, FieldOperand(rdx, HeapObject::kMapOffset)); 2932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 2933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int current = 0; current < receiver_count; ++current) { 2934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check map and tail call if there's a match 29353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Cmp(map_reg, receiver_maps->at(current)); 29363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, handler_ics->at(current), RelocInfo::CODE_TARGET); 2937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 29389fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 2939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 29409fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 29419fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block 29429fac840a46e8b7e26894f4792ba26dde14c56b04Steve Block // Return the generated code. 29433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 2944a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 2945a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2946a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2947a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// Specialized stub for constructing objects from functions which only have only 2948a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block// simple assignments of the form this.x = ...; in their body. 29493ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub( 29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function) { 2951a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------- S t a t e ------------- 2952a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rax : argc 2953a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rdi : constructor 2954a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[0] : return address 2955a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // -- rsp[4] : last argument 2956a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // ----------------------------------- 2957a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Label generic_stub_call; 2958a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2959a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Use r8 for holding undefined which is used in several places below. 296044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(r8, factory()->undefined_value()); 2961a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2962a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef ENABLE_DEBUGGER_SUPPORT 2963a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check to see whether there are any break points in the function code. If 2964a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // there are jump to the generic constructor stub which calls the actual 2965a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // code for the function thereby hitting the break points. 2966a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, FieldOperand(rdi, JSFunction::kSharedFunctionInfoOffset)); 2967a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, FieldOperand(rbx, SharedFunctionInfo::kDebugInfoOffset)); 2968a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rbx, r8); 2969a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &generic_stub_call); 2970a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2971a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2972a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the initial map and verify that it is in fact a map. 2973a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, FieldOperand(rdi, JSFunction::kPrototypeOrInitialMapOffset)); 2974a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Will both indicate a NULL and a Smi. 297569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch STATIC_ASSERT(kSmiTag == 0); 2976a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ JumpIfSmi(rbx, &generic_stub_call); 2977a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpObjectType(rbx, MAP_TYPE, rcx); 2978a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ j(not_equal, &generic_stub_call); 2979a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2980a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#ifdef DEBUG 2981a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Cannot construct functions this way. 2982a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdi: constructor 2983a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx: initial map 2984a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ CmpInstanceType(rbx, JS_FUNCTION_TYPE); 2985a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Assert(not_equal, "Function constructed by construct stub."); 2986a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#endif 2987a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2988a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Now allocate the JSObject in new space. 2989a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdi: constructor 2990a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx: initial map 2991a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movzxbq(rcx, FieldOperand(rbx, Map::kInstanceSizeOffset)); 2992a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ shl(rcx, Immediate(kPointerSizeLog2)); 29933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(rcx, rdx, rcx, no_reg, 29943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &generic_stub_call, NO_ALLOCATION_FLAGS); 2995a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 2996a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Allocated the JSObject, now initialize the fields and add the heap tag. 2997a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx: initial map 2998a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx: JSObject (untagged) 2999a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rdx, JSObject::kMapOffset), rbx); 300044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ Move(rbx, factory()->empty_fixed_array()); 3001a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rdx, JSObject::kPropertiesOffset), rbx); 3002a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(rdx, JSObject::kElementsOffset), rbx); 3003a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3004a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax: argc 3005a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx: JSObject (untagged) 3006a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Load the address of the first in-object property into r9. 3007a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(r9, Operand(rdx, JSObject::kHeaderSize)); 3008a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Calculate the location of the first argument. The stack contains only the 3009a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // return address on top of the argc arguments. 3010a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rcx, Operand(rsp, rax, times_pointer_size, 0)); 3011a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3012a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax: argc 3013a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rcx: first argument 3014a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx: JSObject (untagged) 3015a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r8: undefined 3016a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // r9: first in-object property of the JSObject 3017a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the initialized properties with a constant value or a passed argument 3018a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // depending on the this.x = ...; assignment in the function. 30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> shared(function->shared()); 3020a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = 0; i < shared->this_property_assignments_count(); i++) { 3021a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block if (shared->IsThisPropertyAssignmentArgument(i)) { 3022a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Check if the argument assigned to the property is actually passed. 3023e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // If argument is not passed the property is set to undefined, 3024e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // otherwise find it on the stack. 3025a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block int arg_number = shared->GetThisPropertyAssignmentArgument(i); 3026e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ movq(rbx, r8); 3027a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ cmpq(rax, Immediate(arg_number)); 3028e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke __ cmovq(above, rbx, Operand(rcx, arg_number * -kPointerSize)); 3029e46be819fca9468a0cd4e74859ce0f778eb8ca60Leon Clarke // Store value in the property. 3030a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(r9, i * kPointerSize), rbx); 3031a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } else { 3032a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Set the property to the constant value. 3033a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 3034a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ Move(Operand(r9, i * kPointerSize), constant); 3035a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3036a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3037a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3038a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Fill the unused in-object property fields with undefined. 30398a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang ASSERT(function->has_initial_map()); 3040a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block for (int i = shared->this_property_assignments_count(); 30418a31eba00023874d4a1dcdc5f411cc4336776874Shimeng (Simon) Wang i < function->initial_map()->inobject_properties(); 3042a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block i++) { 3043a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(Operand(r9, i * kPointerSize), r8); 3044a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block } 3045a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3046a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax: argc 3047a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rdx: JSObject (untagged) 3048a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Move argc to rbx and the JSObject to return to rax and tag it. 3049a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rbx, rax); 3050a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ movq(rax, rdx); 3051a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ or_(rax, Immediate(kHeapObjectTag)); 3052a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3053a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rax: JSObject 3054a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // rbx: argc 3055a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Remove caller arguments and receiver from the stack and return. 3056a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ pop(rcx); 3057a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ lea(rsp, Operand(rsp, rbx, times_pointer_size, 1 * kPointerSize)); 3058a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ push(rcx); 305944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Counters* counters = isolate()->counters(); 306044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects(), 1); 306144f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->constructed_objects_stub(), 1); 3062a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ ret(0); 3063a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3064a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Jump to the generic stub in case the specialized code cannot handle the 3065a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // construction. 3066a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block __ bind(&generic_stub_call); 30673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = isolate()->builtins()->JSConstructStubGeneric(); 30683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 3069a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3070a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block // Return the generated code. 3071a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block return GetCode(); 3072a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} 3073a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3074a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 30753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __ 30763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm) 30773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 30783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 30793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement( 30803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 30811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 30821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rax : key 30831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rdx : receiver 30841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rsp[0] : return address 30851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 30863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label slow, miss_force_generic; 3087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 30883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 30893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 30901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 30913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(rax, &miss_force_generic); 30923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger32(rbx, rax); 30933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 30941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 30953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check whether the elements is a number dictionary. 30963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rdx: receiver 30973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rax: key 30983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rbx: key as untagged int32 30993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // rcx: elements 31003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadFromNumberDictionary(&slow, rcx, rax, rbx, r9, rdi, rax); 31013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 31023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 31033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow); 3104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 31053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rax : key 3106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 31073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rsp[0] : return address 3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 31093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 31103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 31113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(slow_ic, RelocInfo::CODE_TARGET); 3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 31133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 31143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 31153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rax : key 31163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rdx : receiver 31173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rsp[0] : return address 31183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 31193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 31203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 31213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray( 3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3126589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : key 3129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 3130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 3131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow, miss_force_generic; 3133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 3138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(rax, &miss_force_generic); 31391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 3141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); 31421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiToInteger32(rcx, rax); 314369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(rax, FieldOperand(rbx, ExternalArray::kLengthOffset)); 31441e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 3145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 31461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31471e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rax: index (as a smi) 31481e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rdx: receiver (JSObject) 31491e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rcx: untagged index 31501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rbx: elements array 31511e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 31521e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rbx: base pointer of external storage 31533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3154589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 31551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsxbq(rcx, Operand(rbx, rcx, times_1, 0)); 31561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3157589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3158589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 31591e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movzxbq(rcx, Operand(rbx, rcx, times_1, 0)); 31601e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3161589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 31621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsxwq(rcx, Operand(rbx, rcx, times_2, 0)); 31631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3164589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 31651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movzxwq(rcx, Operand(rbx, rcx, times_2, 0)); 31661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3167589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 31681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsxlq(rcx, Operand(rbx, rcx, times_4, 0)); 31691e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3170589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 31711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movl(rcx, Operand(rbx, rcx, times_4, 0)); 31721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3173589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 31741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvtss2sd(xmm0, Operand(rbx, rcx, times_4, 0)); 31751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3176589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(xmm0, Operand(rbx, rcx, times_8, 0)); 3178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 31791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block default: 31801e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 31811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 31821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 31831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rax: index 31851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rdx: receiver 31861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For integer array types: 31871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rcx: value 31881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For floating-point array type: 31891e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // xmm0: value as double. 31901e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 31911e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block ASSERT(kSmiValueSize == 32); 3192589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { 31931e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the UnsignedInt array type, we need to see whether 31941e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // the value can be represented in a Smi. If not, we need to convert 31951e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // it to a HeapNumber. 3196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label box_int; 31971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfUIntNotValidSmiValue(rcx, &box_int, Label::kNear); 31991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32001e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Integer32ToSmi(rax, rcx); 32011e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 32021e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32031e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&box_int); 32041e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32051e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Allocate a HeapNumber for the int and perform int-to-double 32061e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // conversion. 32071e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // The value is zero-extended since we loaded the value from memory 32081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // with movl. 32091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvtqsi2sd(xmm0, rcx); 32101e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(rcx, rbx, &slow); 32121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the value. 32131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); 32141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, rcx); 32151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 3216589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS || 3217589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 32181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // For the floating-point array type, we need to always allocate a 32191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // HeapNumber. 32201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ AllocateHeapNumber(rcx, rbx, &slow); 32211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Set the value. 32221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); 32231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rax, rcx); 32241e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 32251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } else { 32261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ Integer32ToSmi(rax, rcx); 32271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 32281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 32291e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32301e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case: Jump to runtime. 32311e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 3232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 323344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ IncrementCounter(counters->keyed_load_external_array_slow(), 1); 32341e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32351e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 32361e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rax : key 32371e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rdx : receiver 32381e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rsp[0] : return address 32391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 32401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm->isolate()->builtins()->KeyedLoadIC_Slow(); 3242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 32431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss case: Jump to runtime. 3245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 32461e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : key 3249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 3250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 3251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 3254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 32551e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 32561e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32571e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray( 3259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3260589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 32611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 32621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rax : value 32631e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rcx : key 32641e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rdx : receiver 32651e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rsp[0] : return address 32661e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 3267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow, miss_force_generic; 32681e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 327144f0eee88ff00398ff7f715fab053374d808c90dSteve Block 327244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Check that the key is a smi. 3273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(rcx, &miss_force_generic); 32741e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Check that the index is in range. 3276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rbx, FieldOperand(rdx, JSObject::kElementsOffset)); 32771e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiToInteger32(rdi, rcx); // Untag the index. 327869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ cmpq(rcx, FieldOperand(rbx, ExternalArray::kLengthOffset)); 32791e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Unsigned comparison catches both negative and too-large values. 3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 32811e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 32821e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Handle both smis and HeapNumbers in the fast path. Go to the 32831e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // runtime for all other kinds of values. 32841e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rax: value 32851e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rcx: key (a smi) 32861e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rdx: receiver (a JSObject) 32871e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rbx: elements array 32881e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rdi: untagged key 3289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check_heap_number; 3290589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { 329144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Float to pixel conversion is only implemented in the runtime for now. 329244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ JumpIfNotSmi(rax, &slow); 329344f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 3294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(rax, &check_heap_number, Label::kNear); 329544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 32961e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // No more branches to slow case on this path. Key and receiver not needed. 32971e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ SmiToInteger32(rdx, rax); 32981e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 32991e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rbx: base pointer of external storage 33003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3301589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 330244f0eee88ff00398ff7f715fab053374d808c90dSteve Block { // Clamp the value to [0..255]. 3303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 330444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ testl(rdx, Immediate(0xFFFFFF00)); 3305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(zero, &done, Label::kNear); 330644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ setcc(negative, rdx); // 1 if negative, 0 if positive. 330744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ decb(rdx); // 0 if negative, 255 if positive. 330844f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&done); 330944f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 331044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movb(Operand(rbx, rdi, times_1, 0), rdx); 331144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3312589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3313589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 33141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movb(Operand(rbx, rdi, times_1, 0), rdx); 33151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3316589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3317589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 33181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movw(Operand(rbx, rdi, times_2, 0), rdx); 33191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3320589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3321589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 33221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movl(Operand(rbx, rdi, times_4, 0), rdx); 33231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3324589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 33251e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Need to perform int-to-float conversion. 33261e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ cvtlsi2ss(xmm0, rdx); 33271e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ movss(Operand(rbx, rdi, times_4, 0), xmm0); 33281e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 3329589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Need to perform int-to-float conversion. 3331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvtlsi2sd(xmm0, rdx); 3332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); 3333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3334589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 33353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3336589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3337589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3338589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 33391e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block UNREACHABLE(); 33401e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block break; 33411e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 33421e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ ret(0); 33431e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 334444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // TODO(danno): handle heap number -> pixel array conversion 3345589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { 334644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ bind(&check_heap_number); 334744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rax: value 334844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rcx: key (a smi) 334944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rdx: receiver (a JSObject) 335044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rbx: elements array 335144f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rdi: untagged key 335244f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ CmpObjectType(rax, HEAP_NUMBER_TYPE, kScratchRegister); 335344f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ j(not_equal, &slow); 335444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // No more branches to slow case on this path. 335544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 335644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // The WebGL specification leaves the behavior of storing NaN and 335744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // +/-Infinity into integer arrays basically undefined. For more 335844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // reproducible behavior, convert these to zero. 335944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movsd(xmm0, FieldOperand(rax, HeapNumber::kValueOffset)); 336044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movq(rbx, FieldOperand(rbx, ExternalArray::kExternalPointerOffset)); 33611e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rdi: untagged index 33621e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // rbx: base pointer of external storage 336344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // top of FPU stack: value 3364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 336544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvtsd2ss(xmm0, xmm0); 336644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movss(Operand(rbx, rdi, times_4, 0), xmm0); 336744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ret(0); 3368589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movsd(Operand(rbx, rdi, times_8, 0), xmm0); 3370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 337144f0eee88ff00398ff7f715fab053374d808c90dSteve Block } else { 337244f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Perform float-to-int conversion with truncation (round-to-zero) 337344f0eee88ff00398ff7f715fab053374d808c90dSteve Block // behavior. 337444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 337544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert to int32 and store the low byte/word. 337644f0eee88ff00398ff7f715fab053374d808c90dSteve Block // If the value is NaN or +/-infinity, the result is 0x80000000, 337744f0eee88ff00398ff7f715fab053374d808c90dSteve Block // which is automatically zero when taken mod 2^n, n < 32. 337844f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rdx: value (converted to an untagged integer) 337944f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rdi: untagged index 338044f0eee88ff00398ff7f715fab053374d808c90dSteve Block // rbx: base pointer of external storage 33813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3382589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3383589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 338444f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvttsd2si(rdx, xmm0); 338544f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movb(Operand(rbx, rdi, times_1, 0), rdx); 338644f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3387589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3388589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 338944f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvttsd2si(rdx, xmm0); 339044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movw(Operand(rbx, rdi, times_2, 0), rdx); 339144f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3392589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3393589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 339444f0eee88ff00398ff7f715fab053374d808c90dSteve Block // Convert to int64, so that NaN and infinities become 339544f0eee88ff00398ff7f715fab053374d808c90dSteve Block // 0x8000000000000000, which is zero mod 2^32. 339644f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ cvttsd2siq(rdx, xmm0); 339744f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ movl(Operand(rbx, rdi, times_4, 0), rdx); 339844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 3399589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3400589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3401589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3402589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 34033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3404589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3405589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3406589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 340744f0eee88ff00398ff7f715fab053374d808c90dSteve Block UNREACHABLE(); 340844f0eee88ff00398ff7f715fab053374d808c90dSteve Block break; 34091e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 341044f0eee88ff00398ff7f715fab053374d808c90dSteve Block __ ret(0); 34111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34121e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block } 34131e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34141e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // Slow case: call runtime. 34151e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block __ bind(&slow); 34161e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 34171e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------- S t a t e ------------- 34181e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rax : value 34191e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rcx : key 34201e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rdx : receiver 34211e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // -- rsp[0] : return address 34221e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block // ----------------------------------- 34231e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 3425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 3426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss case: call runtime. 3428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : value 3432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rcx : key 3433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 3435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 3438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { 3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : key 3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 3447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic; 34501e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 34531e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 3455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(rax, &miss_force_generic); 3456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array. 3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 3459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AssertFastElements(rcx); 3460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); 3463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the result and make sure it's not the hole. 3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch SmiIndex index = masm->SmiToIndex(rbx, rax, kPointerSizeLog2); 3467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rbx, FieldOperand(rcx, 3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index.reg, 3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index.scale, 3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FixedArray::kHeaderSize)); 3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CompareRoot(rbx, Heap::kTheHoleValueRootIndex); 3472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(equal, &miss_force_generic); 3473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rax, rbx); 3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Code* code = masm->isolate()->builtins()->builtin( 3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Builtins::kKeyedLoadIC_MissForceGeneric); 3479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic(code); 3480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic, RelocInfo::CODE_TARGET); 3481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 34843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( 34853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 34863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 34873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rax : key 34883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rdx : receiver 34893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rsp[0] : return address 34903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 34913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label miss_force_generic, slow_allocate_heapnumber; 34923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 34943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 34953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 34973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(rax, &miss_force_generic); 34983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 34993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 35003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rcx, FieldOperand(rdx, JSObject::kElementsOffset)); 35013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AssertFastElements(rcx); 35023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 35043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiCompare(rax, FieldOperand(rcx, FixedArray::kLengthOffset)); 35053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(above_equal, &miss_force_generic); 35063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check for the hole 35083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger32(kScratchRegister, rax); 35093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t offset = FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32); 35103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ cmpl(FieldOperand(rcx, kScratchRegister, times_8, offset), 35113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Immediate(kHoleNanUpper32)); 35123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ j(equal, &miss_force_generic); 35133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Always allocate a heap number for the result. 35153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movsd(xmm0, FieldOperand(rcx, kScratchRegister, times_8, 35163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedDoubleArray::kHeaderSize)); 35173fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateHeapNumber(rcx, rbx, &slow_allocate_heapnumber); 35183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Set the value. 35193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rax, rcx); 35203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movsd(FieldOperand(rcx, HeapNumber::kValueOffset), xmm0); 35213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 35223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow_allocate_heapnumber); 35243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 35253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 35263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(slow_ic, RelocInfo::CODE_TARGET); 35273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 35293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 35303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 35313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(miss_ic, RelocInfo::CODE_TARGET); 35323fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 35333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 35353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement( 35363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 35373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 35383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind elements_kind, 35393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 3540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rax : value 3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rcx : key 3543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rdx : receiver 3544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- rsp[0] : return address 3545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 35463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, finish_store, grow; 35473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label check_capacity, slow; 3548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 3553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(rcx, &miss_force_generic); 3554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 35553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 35563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(rax, &transition_elements_kind); 35573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 35583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 3559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array and make sure it is a fast element array, not 'cow'. 3560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 3562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (is_js_array) { 3563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 35643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 35653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &grow); 35663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 35673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 35683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiCompare(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 3571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ j(above_equal, &miss_force_generic); 3572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 35743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset), 35753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedArrayMapRootIndex); 35763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 35773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 35783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 35793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 35803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(rcx, rcx); 35813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize), 35823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch rax); 35833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 35843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Do the store and update the write barrier. 35853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(elements_kind == FAST_ELEMENTS); 35863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiToInteger32(rcx, rcx); 35873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lea(rcx, 35883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldOperand(rdi, rcx, times_pointer_size, FixedArray::kHeaderSize)); 35893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(Operand(rcx, 0), rax); 35903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure to preserve the value in register rax. 35913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rbx, rax); 35923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(rdi, rcx, rbx, kDontSaveFPRegs); 35933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Done. 3596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ret(0); 3597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle store cache miss. 3599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 3600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic_force_generic = 3601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 3602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 36033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 36053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 36063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_miss, RelocInfo::CODE_TARGET); 36073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 36093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array by a single element if possible. 36103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 36113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 36133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags are already set by previous 36143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compare. 36153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 36163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 36183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 36193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 36203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rdi, Heap::kEmptyFixedArrayRootIndex); 36213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &check_capacity); 36223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); 36243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT); 36253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: value 36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: key 36283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: receiver 36293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: elements 36303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 36313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdi, JSObject::kMapOffset), 36323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->factory()->fixed_array_map()); 36333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdi, FixedArray::kLengthOffset), 36343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(JSArray::kPreallocatedArrayElements)); 36353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(rbx, Heap::kTheHoleValueRootIndex); 36363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) { 36373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdi, FixedArray::SizeFor(i)), rbx); 36383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 36393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the element at index zero. 36413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdi, FixedArray::SizeFor(0)), rax); 36423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 36443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi); 36453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx, 36463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 36473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 36493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1)); 36503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ ret(0); 36513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 36533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for cow elements, in general they are not handled by this stub. 36543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(rdi, HeapObject::kMapOffset), 36553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedCOWArrayMapRootIndex); 36563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(equal, &miss_force_generic); 36573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: value 36593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: key 36603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: receiver 36613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: elements 36623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 36633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(rcx, FieldOperand(rdi, FixedArray::kLengthOffset)); 36643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &slow); 36653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 36673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset), 36683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(1)); 36693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 36703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 36713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 36723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 36733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_slow, RelocInfo::CODE_TARGET); 36743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 36751e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 36761e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 3677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 36783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 36793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm, 36803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 36813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 36823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 36833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rax : value 36843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rcx : key 36853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rdx : receiver 36863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- rsp[0] : return address 36873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 36883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, finish_store; 36893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label grow, slow, check_capacity; 36903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 36923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 36933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 36953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(rcx, &miss_force_generic); 36963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 36973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 36983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 36993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AssertFastElements(rdi); 37003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 37023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_js_array) { 37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiCompare(rcx, FieldOperand(rdx, JSArray::kLengthOffset)); 37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &grow); 37063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 37073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 37083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 37103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiCompare(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset)); 37113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &miss_force_generic); 37123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 37133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Handle smi values specially 37153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 37163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ SmiToInteger32(rcx, rcx); 37173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreNumberToDoubleElements(rax, rdi, rcx, xmm0, 37183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &transition_elements_kind); 37193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ ret(0); 37203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 37213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 37223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 37233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> ic_force_generic = 37243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 37253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ jmp(ic_force_generic, RelocInfo::CODE_TARGET); 37263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 37283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Restore smi-tagging of rcx. 37293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Integer32ToSmi(rcx, rcx); 37303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 37313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_miss, RelocInfo::CODE_TARGET); 37323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 37343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array by a single element if possible. 37353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 37363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 37383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. Flags are already set by previous 37393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // compare. 37403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &miss_force_generic); 37413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Transition on values that can't be stored in a FixedDoubleArray. 37433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label value_is_smi; 37443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(rax, &value_is_smi); 37453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(FieldOperand(rax, HeapObject::kMapOffset), 37463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kHeapNumberMapRootIndex); 37473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &transition_elements_kind); 37483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&value_is_smi); 37493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 37513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 37523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 37533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CompareRoot(rdi, Heap::kEmptyFixedArrayRootIndex); 37543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(not_equal, &check_capacity); 37553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements); 37573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, rdi, rbx, r8, &slow, TAG_OBJECT); 37583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: value 37603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: key 37613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: receiver 37623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: elements 37633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the new FixedDoubleArray. Leave elements unitialized for 37643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // efficiency, they are guaranteed to be initialized before use. 37653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdi, JSObject::kMapOffset), 37663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->factory()->fixed_double_array_map()); 37673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdi, FixedDoubleArray::kLengthOffset), 37683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(JSArray::kPreallocatedArrayElements)); 37693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 37713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ movq(FieldOperand(rdx, JSObject::kElementsOffset), rdi); 37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(rdx, JSObject::kElementsOffset, rdi, rbx, 37733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 37743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 37763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Move(FieldOperand(rdx, JSArray::kLengthOffset), Smi::FromInt(1)); 37779413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch __ movq(rdi, FieldOperand(rdx, JSObject::kElementsOffset)); 37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 37813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rax: value 37823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rcx: key 37833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdx: receiver 37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // rdi: elements 37853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 37863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ cmpq(rcx, FieldOperand(rdi, FixedDoubleArray::kLengthOffset)); 37873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ j(above_equal, &slow); 37883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 37903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiAddConstant(FieldOperand(rdx, JSArray::kLengthOffset), 37913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Smi::FromInt(1)); 37923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 37933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 37963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(ic_slow, RelocInfo::CODE_TARGET); 37973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 37983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 37993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 38003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 3801a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block#undef __ 3802a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block 3803a7e24c173cf37484693b9abb38e494fa7bd7baebSteve Block} } // namespace v8::internal 3804f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 3805f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_X64 3806