13ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 23100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Redistribution and use in source and binary forms, with or without 33100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// modification, are permitted provided that the following conditions are 43100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// met: 53100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 63100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// * Redistributions of source code must retain the above copyright 73100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// notice, this list of conditions and the following disclaimer. 83100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// * Redistributions in binary form must reproduce the above 93100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// copyright notice, this list of conditions and the following 103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// disclaimer in the documentation and/or other materials provided 113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// with the distribution. 123100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// * Neither the name of Google Inc. nor the names of its 133100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// contributors may be used to endorse or promote products derived 143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// from this software without specific prior written permission. 153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// 163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT 223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "v8.h" 293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 30f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#if defined(V8_TARGET_ARCH_MIPS) 31f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke 323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "ic-inl.h" 33257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#include "codegen.h" 343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#include "stub-cache.h" 353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace v8 { 373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescunamespace internal { 383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define __ ACCESS_MASM(masm) 403100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 42257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void ProbeTable(Isolate* isolate, 43257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 44257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Code::Flags flags, 45257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StubCache::Table table, 463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 47257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register name, 483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Number of the cache entry, not scaled. 49257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register offset, 50257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch, 513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register offset_scratch) { 53257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference key_offset(isolate->stub_cache()->key_reference(table)); 54257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference value_offset(isolate->stub_cache()->value_reference(table)); 553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ExternalReference map_offset(isolate->stub_cache()->map_reference(table)); 56257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 57257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t key_off_addr = reinterpret_cast<uint32_t>(key_offset.address()); 58257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch uint32_t value_off_addr = reinterpret_cast<uint32_t>(value_offset.address()); 593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t map_off_addr = reinterpret_cast<uint32_t>(map_offset.address()); 60257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 61257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the relative positions of the address fields. 62257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(value_off_addr > key_off_addr); 63257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT((value_off_addr - key_off_addr) % 4 == 0); 64257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT((value_off_addr - key_off_addr) < (256 * 4)); 653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(map_off_addr > key_off_addr); 663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT((map_off_addr - key_off_addr) % 4 == 0); 673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT((map_off_addr - key_off_addr) < (256 * 4)); 68257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 69257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register base_addr = scratch; 713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch = no_reg; 723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Multiply by 3 because there are 3 fields per entry (name, code, map). 743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(offset_scratch, offset, 1); 753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(offset_scratch, offset_scratch, offset); 763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calculate the base address of the entry. 783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(base_addr, Operand(key_offset)); 793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(at, offset_scratch, kPointerSizeLog2); 803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(base_addr, base_addr, at); 81257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 82257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key in the entry matches the name. 833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(at, MemOperand(base_addr, 0)); 843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, name, Operand(at)); 853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check the map matches. 873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(at, MemOperand(base_addr, map_off_addr - key_off_addr)); 883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); 893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, at, Operand(scratch2)); 90257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 91257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the code entry from the cache. 923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register code = scratch2; 933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2 = no_reg; 943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(code, MemOperand(base_addr, value_off_addr - key_off_addr)); 95257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 96257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the flags match what we're looking for. 973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register flags_reg = base_addr; 983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch base_addr = no_reg; 993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(flags_reg, FieldMemOperand(code, Code::kFlagsOffset)); 1003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(flags_reg, flags_reg, Operand(~Code::kFlagsNotUsedInLookup)); 1013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, flags_reg, Operand(flags)); 102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#ifdef DEBUG 1043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_test_secondary_stub_cache && table == StubCache::kPrimary) { 1053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 1063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else if (FLAG_test_primary_stub_cache && table == StubCache::kSecondary) { 1073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 1083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch#endif 110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Jump to the first instruction in the code stub. 1123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(at, code, Operand(Code::kHeaderSize - kHeapObjectTag)); 1133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(at); 114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss: fall through. 116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Helper function used to check that the dictionary doesn't contain 121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// the property. This function may return false negatives, so miss_label 122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// must always call a backup property check that is complete. 123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// This function is safe to call if the receiver has fast properties. 124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Name must be a symbol and receiver must be a heap object. 1253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateDictionaryNegativeLookup(MacroAssembler* masm, 1263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss_label, 1273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 1283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 1293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch0, 1303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1) { 131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(name->IsSymbol()); 132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->negative_lookups(), 1, scratch0, scratch1); 134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kInterceptorOrAccessCheckNeededMask = 139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch (1 << Map::kHasNamedInterceptor) | (1 << Map::kIsAccessCheckNeeded); 140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Bail out if the receiver has a named interceptor or requires access checks. 142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register map = scratch1; 143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(scratch0, FieldMemOperand(map, Map::kBitFieldOffset)); 1453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(scratch0, scratch0, Operand(kInterceptorOrAccessCheckNeededMask)); 1463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(miss_label, ne, scratch0, Operand(zero_reg)); 147257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 148257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that receiver is a JSObject. 149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(scratch0, FieldMemOperand(map, Map::kInstanceTypeOffset)); 1503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(miss_label, lt, scratch0, Operand(FIRST_SPEC_OBJECT_TYPE)); 151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load properties array. 153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register properties = scratch0; 154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the properties array is a dictionary. 156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(map, FieldMemOperand(properties, HeapObject::kMapOffset)); 157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register tmp = properties; 158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(tmp, Heap::kHashTableMapRootIndex); 159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss_label, ne, map, Operand(tmp)); 160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore the temporarily used register. 162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(properties, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringDictionaryLookupStub::GenerateNegativeLookup(masm, 1663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss_label, 1673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &done, 1683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 1693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch properties, 1703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 1713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1); 172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DecrementCounter(counters->negative_lookups_miss(), 1, scratch0, scratch1); 174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCache::GenerateProbe(MacroAssembler* masm, 1783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Code::Flags flags, 1793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register receiver, 1803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register name, 1813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch, 1823e5fa29ddb82551500b118e9bf37af3966277b70Teng-Hui Zhu Register extra, 1833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register extra2, 1843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register extra3) { 185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Isolate* isolate = masm->isolate(); 186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that code is valid. The multiplying code relies on the 1893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // entry size being 12. 1903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(sizeof(Entry) == 12); 191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure the flags does not name a specific type. 193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(Code::ExtractTypeFromFlags(flags) == 0); 194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure that there are no register conflicts. 196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!scratch.is(receiver)); 197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!scratch.is(name)); 198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!extra.is(receiver)); 199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!extra.is(name)); 200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!extra.is(scratch)); 201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!extra2.is(receiver)); 202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!extra2.is(name)); 203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!extra2.is(scratch)); 204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!extra2.is(extra)); 205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check register validity. 207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!scratch.is(no_reg)); 208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!extra.is(no_reg)); 209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!extra2.is(no_reg)); 2103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!extra3.is(no_reg)); 2113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Counters* counters = masm->isolate()->counters(); 2133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->megamorphic_stub_cache_probes(), 1, 2143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra2, extra3); 215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 2173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(receiver, &miss); 218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the map of the receiver and compute the hash. 220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch, FieldMemOperand(name, String::kHashFieldOffset)); 2213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(at, FieldMemOperand(receiver, HeapObject::kMapOffset)); 2223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(scratch, scratch, at); 2233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t mask = kPrimaryTableSize - 1; 2243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We shift out the last two bits because they are not part of the hash and 2253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // they are always 01 for maps. 2263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ srl(scratch, scratch, kHeapObjectTagSize); 2273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Xor(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask)); 2283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(scratch, scratch, Operand(mask)); 229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Probe the primary table. 2313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ProbeTable(isolate, 2323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, 2333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flags, 2343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kPrimary, 2353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 2363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 2373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 2383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra, 2393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra2, 2403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra3); 241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Primary miss: Compute hash for secondary probe. 2433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ srl(at, name, kHeapObjectTagSize); 2443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Subu(scratch, scratch, at); 2453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch uint32_t mask2 = kSecondaryTableSize - 1; 2463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(scratch, scratch, Operand((flags >> kHeapObjectTagSize) & mask2)); 2473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ And(scratch, scratch, Operand(mask2)); 248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Probe the secondary table. 2503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ProbeTable(isolate, 2513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm, 2523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch flags, 2533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kSecondary, 2543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 2553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 2563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 2573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra, 2583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra2, 2593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra3); 260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Cache miss: Fall-through and let caller handle the miss by 262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // entering the runtime system. 263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ IncrementCounter(counters->megamorphic_stub_cache_misses(), 1, 2653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra2, extra3); 2663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 2673100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateLoadGlobalFunctionPrototype(MacroAssembler* masm, 2703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int index, 2713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register prototype) { 272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the global or builtins object from the current context. 273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the global context from the global or builtins object. 275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(prototype, 276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(prototype, GlobalObject::kGlobalContextOffset)); 277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the function from the global context. 278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(prototype, MemOperand(prototype, Context::SlotOffset(index))); 279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the initial map. The global functions all have initial maps. 280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(prototype, 281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(prototype, JSFunction::kPrototypeOrInitialMapOffset)); 282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the prototype from the initial map. 283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 2843100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 2853100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 2863100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28744f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StubCompiler::GenerateDirectLoadGlobalFunctionPrototype( 2883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 2893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index, 2903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register prototype, 2913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Isolate* isolate = masm->isolate(); 293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check we're still in the same context. 294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(prototype, MemOperand(cp, Context::SlotOffset(Context::GLOBAL_INDEX))); 295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!prototype.is(at)); 296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(at, isolate->global()); 297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss, ne, prototype, Operand(at)); 298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the global function with the given index. 2993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function( 3003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JSFunction::cast(isolate->global_context()->get(index))); 301257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load its initial map. The global functions all have initial maps. 302257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(prototype, Handle<Map>(function->initial_map())); 303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the prototype from the initial map. 304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(prototype, FieldMemOperand(prototype, Map::kPrototypeOffset)); 30544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 30644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 30744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 3083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// Load a fast property out of a holder object (src). In-object properties 3093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// are loaded directly otherwise the property is loaded from the properties 3103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// fixed array. 3113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateFastPropertyLoad(MacroAssembler* masm, 3123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register dst, 3133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register src, 3143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 3153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int index) { 316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Adjust for the number of properties stored in the holder. 317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index -= holder->map()->inobject_properties(); 318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (index < 0) { 319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the property straight out of the holder. 320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int offset = holder->map()->instance_size() + (index * kPointerSize); 321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(dst, FieldMemOperand(src, offset)); 322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate the offset into the properties array. 324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int offset = index * kPointerSize + FixedArray::kHeaderSize; 325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(dst, FieldMemOperand(src, JSObject::kPropertiesOffset)); 326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(dst, FieldMemOperand(dst, offset)); 327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 3293100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateLoadArrayLength(MacroAssembler* masm, 3323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register receiver, 3333100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch, 3343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* miss_label) { 335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 3363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(receiver, miss_label); 337257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the object is a JS array. 339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(receiver, scratch, scratch); 340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss_label, ne, scratch, Operand(JS_ARRAY_TYPE)); 341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load length directly from the JS array. 343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Generate code to check if an object is a string. If the object is a 349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// heap object, its map's instance type is left in the scratch1 register. 350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// If this is not needed, scratch1 and scratch2 may be the same register. 351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void GenerateStringCheck(MacroAssembler* masm, 352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver, 353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2, 355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* smi, 356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* non_string_object) { 357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(receiver, smi, t0); 359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the object is a string. 361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, FieldMemOperand(receiver, HeapObject::kMapOffset)); 362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(scratch1, FieldMemOperand(scratch1, Map::kInstanceTypeOffset)); 363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(scratch2, scratch1, Operand(kIsNotStringMask)); 364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The cast is to resolve the overload for the argument of 0x0. 365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(non_string_object, 366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ne, 367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(static_cast<int32_t>(kStringTag))); 3693100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 3703100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 3713100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 37244f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Generate code to load the length from a string object and return the length. 37344f0eee88ff00398ff7f715fab053374d808c90dSteve Block// If the receiver object is not a string or a wrapped string object the 37444f0eee88ff00398ff7f715fab053374d808c90dSteve Block// execution continues at the miss label. The register containing the 37544f0eee88ff00398ff7f715fab053374d808c90dSteve Block// receiver is potentially clobbered. 37644f0eee88ff00398ff7f715fab053374d808c90dSteve Blockvoid StubCompiler::GenerateLoadStringLength(MacroAssembler* masm, 37744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register receiver, 37844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 37944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 38044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* miss, 38144f0eee88ff00398ff7f715fab053374d808c90dSteve Block bool support_wrappers) { 382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label check_wrapper; 383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the object is a string leaving the instance type in the 385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // scratch1 register. 386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateStringCheck(masm, receiver, scratch1, scratch2, miss, 387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch support_wrappers ? &check_wrapper : miss); 388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load length directly from the string. 390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, FieldMemOperand(receiver, String::kLengthOffset)); 391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (support_wrappers) { 394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the object is a JSValue wrapper. 395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&check_wrapper); 396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss, ne, scratch1, Operand(JS_VALUE_TYPE)); 397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Unwrap the value and check if the wrapped value is a string. 399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, FieldMemOperand(receiver, JSValue::kValueOffset)); 400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateStringCheck(masm, scratch1, scratch2, scratch2, miss, miss); 401257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, FieldMemOperand(scratch1, String::kLengthOffset)); 402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 40444f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 40544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 40644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 4073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateLoadFunctionPrototype(MacroAssembler* masm, 4083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register receiver, 4093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, 4103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch2, 4113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* miss_label) { 412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TryGetFunctionPrototype(receiver, scratch1, scratch2, miss_label); 413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, scratch1); 414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 4153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 4163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 41844f0eee88ff00398ff7f715fab053374d808c90dSteve Block// Generate StoreField code, value is passed in a0 register. 4193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// After executing generated code, the receiver_reg and name_reg 4203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu// may be clobbered. 4213100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateStoreField(MacroAssembler* masm, 4223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 4233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int index, 4243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 4253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register receiver_reg, 4263100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register name_reg, 4273100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch, 4283100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* miss_label) { 429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0 : value. 430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label exit; 4313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the map of the object hasn't changed. 4328f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch CompareMapMode mode = transition.is_null() ? ALLOW_ELEMENT_TRANSITION_MAPS 4338f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch : REQUIRE_EXACT_MAP; 4343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(receiver_reg, scratch, Handle<Map>(object->map()), miss_label, 4358f9999fcc44cfd4f5e1140c6678bbca4cf8ea1c7Ben Murdoch DO_SMI_CHECK, mode); 436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Perform global security token check if needed. 438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (object->IsJSGlobalProxy()) { 439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckAccessGlobalProxy(receiver_reg, scratch, miss_label); 440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stub never generated for non-global objects that require access 443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // checks. 444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Perform map transition for the receiver if necessary. 4473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition.is_null() && (object->map()->unused_property_fields() == 0)) { 448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The properties must be extended before we can store the value. 449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We jump to a runtime call that extends the properties array. 450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(receiver_reg); 4513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a2, Operand(transition)); 452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(a2, a0); 453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallExternalReference( 454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference(IC_Utility(IC::kSharedStoreIC_ExtendStorage), 455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()), 456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3, 1); 457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return; 458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!transition.is_null()) { 461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Update the map of the object; no write barrier updating is 462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // needed because the map is never in new space. 4633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(t0, Operand(transition)); 464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t0, FieldMemOperand(receiver_reg, HeapObject::kMapOffset)); 465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Adjust for the number of properties stored in the object. Even in the 468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // face of a transition we can use the old map here because the size of the 469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // object and the number of in-object properties is not going to change. 470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index -= object->map()->inobject_properties(); 471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (index < 0) { 473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set the property straight into the object. 474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int offset = object->map()->instance_size() + (index * kPointerSize); 475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a0, FieldMemOperand(receiver_reg, offset)); 476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Skip updating write barrier if storing a smi. 478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a0, &exit, scratch); 479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Update the write barrier for the array address. 481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Pass the now unused name_reg as a scratch register. 4823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(name_reg, a0); 4833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(receiver_reg, 4843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 4853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 4863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 4873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kRAHasNotBeenSaved, 4883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Write to the properties array. 491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int offset = index * kPointerSize + FixedArray::kHeaderSize; 492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the properties array. 493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch, FieldMemOperand(receiver_reg, JSObject::kPropertiesOffset)); 494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a0, FieldMemOperand(scratch, offset)); 495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Skip updating write barrier if storing a smi. 497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a0, &exit); 498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Update the write barrier for the array address. 500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Ok to clobber receiver_reg and name_reg, since we return. 5013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(name_reg, a0); 5023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(scratch, 5033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch offset, 5043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 5053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, 5063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kRAHasNotBeenSaved, 5073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the value (register v0). 511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&exit); 512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, a0); 513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 5143100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 5153100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5163100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 5173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescuvoid StubCompiler::GenerateLoadMiss(MacroAssembler* masm, Code::Kind kind) { 518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(kind == Code::LOAD_IC || kind == Code::KEYED_LOAD_IC); 5193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = (kind == Code::LOAD_IC) 5203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ? masm->isolate()->builtins()->LoadIC_Miss() 5213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch : masm->isolate()->builtins()->KeyedLoadIC_Miss(); 5223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void GenerateCallFunction(MacroAssembler* masm, 5273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const ParameterCount& arguments, 5293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label* miss, 5303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Code::ExtraICState extra_ic_state) { 531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0: receiver 533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1: function to call 534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the function really is a function. 536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a1, miss); 537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a1, a3, a3); 538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); 539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Patch the receiver on the stack with the global proxy if 541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // necessary. 542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (object->IsGlobalObject()) { 543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); 544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, MemOperand(sp, arguments.immediate() * kPointerSize)); 545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 546257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Invoke the function. 5483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state) 5493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ? CALL_AS_FUNCTION 5503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : CALL_AS_METHOD; 5513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ InvokeFunction(a1, arguments, JUMP_FUNCTION, NullCallWrapper(), call_kind); 552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void PushInterceptorArguments(MacroAssembler* masm, 556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver, 557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register holder, 558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register name, 5593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj) { 560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(name); 5613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<InterceptorInfo> interceptor(holder_obj->GetNamedInterceptor()); 5623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!masm->isolate()->heap()->InNewSpace(*interceptor)); 563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch = name; 5643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(scratch, Operand(interceptor)); 565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(scratch, receiver, holder); 566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch, FieldMemOperand(scratch, InterceptorInfo::kDataOffset)); 567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(scratch); 568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void CompileCallLoadPropertyWithInterceptor( 5723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 5733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 5743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register holder, 5753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register name, 5763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj) { 577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PushInterceptorArguments(masm, receiver, holder, name, holder_obj); 578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference ref = 580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference(IC_Utility(IC::kLoadPropertyWithInterceptorOnly), 581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()); 5823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCEntryArgs(5); 5833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ PrepareCEntryFunction(ref); 584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CEntryStub stub(1); 586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallStub(&stub); 587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic const int kFastApiCallArguments = 3; 591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Reserves space for the extra arguments to FastHandleApiCall in the 594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// caller's frame. 595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// 596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// These arguments are set by CheckPrototypes and GenerateFastApiDirectCall. 597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void ReserveSpaceForFastApiCall(MacroAssembler* masm, 598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch) { 599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(Smi::FromInt(0) == 0); 600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < kFastApiCallArguments; i++) { 601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(zero_reg); 602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Undoes the effects of ReserveSpaceForFastApiCall. 607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void FreeSpaceForFastApiCall(MacroAssembler* masm) { 608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(kFastApiCallArguments); 6093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 6103100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6113100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 6123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateFastApiDirectCall(MacroAssembler* masm, 613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const CallOptimization& optimization, 614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int argc) { 615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[0] : holder (set by CheckPrototypes) 6173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- sp[4] : callee JS function 618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[8] : call data 6193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- sp[12] : last JS argument 620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ... 6213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // -- sp[(argc + 3) * 4] : first JS argument 622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[(argc + 4) * 4] : receiver 623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the function and setup the context. 6253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function = optimization.constant_function(); 6263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(t1, function); 627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(cp, FieldMemOperand(t1, JSFunction::kContextOffset)); 628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Pass the additional arguments FastHandleApiCall expects. 6303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<CallHandlerInfo> api_call_info = optimization.api_call_info(); 6313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> call_data(api_call_info->data()); 6323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (masm->isolate()->heap()->InNewSpace(*call_data)) { 6333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a0, api_call_info); 634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t2, FieldMemOperand(a0, CallHandlerInfo::kDataOffset)); 635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 6363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(t2, call_data); 637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store JS function and call data. 640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t1, MemOperand(sp, 1 * kPointerSize)); 641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t2, MemOperand(sp, 2 * kPointerSize)); 642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2 points to call data as expected by Arguments 644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // (refer to layout above). 645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a2, sp, Operand(2 * kPointerSize)); 646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kApiStackSpace = 4; 648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 6493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm, StackFrame::MANUAL); 650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ EnterExitFrame(false, kApiStackSpace); 651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // NOTE: the O32 abi requires a0 to hold a special pointer when returning a 653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // struct from the function (which is currently the case). This means we pass 654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the first argument in a1 instead of a0. TryCallApiFunctionAndReturn 655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // will handle setting up a0. 656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1 = v8::Arguments& 658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Arguments is built at sp + 1 (sp is a reserved spot for ra). 659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a1, sp, kPointerSize); 660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v8::Arguments::implicit_args = data 662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, MemOperand(a1, 0 * kPointerSize)); 663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v8::Arguments::values = last argument 664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t0, a2, Operand(argc * kPointerSize)); 665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t0, MemOperand(a1, 1 * kPointerSize)); 666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v8::Arguments::length_ = argc 667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t0, Operand(argc)); 668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t0, MemOperand(a1, 2 * kPointerSize)); 669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v8::Arguments::is_construct_call = 0 670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(zero_reg, MemOperand(a1, 3 * kPointerSize)); 671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kStackUnwindSpace = argc + kFastApiCallArguments + 1; 6733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address function_address = v8::ToCData<Address>(api_call_info->callback()); 6743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ApiFunction fun(function_address); 675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference ref = 676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference(&fun, 677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference::DIRECT_API_CALL, 678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()); 6793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AllowExternalCallThatCantCauseGC scope(masm); 6803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); 681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 68344f0eee88ff00398ff7f715fab053374d808c90dSteve Blockclass CallInterceptorCompiler BASE_EMBEDDED { 68444f0eee88ff00398ff7f715fab053374d808c90dSteve Block public: 68544f0eee88ff00398ff7f715fab053374d808c90dSteve Block CallInterceptorCompiler(StubCompiler* stub_compiler, 68644f0eee88ff00398ff7f715fab053374d808c90dSteve Block const ParameterCount& arguments, 6873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register name, 6883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Code::ExtraICState extra_ic_state) 68944f0eee88ff00398ff7f715fab053374d808c90dSteve Block : stub_compiler_(stub_compiler), 69044f0eee88ff00398ff7f715fab053374d808c90dSteve Block arguments_(arguments), 6913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch name_(name), 6923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch extra_ic_state_(extra_ic_state) {} 69344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 6943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void Compile(MacroAssembler* masm, 6953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 6963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 6973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 6983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult* lookup, 6993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 7003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 7013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 7023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 7033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(holder->HasNamedInterceptor()); 705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!holder->GetNamedInterceptor()->getter()->IsUndefined()); 706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(receiver, miss); 709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CallOptimization optimization(lookup); 710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (optimization.is_constant_call()) { 7113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCacheable(masm, object, receiver, scratch1, scratch2, scratch3, 7123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder, lookup, name, optimization, miss); 713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 7143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileRegular(masm, object, receiver, scratch1, scratch2, scratch3, 7153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, holder, miss); 716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch private: 7203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch void CompileCacheable(MacroAssembler* masm, 7213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 7223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 7233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 7243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 7253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 7263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 7273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult* lookup, 7283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 7293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const CallOptimization& optimization, 7303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss_label) { 731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(optimization.is_constant_call()); 732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!lookup->holder()->IsGlobalObject()); 733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm->isolate()->counters(); 734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int depth1 = kInvalidProtoDepth; 735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int depth2 = kInvalidProtoDepth; 736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool can_do_fast_api_call = false; 737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (optimization.is_simple_api_call() && 7383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch !lookup->holder()->IsGlobalObject()) { 7393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth1 = optimization.GetPrototypeDepthOfExpectedType( 7403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, interceptor_holder); 741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (depth1 == kInvalidProtoDepth) { 7423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth2 = optimization.GetPrototypeDepthOfExpectedType( 7433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder, Handle<JSObject>(lookup->holder())); 744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 7453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch can_do_fast_api_call = 7463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch depth1 != kInvalidProtoDepth || depth2 != kInvalidProtoDepth; 747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->call_const_interceptor(), 1, 7503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2); 751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (can_do_fast_api_call) { 753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->call_const_interceptor_fast_api(), 1, 754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, scratch2); 755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ReserveSpaceForFastApiCall(masm, scratch1); 756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps from receiver to interceptor's holder 759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // haven't changed and thus we can invoke interceptor. 760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_cleanup; 761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* miss = can_do_fast_api_call ? &miss_cleanup : miss_label; 762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register holder = 7633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 7643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 7653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth1, miss); 766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Invoke an interceptor and if it provides a value, 768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // branch to |regular_invoke|. 769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label regular_invoke; 770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LoadWithInterceptor(masm, receiver, holder, interceptor_holder, scratch2, 771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ®ular_invoke); 772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Interceptor returned nothing for this property. Try to use cached 774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // constant function. 775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps from interceptor's holder to constant function's 777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // holder haven't changed and thus we can use cached constant function. 7783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*interceptor_holder != lookup->holder()) { 779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch stub_compiler_->CheckPrototypes(interceptor_holder, receiver, 7803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 7813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 7823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, depth2, miss); 783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // CheckPrototypes has a side effect of fetching a 'holder' 785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // for API (object which is instanceof for the signature). It's 786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // safe to omit it here, as if present, it should be fetched 787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // by the previous CheckPrototypes. 788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(depth2 == kInvalidProtoDepth); 789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Invoke function. 792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (can_do_fast_api_call) { 7933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiDirectCall(masm, optimization, arguments_.immediate()); 794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 7953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_ic_state_) 7963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ? CALL_AS_FUNCTION 7973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : CALL_AS_METHOD; 798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ InvokeFunction(optimization.constant_function(), arguments_, 7993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch JUMP_FUNCTION, NullCallWrapper(), call_kind); 800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Deferred code for fast API call case---clean preallocated space. 803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (can_do_fast_api_call) { 804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_cleanup); 805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FreeSpaceForFastApiCall(masm); 806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss_label); 807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Invoke a regular function. 810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(®ular_invoke); 811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (can_do_fast_api_call) { 812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FreeSpaceForFastApiCall(masm); 813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 81444f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 81544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 81644f0eee88ff00398ff7f715fab053374d808c90dSteve Block void CompileRegular(MacroAssembler* masm, 8173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 81844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register receiver, 81944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 82044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 82144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch3, 8223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 82444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* miss_label) { 825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register holder = 826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch stub_compiler_->CheckPrototypes(object, receiver, interceptor_holder, 8273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2, scratch3, 8283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, miss_label); 829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call a runtime function to load the interceptor property. 8313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Save the name_ register across the call. 833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(name_); 834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 8353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch PushInterceptorArguments(masm, receiver, holder, name_, interceptor_holder); 836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CallExternalReference( 838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference( 839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IC_Utility(IC::kLoadPropertyWithInterceptorForCall), 840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()), 841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 5); 842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore the name_ register. 843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ pop(name_); 8443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 84544f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 84644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 84744f0eee88ff00398ff7f715fab053374d808c90dSteve Block void LoadWithInterceptor(MacroAssembler* masm, 84844f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register receiver, 84944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register holder, 8503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder_obj, 85144f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch, 85244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* interceptor_succeeded) { 8533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 8543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope scope(masm, StackFrame::INTERNAL); 8553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 8563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(holder, name_); 8573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm, 8583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 8593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder, 8603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_, 8613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_obj); 8623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_); // Restore the name. 8633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); // Restore the holder. 8643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If interceptor returns no-result sentinel, call the constant function. 866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(scratch, Heap::kNoInterceptorResultSentinelRootIndex); 867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(interceptor_succeeded, ne, v0, Operand(scratch)); 86844f0eee88ff00398ff7f715fab053374d808c90dSteve Block } 86944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 87044f0eee88ff00398ff7f715fab053374d808c90dSteve Block StubCompiler* stub_compiler_; 87144f0eee88ff00398ff7f715fab053374d808c90dSteve Block const ParameterCount& arguments_; 87244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register name_; 8733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Code::ExtraICState extra_ic_state_; 87444f0eee88ff00398ff7f715fab053374d808c90dSteve Block}; 87544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 87644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Generate code to check that a global property cell is empty. Create 879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// the property cell at compilation time if no cell exists for the 880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// property. 8813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCell(MacroAssembler* masm, 8823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> global, 8833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 8843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 8853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 8863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell = 8873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GlobalObject::EnsurePropertyCell(global, name); 888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(cell->value()->IsTheHole()); 8893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(scratch, Operand(cell)); 890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch, 891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(scratch, JSGlobalPropertyCell::kValueOffset)); 892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss, ne, scratch, Operand(at)); 894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Calls GenerateCheckPropertyCell for each global object in the prototype chain 898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// from object to (but not including) holder. 8993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochstatic void GenerateCheckPropertyCells(MacroAssembler* masm, 9003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 9013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 9023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 9033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch, 9043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 9053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> current = object; 9063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!current.is_identical_to(holder)) { 907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (current->IsGlobalObject()) { 9083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell(masm, 9093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject>::cast(current), 9103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, 9113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 9123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch miss); 913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 9143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch current = Handle<JSObject>(JSObject::cast(current->GetPrototype())); 915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Convert and store int passed in register ival to IEEE 754 single precision 920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// floating point value at memory location (dst + 4 * wordoffset) 921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// If FPU is available use it for conversion. 922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void StoreIntAsFloat(MacroAssembler* masm, 923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst, 924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register wordoffset, 925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register ival, 926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register fval, 927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch1, 928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch2) { 929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(ival, f0); 932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_s_w(f0, f0); 933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(scratch1, wordoffset, 2); 934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(scratch1, dst, scratch1); 935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ swc1(f0, MemOperand(scratch1, 0)); 936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // FPU is not available, do manual conversions. 938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 939257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_special, done; 940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Move sign bit from source to destination. This works because the sign 941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // bit in the exponent word of the double has the same position and polarity 942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // as the 2's complement sign bit in a Smi. 943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(kBinary32SignMask == 0x80000000u); 944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(fval, ival, Operand(kBinary32SignMask)); 946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Negate value if it is negative. 947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(scratch1, zero_reg, ival); 9483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movn(ival, scratch1, fval); 949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We have -1, 0 or 1, which we treat specially. Register ival contains 951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // absolute value: it is either equal to 1 (special case of -1 and 1), 952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // greater than 1 (not a special case) or less than 1 (special case of 0). 953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_special, gt, ival, Operand(1)); 954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For 1 or -1 we need to or in the 0 exponent (biased). 956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const uint32_t exponent_word_for_1 = 957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kBinary32ExponentBias << kBinary32ExponentShift; 958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(scratch1, ival, Operand(1)); 960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(scratch2, exponent_word_for_1); 961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(scratch2, fval, scratch2); 9623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(fval, scratch2, scratch1); // Only if ival is equal to 1. 963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done); 964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_special); 966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Count leading zeros. 967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Gets the wrong answer for 0, but we already checked for that case above. 968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register zeros = scratch2; 9693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Clz(zeros, ival); 970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compute exponent and or it into the exponent register. 972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(scratch1, (kBitsPerInt - 1) + kBinary32ExponentBias); 973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(scratch1, scratch1, zeros); 974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(scratch1, scratch1, kBinary32ExponentShift); 976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(fval, fval, scratch1); 977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Shift up the source chopping the top bit off. 979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(zeros, zeros, Operand(1)); 980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This wouldn't work for 1 and -1 as the shift would be 32 which means 0. 981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(ival, ival, zeros); 982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // And the top (top 20 bits). 983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(scratch1, ival, kBitsPerInt - kBinary32MantissaBits); 984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(fval, fval, scratch1); 985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(scratch1, wordoffset, 2); 989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(scratch1, dst, scratch1); 990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(fval, MemOperand(scratch1, 0)); 991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Convert unsigned integer with specified number of leading zeroes in binary 996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// representation to IEEE 754 double. 997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Integer to convert is passed in register hiword. 998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// Resulting double is returned in registers hiword:loword. 999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch// This functions does not work correctly for 0. 1000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochstatic void GenerateUInt2Double(MacroAssembler* masm, 1001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register hiword, 1002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register loword, 1003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register scratch, 1004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int leading_zeroes) { 1005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int meaningful_bits = kBitsPerInt - leading_zeroes - 1; 1006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int biased_exponent = HeapNumber::kExponentBias + meaningful_bits; 1007257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int mantissa_shift_for_hi_word = 1009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch meaningful_bits - HeapNumber::kMantissaBitsInTopWord; 1010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int mantissa_shift_for_lo_word = 1012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kBitsPerInt - mantissa_shift_for_hi_word; 1013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(scratch, biased_exponent << HeapNumber::kExponentShift); 1015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (mantissa_shift_for_hi_word > 0) { 1016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(loword, hiword, mantissa_shift_for_lo_word); 1017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(hiword, hiword, mantissa_shift_for_hi_word); 1018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(hiword, scratch, hiword); 1019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(loword, zero_reg); 1021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(hiword, hiword, mantissa_shift_for_hi_word); 1022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(hiword, scratch, hiword); 1023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If least significant bit of biased exponent was not 1 it was corrupted 1026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // by most significant bit of mantissa so we should fix that. 1027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!(biased_exponent & 1)) { 1028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(scratch, 1 << HeapNumber::kExponentShift); 1029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ nor(scratch, scratch, scratch); 1030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ and_(hiword, hiword, scratch); 1031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 10353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef __ 10363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#define __ ACCESS_MASM(masm()) 10373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 10393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochRegister StubCompiler::CheckPrototypes(Handle<JSObject> object, 104044f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register object_reg, 10413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 104244f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register holder_reg, 104344f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch1, 104444f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch2, 10453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 104644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int save_at_depth, 104744f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* miss) { 1048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure there's no overlap between holder and object registers. 1049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!scratch1.is(object_reg) && !scratch1.is(holder_reg)); 1050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!scratch2.is(object_reg) && !scratch2.is(holder_reg) 1051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch && !scratch2.is(scratch1)); 1052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Keep track of the current object in register reg. 1054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register reg = object_reg; 1055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int depth = 0; 1056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (save_at_depth == depth) { 1058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(reg, MemOperand(sp)); 1059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the maps in the prototype chain. 1062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Traverse the prototype chain from the object and do map checks. 10633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> current = object; 10643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch while (!current.is_identical_to(holder)) { 10653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ++depth; 1066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Only global objects and objects that do not require access 1068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // checks are allowed in stubs. 1069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(current->IsJSGlobalProxy() || !current->IsAccessCheckNeeded()); 1070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 10713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> prototype(JSObject::cast(current->GetPrototype())); 1072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!current->HasFastProperties() && 1073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch !current->IsJSGlobalObject() && 1074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch !current->IsJSGlobalProxy()) { 1075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!name->IsSymbol()) { 10763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name = factory()->LookupSymbol(name); 1077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 10783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(current->property_dictionary()->FindEntry(*name) == 1079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StringDictionary::kNotFound); 1080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 10813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateDictionaryNegativeLookup(masm(), miss, reg, name, 10823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, scratch2); 1083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch1, FieldMemOperand(reg, HeapObject::kMapOffset)); 10853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 1086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 10873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 10883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> current_map(current->map()); 10893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(reg, scratch1, current_map, miss, DONT_DO_SMI_CHECK, 10903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ALLOW_ELEMENT_TRANSITION_MAPS); 10913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check access rights to the global object. This has to happen after 10923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the map check so that we know that the object is actually a global 10933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // object. 1094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (current->IsJSGlobalProxy()) { 10953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckAccessGlobalProxy(reg, scratch2, miss); 1096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 10973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch reg = holder_reg; // From now on the object will be in holder_reg. 1098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 10993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (heap()->InNewSpace(*prototype)) { 11003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The prototype is in new space; we cannot store a reference to it 11013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // in the code. Load it from the map. 11023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(reg, FieldMemOperand(scratch1, Map::kPrototypeOffset)); 11033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 11043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The prototype is in old space; load it directly. 11053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(reg, Operand(prototype)); 1106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (save_at_depth == depth) { 1110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(reg, MemOperand(sp)); 1111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Go to the next object in the prototype chain. 1114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch current = prototype; 1115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 111785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Log the check depth. 111885b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch LOG(masm()->isolate(), IntEvent("check-maps-depth", depth + 1)); 11193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 11203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check the holder map. 11213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(reg, scratch1, Handle<Map>(current->map()), miss, 11223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 11233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Perform security check for access to the global object. 1125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(holder->IsJSGlobalProxy() || !holder->IsAccessCheckNeeded()); 1126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (holder->IsJSGlobalProxy()) { 1127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckAccessGlobalProxy(reg, scratch1, miss); 11283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 1129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 11303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // If we've skipped any global objects, it's not enough to verify that 11313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // their maps haven't changed. We also need to check that the property 11323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // cell for the property is still empty. 11333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCells(masm(), object, holder, name, scratch1, miss); 1134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the register containing the holder. 1136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return reg; 113744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 113844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 113944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 11403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadField(Handle<JSObject> object, 11413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 11423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register receiver, 11433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, 11443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch2, 114544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch3, 11463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu int index, 11473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 11483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* miss) { 1149257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 11503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(receiver, miss); 1151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps haven't changed. 11533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = CheckPrototypes( 11543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch object, receiver, holder, scratch1, scratch2, scratch3, name, miss); 1155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateFastPropertyLoad(masm(), v0, reg, holder, index); 1156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 11573100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadConstant(Handle<JSObject> object, 11613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 11623100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register receiver, 11633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, 11643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch2, 116544f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch3, 11663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 11673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 11683100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* miss) { 1169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 1170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(receiver, miss, scratch1); 1171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps haven't changed. 11737a930e02c0b52d70d022ed255db551895dfe1157Ben Murdoch CheckPrototypes(object, receiver, holder, 11747a930e02c0b52d70d022ed255db551895dfe1157Ben Murdoch scratch1, scratch2, scratch3, name, miss); 1175257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the constant value. 11773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadHeapObject(v0, value); 1178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 11793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 11803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11813100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 11823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadCallback(Handle<JSObject> object, 11833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 11843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register receiver, 11853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register name_reg, 11863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1, 11873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2, 11883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3, 11893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 11903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 11913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 1192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 1193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(receiver, miss, scratch1); 1194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps haven't changed. 11963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register reg = CheckPrototypes(object, receiver, holder, scratch1, 11973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2, scratch3, name, miss); 1198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Build AccessorInfo::args_ list on the stack and push property name below 1200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the exit frame to make GC aware of them and store pointers to them. 1201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(receiver); 1202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(scratch2, sp); // scratch2 = AccessorInfo::args_ 12033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (heap()->InNewSpace(callback->data())) { 12043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(scratch3, callback); 1205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch3, FieldMemOperand(scratch3, AccessorInfo::kDataOffset)); 1206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 12073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(scratch3, Handle<Object>(callback->data())); 1208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(reg, scratch3, name_reg); 1210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(a2, scratch2); // Saved in case scratch2 == a1. 1211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(a1, sp); // a1 (first argument - see note below) = Handle<String> 1212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // NOTE: the O32 abi requires a0 to hold a special pointer when returning a 1214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // struct from the function (which is currently the case). This means we pass 1215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the arguments in a1-a2 instead of a0-a1. TryCallApiFunctionAndReturn 1216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // will handle setting up a0. 1217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kApiStackSpace = 1; 12193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm(), StackFrame::MANUAL); 122085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ EnterExitFrame(false, kApiStackSpace); 12213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Create AccessorInfo instance on the stack above the exit frame with 12233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // scratch2 (internal::Object** args_) as the data. 1224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, MemOperand(sp, kPointerSize)); 1225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2 (second argument - see note above) = AccessorInfo& 1226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a2, sp, kPointerSize); 1227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 12283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch const int kStackUnwindSpace = 4; 12293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Address getter_address = v8::ToCData<Address>(callback->getter()); 12303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ApiFunction fun(getter_address); 1231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference ref = 1232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference(&fun, 1233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference::DIRECT_GETTER_CALL, 1234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm()->isolate()); 12353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CallApiFunctionAndReturn(ref, kStackUnwindSpace); 12363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 12373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 12393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid StubCompiler::GenerateLoadInterceptor(Handle<JSObject> object, 12403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> interceptor_holder, 12413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu LookupResult* lookup, 12423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register receiver, 12433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register name_reg, 12443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch1, 12453100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Register scratch2, 124644f0eee88ff00398ff7f715fab053374d808c90dSteve Block Register scratch3, 12473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 12483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu Label* miss) { 1249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(interceptor_holder->HasNamedInterceptor()); 1250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!interceptor_holder->GetNamedInterceptor()->getter()->IsUndefined()); 1251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 1253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(receiver, miss); 1254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // So far the most popular follow ups for interceptor loads are FIELD 1256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // and CALLBACKS, so inline only them, other cases may be added 1257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // later. 1258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool compile_followup_inline = false; 12593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->IsFound() && lookup->IsCacheable()) { 1260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (lookup->type() == FIELD) { 1261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch compile_followup_inline = true; 1262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else if (lookup->type() == CALLBACKS && 12633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetCallbackObject()->IsAccessorInfo()) { 12643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compile_followup_inline = 12653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())->getter() != NULL; 1266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (compile_followup_inline) { 1270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Compile the interceptor call, followed by inline code to load the 1271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // property from further up the prototype chain if the call fails. 1272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps haven't changed. 1273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, scratch2, scratch3, 1275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch name, miss); 1276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(holder_reg.is(receiver) || holder_reg.is(scratch1)); 1277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Save necessary data before invoking an interceptor. 1279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Requires a frame to make GC aware of pushed pointers. 12803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch { 12813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FrameScope frame_scope(masm(), StackFrame::INTERNAL); 12823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 12833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // CALLBACKS case needs a receiver to be passed into C++ callback. 12843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(receiver, holder_reg, name_reg); 12853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 12863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Push(holder_reg, name_reg); 12873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 12883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Invoke an interceptor. Note: map checks from receiver to 12893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // interceptor's holder has been compiled before (see a caller 12903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // of this method). 12913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CompileCallLoadPropertyWithInterceptor(masm(), 12923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver, 12933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch holder_reg, 12943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name_reg, 12953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch interceptor_holder); 12963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if interceptor provided a value for property. If it's 12973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the case, return immediately. 12983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label interceptor_failed; 12993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch1, Heap::kNoInterceptorResultSentinelRootIndex); 13003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&interceptor_failed, eq, v0, Operand(scratch1)); 13013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch frame_scope.GenerateLeaveFrame(); 13023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 130385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 13043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&interceptor_failed); 13053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(name_reg); 13063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(holder_reg); 13073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (lookup->type() == CALLBACKS && !receiver.is(holder_reg)) { 13083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ pop(receiver); 13093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 13103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Leave the internal frame. 131185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 1312257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps from interceptor's holder to lookup's holder 1313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // haven't changed. And load lookup's holder into |holder| register. 13143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (*interceptor_holder != lookup->holder()) { 1315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch holder_reg = CheckPrototypes(interceptor_holder, 1316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch holder_reg, 13173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 1318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, 1319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch2, 1320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch3, 1321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch name, 1322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch miss); 1323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1325257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (lookup->type() == FIELD) { 1326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We found FIELD property in prototype chain of interceptor's holder. 1327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Retrieve a field from field's holder. 1328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateFastPropertyLoad(masm(), v0, holder_reg, 13293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(lookup->holder()), 13303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch lookup->GetFieldIndex()); 1331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We found CALLBACKS property in prototype chain of interceptor's 1334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // holder. 1335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(lookup->type() == CALLBACKS); 13363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback( 13373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch AccessorInfo::cast(lookup->GetCallbackObject())); 1338257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(callback->getter() != NULL); 1339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tail call to runtime. 1341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Important invariant in CALLBACKS case: the code above must be 1342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // structured to never clobber |receiver| register. 13433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(scratch2, callback); 1344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // holder_reg is either receiver or scratch1. 1345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!receiver.is(holder_reg)) { 1346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(scratch1.is(holder_reg)); 1347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(receiver, holder_reg); 1348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch3, 1349257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); 1350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(scratch3, scratch2, name_reg); 1351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(receiver); 1353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(scratch3, 1354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FieldMemOperand(scratch2, AccessorInfo::kDataOffset)); 1355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(holder_reg, scratch3, scratch2, name_reg); 1356257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1357257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1358257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference ref = 1359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference(IC_Utility(IC::kLoadCallbackProperty), 1360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm()->isolate()); 1361257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallExternalReference(ref, 5, 1); 1362257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1363257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { // !compile_followup_inline 1364257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Call the runtime system to load the interceptor. 1365257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps haven't changed. 1366257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register holder_reg = CheckPrototypes(object, receiver, interceptor_holder, 1367257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch scratch1, scratch2, scratch3, 1368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch name, miss); 1369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch PushInterceptorArguments(masm(), receiver, holder_reg, 1370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch name_reg, interceptor_holder); 1371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference ref = ExternalReference( 1373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch IC_Utility(IC::kLoadPropertyWithInterceptorForLoad), masm()->isolate()); 1374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallExternalReference(ref, 5, 1); 1375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 13763100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 13773100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 13793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateNameCheck(Handle<String> name, Label* miss) { 1380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::KEYED_CALL_IC) { 13813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(miss, ne, a2, Operand(name)); 1382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 138344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 13846ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13856ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 13863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateGlobalReceiverCheck(Handle<JSObject> object, 13873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 13883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 138944f0eee88ff00398ff7f715fab053374d808c90dSteve Block Label* miss) { 1390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(holder->IsGlobalObject()); 1391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the number of arguments. 1393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 1394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the receiver from the stack. 1396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(sp, argc * kPointerSize)); 1397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps haven't changed. 13993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(a0, miss); 1400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CheckPrototypes(object, a0, holder, a3, a1, t0, name, miss); 14013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 14023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateLoadFunctionFromCell( 14053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 14063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 14073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label* miss) { 1408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the value from the cell. 14093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a3, Operand(cell)); 1410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset)); 1411257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1412257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the cell contains the same function. 14133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (heap()->InNewSpace(*function)) { 1414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We can't embed a pointer to a function in new space so we have 1415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // to verify that the shared function info is unchanged. This has 1416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the nice side effect that multiple closures based on the same 1417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // function can all use this call IC. Before we load through the 1418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // function, we have to verify that it still is a function. 1419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a1, miss); 1420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a1, a3, a3); 1421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss, ne, a3, Operand(JS_FUNCTION_TYPE)); 1422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1423257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the shared function info. Make sure it hasn't changed. 1424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a3, Handle<SharedFunctionInfo>(function->shared())); 1425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 1426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(miss, ne, t0, Operand(a3)); 1427257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 14283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(miss, ne, a1, Operand(function)); 1429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 14303100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 14313100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14323100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 14333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid CallStubCompiler::GenerateMissBranch() { 14343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = 1435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch isolate()->stub_cache()->ComputeCallMiss(arguments().immediate(), 1436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kind_, 14373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch extra_state_); 14383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(code, RelocInfo::CODE_TARGET); 14396ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 14406ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14416ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14423ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallField(Handle<JSObject> object, 14433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 144444f0eee88ff00398ff7f715fab053374d808c90dSteve Block int index, 14453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 1447257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 1448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 1449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 1450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 1451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &miss); 1453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 1455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the receiver of the function from the stack into a0. 1457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(sp, argc * kPointerSize)); 1458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 1459257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a0, &miss, t0); 1460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do the right check and compute the holder register. 1462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register reg = CheckPrototypes(object, a0, holder, a1, a3, t0, name, &miss); 1463257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateFastPropertyLoad(masm(), a1, reg, holder, index); 1464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 14653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); 1466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle call cache miss. 1468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 14693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 1472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(FIELD, name); 14736ded16be15dd865a9b21ea304d5273c8be299c87Steve Block} 14746ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14756ded16be15dd865a9b21ea304d5273c8be299c87Steve Block 14763ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPushCall( 14773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 14783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 14793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 14803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 14813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 1483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 1484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 1485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 1486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ... 1487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[argc * 4] : receiver 1488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 14893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If object is not an array, bail out to regular call. 14913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 14923100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 14943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &miss); 14963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 1497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver = a1; 1498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the receiver from the stack. 1500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 1501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(receiver, MemOperand(sp, argc * kPointerSize)); 1502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 1504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(receiver, &miss); 1505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps haven't changed. 15073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, a3, v0, t0, 15083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 1509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (argc == 0) { 1511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Nothing to do, just return the length. 1512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 1513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label call_builtin; 15173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (argc == 1) { // Otherwise fall through to call the builtin. 15183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label attempt_to_grow_elements; 1519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 15203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements = t2; 15213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register end_elements = t1; 15223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements array of the object. 15233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); 152485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 15253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check that the elements are in fast mode and writable. 15263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(elements, 15273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch v0, 15283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedArrayMapRootIndex, 15293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_builtin, 15303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 15315d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 1532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the array's length into v0 and calculate new length. 1533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 1534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTagSize == 1); 1535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 1536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(v0, v0, Operand(Smi::FromInt(argc))); 1537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 15383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Get the elements' length. 1539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); 1540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if we could survive without allocation. 1542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&attempt_to_grow_elements, gt, v0, Operand(t0)); 1543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 15443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check if value is a smi. 15453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label with_write_barrier; 15463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t0, MemOperand(sp, (argc - 1) * kPointerSize)); 15473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(t0, &with_write_barrier); 15483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Save new length. 1550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 1551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 15523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 1553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We may need a register containing the address end_elements below, 1554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // so write back the value in end_elements. 1555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); 1556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(end_elements, elements, end_elements); 1557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kEndElementsOffset = 1558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FixedArray::kHeaderSize - kHeapObjectTag - argc * kPointerSize; 15593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(end_elements, end_elements, kEndElementsOffset); 15603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(t0, MemOperand(end_elements)); 1561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for a smi. 1563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&with_write_barrier); 15673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, FieldMemOperand(receiver, HeapObject::kMapOffset)); 15693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (FLAG_smi_only_arrays && !FLAG_trace_elements_transitions) { 15713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label fast_object, not_fast_object; 15723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(a3, t3, ¬_fast_object); 15733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&fast_object); 15743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // In case of fast smi-only, convert to fast object, otherwise bail out. 15753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(¬_fast_object); 15763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastSmiOnlyElements(a3, t3, &call_builtin); 15773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // edx: receiver 15783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // r3: map 15793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ONLY_ELEMENTS, 15803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FAST_ELEMENTS, 15813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a3, 15823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch t3, 15833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &call_builtin); 15843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(a2, receiver); 15853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsTransitionGenerator::GenerateSmiOnlyToObject(masm()); 15863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&fast_object); 15873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 15883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(a3, a3, &call_builtin); 15893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 15903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Save new length. 15923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 15933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 15943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the value. 15953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We may need a register containing the address end_elements below, 15963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // so write back the value in end_elements. 15973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); 15983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(end_elements, elements, end_elements); 15993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(end_elements, end_elements, kEndElementsOffset); 16003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(t0, MemOperand(end_elements)); 16013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 16023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(elements, 16033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch end_elements, 16043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch t0, 16053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kRAHasNotBeenSaved, 16063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs, 16073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, 16083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch OMIT_SMI_CHECK); 1609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&attempt_to_grow_elements); 1613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0: array's length + 1. 1614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t0: elements' length. 1615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!FLAG_inline_new) { 1617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&call_builtin); 1618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 16203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a2, MemOperand(sp, (argc - 1) * kPointerSize)); 16213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Growing elements that are SMI-only requires special handling in case 16223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // the new element is non-Smi. For now, delegate to the builtin. 16233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label no_fast_elements_check; 16243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(a2, &no_fast_elements_check); 16253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(t3, FieldMemOperand(receiver, HeapObject::kMapOffset)); 16263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckFastObjectElements(t3, t3, &call_builtin); 16273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&no_fast_elements_check); 16283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 1629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference new_space_allocation_top = 1630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference::new_space_allocation_top_address( 1631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm()->isolate()); 1632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference new_space_allocation_limit = 1633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference::new_space_allocation_limit_address( 1634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm()->isolate()); 1635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int kAllocationDelta = 4; 1637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load top and check if it is the end of elements. 1638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(end_elements, v0, kPointerSizeLog2 - kSmiTagSize); 1639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(end_elements, elements, end_elements); 1640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(end_elements, end_elements, Operand(kEndElementsOffset)); 1641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t3, Operand(new_space_allocation_top)); 16423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, MemOperand(t3)); 16433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&call_builtin, ne, end_elements, Operand(a3)); 1644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t5, Operand(new_space_allocation_limit)); 1646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t5, MemOperand(t5)); 16473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(a3, a3, Operand(kAllocationDelta * kPointerSize)); 16483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&call_builtin, hi, a3, Operand(t5)); 1649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We fit and could grow elements. 1651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Update new_space_allocation_top. 16523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a3, MemOperand(t3)); 1653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Push the argument. 16543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a2, MemOperand(end_elements)); 1655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fill the rest with holes. 16563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(a3, Heap::kTheHoleValueRootIndex); 1657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 1; i < kAllocationDelta; i++) { 16583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(a3, MemOperand(end_elements, i * kPointerSize)); 1659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Update elements' and array's sizes. 1662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(v0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 1663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t0, t0, Operand(Smi::FromInt(kAllocationDelta))); 1664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); 1665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Elements are in new space, so write barrier is not required. 1667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_builtin); 1671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPush, 1672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm()->isolate()), 1673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch argc + 1, 1674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1); 1675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle call cache miss. 1678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 16793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 1682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(function); 1683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 16863ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileArrayPopCall( 16873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 16883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 16893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 16903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 16913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 1693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 1694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 1695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 1696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ... 1697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[argc * 4] : receiver 1698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 1699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If object is not an array, bail out to regular call. 17013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSArray() || !cell.is_null()) return Handle<Code>::null(); 1702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1703257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss, return_undefined, call_builtin; 1704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver = a1; 1705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register elements = a3; 1706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &miss); 1707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the receiver from the stack. 1709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 1710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(receiver, MemOperand(sp, argc * kPointerSize)); 1711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 1712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(receiver, &miss); 1713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps haven't changed. 17153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), receiver, holder, elements, 17163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch t0, v0, name, &miss); 1717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array of the object. 1719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(elements, FieldMemOperand(receiver, JSArray::kElementsOffset)); 1720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the elements are in fast mode and writable. 1722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(elements, 1723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch v0, 1724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Heap::kFixedArrayMapRootIndex, 1725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &call_builtin, 1726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DONT_DO_SMI_CHECK); 1727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the array's length into t0 and calculate new length. 1729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 1730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(t0, t0, Operand(Smi::FromInt(1))); 1731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&return_undefined, lt, t0, Operand(zero_reg)); 1732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the last element. 1734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t2, Heap::kTheHoleValueRootIndex); 1735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTagSize == 1); 1736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 1737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We can't address the last element in one operation. Compute the more 1738257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // expensive shift first, and use an offset later on. 1739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t1, t0, kPointerSizeLog2 - kSmiTagSize); 1740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(elements, elements, t1); 1741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); 1742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&call_builtin, eq, v0, Operand(t2)); 1743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1744257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set the array's length. 1745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 1746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fill with the hole. 1748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t2, MemOperand(elements, FixedArray::kHeaderSize - kHeapObjectTag)); 1749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&return_undefined); 1753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); 1754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&call_builtin); 1758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallExternalReference(ExternalReference(Builtins::c_ArrayPop, 1759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm()->isolate()), 1760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch argc + 1, 1761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1); 1762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle call cache miss. 1764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 17653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 1768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(function); 1769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 1770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 17723ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharCodeAtCall( 17733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 17743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 17753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 17763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 17773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1778257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 1779257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : function name 1780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 1781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 1782257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ... 1783257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[argc * 4] : receiver 1784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 1785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If object is not a string, bail out to regular call. 17873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 1788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 1790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 1791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label name_miss; 1792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label index_out_of_range; 1793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 1795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 17973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index_out_of_range_label = &miss; 1800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &name_miss); 1803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps starting from the prototype haven't changed. 1805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), 1806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Context::STRING_FUNCTION_INDEX, 1807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch v0, 1808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &miss); 18093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 18103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 18113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch v0, holder, a1, a3, t0, name, &miss); 1812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver = a1; 1814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register index = t1; 1815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result = v0; 1816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(receiver, MemOperand(sp, argc * kPointerSize)); 1817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (argc > 0) { 1818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); 1819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 1821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1822257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 18233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharCodeAtGenerator generator(receiver, 18243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 18253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 18263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 18273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 18283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 18293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 18303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 1831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StubRuntimeCallHelper call_helper; 18353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 1836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (index_out_of_range.is_linked()) { 1838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&index_out_of_range); 1839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(v0, Heap::kNanValueRootIndex); 1840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 1845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore function name in a2. 18463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a2, name); 1847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&name_miss); 18483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 1851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(function); 18523100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 18533100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18543100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 18553ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringCharAtCall( 18563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 18573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 18583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 18593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 18603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 1862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : function name 1863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 1864257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 1865257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ... 1866257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[argc * 4] : receiver 1867257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 1868257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If object is not a string, bail out to regular call. 18703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsString() || !cell.is_null()) return Handle<Code>::null(); 1871257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 1873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 1874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label name_miss; 1875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label index_out_of_range; 1876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label* index_out_of_range_label = &index_out_of_range; 1877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (kind_ == Code::CALL_IC && 18783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch (CallICBase::StringStubState::decode(extra_state_) == 1879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch DEFAULT_STRING_STUB)) { 1880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch index_out_of_range_label = &miss; 1881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1882257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &name_miss); 1883257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps starting from the prototype haven't changed. 1885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateDirectLoadGlobalFunctionPrototype(masm(), 1886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Context::STRING_FUNCTION_INDEX, 1887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch v0, 1888257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &miss); 18893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(!object.is_identical_to(holder)); 18903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>(JSObject::cast(object->GetPrototype())), 18913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch v0, holder, a1, a3, t0, name, &miss); 1892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver = v0; 1894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register index = t1; 18953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = a3; 1896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register result = v0; 1897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(receiver, MemOperand(sp, argc * kPointerSize)); 1898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (argc > 0) { 1899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(index, MemOperand(sp, (argc - 1) * kPointerSize)); 1900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 1901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(index, Heap::kUndefinedValueRootIndex); 1902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 19043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharAtGenerator generator(receiver, 19053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index, 19063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 19073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch result, 19083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a string. 19093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss, // When not a number. 19103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch index_out_of_range_label, 19113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STRING_INDEX_IS_NUMBER); 19123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 1913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StubRuntimeCallHelper call_helper; 19173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 1918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (index_out_of_range.is_linked()) { 1920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&index_out_of_range); 1921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(v0, Heap::kEmptyStringRootIndex); 1922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 1927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore function name in a2. 19283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a2, name); 1929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&name_miss); 19303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 1931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 1933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(function); 19343100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 19353100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19363100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 19373ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileStringFromCharCodeCall( 19383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 19393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 19403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 19413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 19423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 1943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 1944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : function name 1945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 1946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 1947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ... 1948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[argc * 4] : receiver 1949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 1950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 1952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the object is not a JSObject or we got an unexpected number of 1954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // arguments, bail out to the regular call. 19553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 1956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 1958257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &miss); 1959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 19603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 1961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, 1 * kPointerSize)); 1962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 1964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a1, &miss); 1965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 19663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, v0, a3, t0, 19673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 1968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 19693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 19703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 19713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 1972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadFunctionFromCell(cell, function, &miss); 1973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 1974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the char code argument. 1976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register code = a1; 1977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(code, MemOperand(sp, 0 * kPointerSize)); 1978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the code is a smi. 1980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow; 1981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 1982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(code, &slow); 1983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert the smi code to uint16. 1985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(code, code, Operand(Smi::FromInt(0xffff))); 1986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 19873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch StringCharFromCodeGenerator generator(code, v0); 19883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateFast(masm()); 1989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 1990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 1991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StubRuntimeCallHelper call_helper; 19933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch generator.GenerateSlow(masm(), call_helper); 1994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tail call the full function. We do not have to patch the receiver 1996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // because the function makes no use of it. 1997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 19983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 19993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 2000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: function name. 20033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 20063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 20073100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 20083100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 20093100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 20103ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathFloorCall( 20113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 20123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 20133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 20143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 20153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : function name 2018257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 2020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ... 2021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[argc * 4] : receiver 2022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 20243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!CpuFeatures::IsSupported(FPU)) { 20253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return Handle<Code>::null(); 20263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 202785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 20283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CpuFeatures::Scope scope_fpu(FPU); 2029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 2030257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the object is not a JSObject or we got an unexpected number of 2031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // arguments, bail out to the regular call. 20323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 2033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss, slow; 2035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &miss); 2036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 20373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 2038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, 1 * kPointerSize)); 2039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 2040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a1, &miss); 20413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, 20423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2043257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 20443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 20453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 20463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadFunctionFromCell(cell, function, &miss); 2048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the (only) argument into v0. 2051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, MemOperand(sp, 0 * kPointerSize)); 2052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the argument is a smi, just return. 2054257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 2055257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t0, v0, Operand(kSmiTagMask)); 2056257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1, eq, t0, Operand(zero_reg)); 2057257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(eq, t0, Operand(zero_reg)); 2058257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2059257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); 2060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label wont_fit_smi, no_fpu_error, restore_fcsr_and_return; 2062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If fpu is enabled, we use the floor instruction. 2064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the HeapNumber value. 2066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); 2067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Backup FCSR. 2069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cfc1(a3, FCSR); 2070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Clearing FCSR clears the exception mask with no side-effects. 2071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ctc1(zero_reg, FCSR); 2072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Convert the argument to an integer. 2073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ floor_w_d(f0, f0); 2074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Start checking for special cases. 2076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the argument exponent and clear the sign bit. 2077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t1, FieldMemOperand(v0, HeapNumber::kValueOffset + kPointerSize)); 2078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t2, t1, Operand(~HeapNumber::kSignMask)); 2079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(t2, t2, HeapNumber::kMantissaBitsInTopWord); 2080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Retrieve FCSR and check for fpu errors. 2082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cfc1(t5, FCSR); 20833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ And(t5, t5, Operand(kFCSRExceptionFlagMask)); 2084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&no_fpu_error, eq, t5, Operand(zero_reg)); 2085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for NaN, Infinity, and -Infinity. 2087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // They are invariant through a Math.Floor call, so just 2088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // return the original argument. 2089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(t3, t2, Operand(HeapNumber::kExponentMask 2090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch >> HeapNumber::kMantissaBitsInTopWord)); 2091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&restore_fcsr_and_return, eq, t3, Operand(zero_reg)); 2092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We had an overflow or underflow in the conversion. Check if we 2093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have a big exponent. 2094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If greater or equal, the argument is already round and in v0. 2095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&restore_fcsr_and_return, ge, t3, 2096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(HeapNumber::kMantissaBits)); 2097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&wont_fit_smi); 2098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&no_fpu_error); 2100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Move the result back to v0. 2101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mfc1(v0, f0); 2102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the result fits into a smi. 2103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a1, v0, Operand(0x40000000)); 2104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&wont_fit_smi, lt, a1, Operand(zero_reg)); 2105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tag the result. 2106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 2107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(v0, v0, kSmiTagSize); 2108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for -0. 2110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&restore_fcsr_and_return, ne, v0, Operand(zero_reg)); 2111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t1 already holds the HeapNumber exponent. 2112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t0, t1, Operand(HeapNumber::kSignMask)); 2113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If our HeapNumber is negative it was -0, so load its address and return. 2114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Else v0 is loaded with 0, so we can also just return. 2115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&restore_fcsr_and_return, eq, t0, Operand(zero_reg)); 2116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, MemOperand(sp, 0 * kPointerSize)); 2117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&restore_fcsr_and_return); 2119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore FCSR and return. 2120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ctc1(a3, FCSR); 2121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 2123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&wont_fit_smi); 2126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore FCSR and fall to slow case. 2127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ctc1(a3, FCSR); 2128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 2130257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tail call the full function. We do not have to patch the receiver 2131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // because the function makes no use of it. 21323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 21333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 2134257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2135257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2136257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: function name. 21373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 21403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 21413100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 21423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 21433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 21443ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileMathAbsCall( 21453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 21463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 21473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 21483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 21493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2150257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2151257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : function name 2152257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[(argc - n - 1) * 4] : arg[n] (zero-based) 2154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ... 2155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- sp[argc * 4] : receiver 2156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 2159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the object is not a JSObject or we got an unexpected number of 2160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // arguments, bail out to the regular call. 21613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject() || argc != 1) return Handle<Code>::null(); 2162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 216485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 21653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateNameCheck(name, &miss); 21663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (cell.is_null()) { 2167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, 1 * kPointerSize)); 2168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 2169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a1, &miss); 21703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, v0, a3, t0, 21713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 21733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(cell->value() == *function); 21743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateGlobalReceiverCheck(Handle<JSObject>::cast(object), holder, name, 21753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadFunctionFromCell(cell, function, &miss); 2177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the (only) argument into v0. 2180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(v0, MemOperand(sp, 0 * kPointerSize)); 2181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the argument is a smi. 2183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_smi; 2184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch STATIC_ASSERT(kSmiTag == 0); 2185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(v0, ¬_smi); 2186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do bitwise not or do nothing depending on the sign of the 2188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // argument. 2189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(t0, v0, kBitsPerInt - 1); 2190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(a1, v0, t0); 2191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Add 1 or do nothing depending on the sign of the argument. 2193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(v0, a1, t0); 2194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the result is still negative, go to the slow case. 2196257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This only happens for the most negative smi. 2197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow; 2198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&slow, lt, v0, Operand(zero_reg)); 2199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Smi case done. 2201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 2202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the argument is a heap number and load its exponent and 2205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // sign. 2206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_smi); 2207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckMap(v0, a1, Heap::kHeapNumberMapRootIndex, &slow, DONT_DO_SMI_CHECK); 2208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); 2209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the sign of the argument. If the argument is positive, 2211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // just return it. 2212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label negative_sign; 2213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t0, a1, Operand(HeapNumber::kSignMask)); 2214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&negative_sign, ne, t0, Operand(zero_reg)); 2215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 2216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the argument is negative, clear the sign, and return a new 2219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // number. 2220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&negative_sign); 2221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(a1, a1, Operand(HeapNumber::kSignMask)); 2222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); 2223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t2, Heap::kHeapNumberMapRootIndex); 2224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(v0, t0, t1, t2, &slow); 2225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a1, FieldMemOperand(v0, HeapNumber::kExponentOffset)); 2226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); 2227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Drop(argc + 1); 2228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tail call the full function. We do not have to patch the receiver 2231257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // because the function makes no use of it. 2232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 22333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 22343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), CALL_AS_METHOD); 2235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: function name. 22383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 22413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return cell.is_null() ? GetCode(function) : GetCode(NORMAL, name); 22423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 22433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 22443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 22453ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileFastApiCall( 224644f0eee88ff00398ff7f715fab053374d808c90dSteve Block const CallOptimization& optimization, 22473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Object> object, 22483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 22493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 22503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 22513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = isolate()->counters(); 2254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(optimization.is_simple_api_call()); 2256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Bail out if object is a global object as we don't want to 2257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // repatch it to global receiver. 22583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (object->IsGlobalObject()) return Handle<Code>::null(); 22593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!cell.is_null()) return Handle<Code>::null(); 22603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!object->IsJSObject()) return Handle<Code>::null(); 2261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int depth = optimization.GetPrototypeDepthOfExpectedType( 22623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>::cast(object), holder); 22633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (depth == kInvalidProtoDepth) return Handle<Code>::null(); 2264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss, miss_before_stack_reserved; 2266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &miss_before_stack_reserved); 2268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the receiver from the stack. 2270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 2271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, argc * kPointerSize)); 2272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 2274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a1, &miss_before_stack_reserved); 2275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->call_const(), 1, a0, a3); 2277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->call_const_fast_api(), 1, a0, a3); 2278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ReserveSpaceForFastApiCall(masm(), a0); 2280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps haven't changed and find a Holder as a side effect. 22823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, name, 2283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch depth, &miss); 2284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 22853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateFastApiDirectCall(masm(), optimization, argc); 2286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FreeSpaceForFastApiCall(masm()); 2289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_before_stack_reserved); 22913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(function); 22953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 22963100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 22973100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 22983ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallConstant(Handle<Object> object, 22993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 23003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 23013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 230244f0eee88ff00398ff7f715fab053374d808c90dSteve Block CheckType check) { 2303257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2304257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2305257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2306257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2307257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasCustomCallGenerator(function)) { 23083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, 23093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell>::null(), 23103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, name); 23113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 23123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 2313257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2314257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2315257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2316257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &miss); 2318257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2319257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the receiver from the stack. 2320257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 2321257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, argc * kPointerSize)); 2322257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2323257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver isn't a smi. 2324257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (check != NUMBER_CHECK) { 23253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(a1, &miss); 2326257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2327257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2328257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Make sure that it's okay not to patch the on stack receiver 2329257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // unless we're doing a receiver map check. 2330257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(!object->IsGlobalObject() || check == RECEIVER_MAP_CHECK); 2331257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch switch (check) { 2332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case RECEIVER_MAP_CHECK: 2333257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(masm()->isolate()->counters()->call_const(), 2334257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1, a0, a3); 2335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2336257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps haven't changed. 23373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes(Handle<JSObject>::cast(object), a1, holder, a0, a3, t0, 23383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch name, &miss); 2339257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2340257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Patch the receiver on the stack with the global proxy if 2341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // necessary. 2342257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (object->IsGlobalObject()) { 2343257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a1, GlobalObject::kGlobalReceiverOffset)); 2344257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, MemOperand(sp, argc * kPointerSize)); 2345257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2348257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch case STRING_CHECK: 23493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2350257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the object is a two-byte string or a symbol. 2351257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a1, a3, a3); 2352257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss, Ugreater_equal, a3, Operand(FIRST_NONSTRING_TYPE)); 2353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps starting from the prototype haven't changed. 2354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateDirectLoadGlobalFunctionPrototype( 2355257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm(), Context::STRING_FUNCTION_INDEX, a0, &miss); 23563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 23573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 23583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a0, holder, a3, a1, t0, name, &miss); 23593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 236085b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 236185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 236285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 23633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 23643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 23653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 23663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case NUMBER_CHECK: 23673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label fast; 2369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the object is a smi or a heap number. 23703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(a1, &fast); 2371257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a1, a0, a0); 2372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss, ne, a0, Operand(HEAP_NUMBER_TYPE)); 2373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&fast); 2374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps starting from the prototype haven't changed. 2375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateDirectLoadGlobalFunctionPrototype( 2376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm(), Context::NUMBER_FUNCTION_INDEX, a0, &miss); 23773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 23783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 23793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a0, holder, a3, a1, t0, name, &miss); 23803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 238185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Calling non-strict non-builtins with a value as the receiver 238285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // requires boxing. 238385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ jmp(&miss); 23843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 23853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch break; 23863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 23873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case BOOLEAN_CHECK: 23883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (function->IsBuiltin() || !function->shared()->is_classic_mode()) { 2389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label fast; 2390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the object is a boolean. 2391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t0, Heap::kTrueValueRootIndex); 2392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&fast, eq, a1, Operand(t0)); 2393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t0, Heap::kFalseValueRootIndex); 2394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss, ne, a1, Operand(t0)); 2395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&fast); 2396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the maps starting from the prototype haven't changed. 2397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateDirectLoadGlobalFunctionPrototype( 2398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm(), Context::BOOLEAN_FUNCTION_INDEX, a0, &miss); 23993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CheckPrototypes( 24003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject>(JSObject::cast(object->GetPrototype())), 24013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a0, holder, a3, a1, t0, name, &miss); 24023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 24033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Calling non-strict non-builtins with a value as the receiver 24043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // requires boxing. 24053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&miss); 2406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 2408257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 24103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 24113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch ? CALL_AS_FUNCTION 24123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch : CALL_AS_METHOD; 24133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeFunction( 24143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch function, arguments(), JUMP_FUNCTION, NullCallWrapper(), call_kind); 2415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle call cache miss. 2417257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2418257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 24193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(function); 24233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 24243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 24253100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 24263ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallInterceptor(Handle<JSObject> object, 24273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 24283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2431257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2432257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &miss); 2437257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the number of arguments. 2439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 24403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LookupPostInterceptor(holder, name, &lookup); 2442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the receiver from the stack. 2444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a1, MemOperand(sp, argc * kPointerSize)); 2445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 24463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallInterceptorCompiler compiler(this, arguments(), a2, extra_state_); 24473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch compiler.Compile(masm(), object, holder, name, &lookup, a1, a3, t0, a0, 24483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Move returned value, the function to call, to a1. 2451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(a1, v0); 2452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Restore receiver. 2453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a0, MemOperand(sp, argc * kPointerSize)); 2454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 24553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCallFunction(masm(), object, arguments(), &miss, extra_state_); 2456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle call cache miss. 2458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 24593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2460257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2461257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2462257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(INTERCEPTOR, name); 24633100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 24643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 24653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 24663ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> CallStubCompiler::CompileCallGlobal( 24673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 24683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 24693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 24703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function, 24713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2477257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (HasCustomCallGenerator(function)) { 24783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> code = CompileCustomCall(object, holder, cell, function, name); 24793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // A null handle means bail out to the regular compiler code below. 24803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (!code.is_null()) return code; 2481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateNameCheck(name, &miss); 2485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the number of arguments. 2487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch const int argc = arguments().immediate(); 2488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateGlobalReceiverCheck(object, holder, name, &miss); 2489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadFunctionFromCell(cell, function, &miss); 2490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Patch the receiver on the stack with the global proxy if 2492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // necessary. 2493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (object->IsGlobalObject()) { 2494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a0, GlobalObject::kGlobalReceiverOffset)); 2495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, MemOperand(sp, argc * kPointerSize)); 2496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 24983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Set up the context (function already in r1). 2499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(cp, FieldMemOperand(a1, JSFunction::kContextOffset)); 2500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Jump to the cached code (tail call). 2502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm()->isolate()->counters(); 2503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->call_global_inline(), 1, a3, t0); 2504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ParameterCount expected(function->shared()->formal_parameter_count()); 25053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CallKind call_kind = CallICBase::Contextual::decode(extra_state_) 2506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ? CALL_AS_FUNCTION 2507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch : CALL_AS_METHOD; 25083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // We call indirectly through the code field in the function to 25093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // allow recompilation to take effect without changing any of the 25103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // call sites. 25113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(a3, FieldMemOperand(a1, JSFunction::kCodeEntryOffset)); 25123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ InvokeCode(a3, expected, arguments(), JUMP_FUNCTION, 25133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch NullCallWrapper(), call_kind); 2514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle call cache miss. 2516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->call_global_inline_miss(), 1, a1, a3); 25183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateMissBranch(); 2519257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(NORMAL, name); 25223100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 25233100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 25243100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 25253ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreField(Handle<JSObject> object, 252644f0eee88ff00398ff7f715fab053374d808c90dSteve Block int index, 25273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 25283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : value 2531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Name register might be clobbered. 25383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, a1, a2, a3, &miss); 2539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a2, Operand(Handle<String>(name))); // Restore name. 2541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss(); 2542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 2543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 25453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 25463100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 25473100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 25483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 25493ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreCallback( 25503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 25513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback, 25523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : value 2555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the map of the object hasn't changed. 25623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(a1, a3, Handle<Map>(object->map()), &miss, 25633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Perform global security token check if needed. 2566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (object->IsJSGlobalProxy()) { 2567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckAccessGlobalProxy(a1, a3, &miss); 2568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stub never generated for non-global objects that require access 2571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // checks. 2572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(object->IsJSGlobalProxy() || !object->IsAccessCheckNeeded()); 2573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(a1); // Receiver. 25753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a3, Operand(callback)); // Callback info. 2576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(a3, a2, a0); 2577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do tail-call to the runtime system. 2579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference store_callback_property = 2580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference(IC_Utility(IC::kStoreCallbackProperty), 2581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm()->isolate()); 2582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallExternalReference(store_callback_property, 4, 1); 2583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle store cache miss. 2585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); 2587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 2588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2590257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(CALLBACKS, name); 259144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 259244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 259344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 25943ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreInterceptor( 25953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 25963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : value 2599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the map of the object hasn't changed. 26063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(a1, a3, Handle<Map>(receiver->map()), &miss, 26073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DO_SMI_CHECK, ALLOW_ELEMENT_TRANSITION_MAPS); 2608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Perform global security token check if needed. 2610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (receiver->IsJSGlobalProxy()) { 2611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ CheckAccessGlobalProxy(a1, a3, &miss); 2612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Stub is never generated for non-global objects that require access 2615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // checks. 2616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(receiver->IsJSGlobalProxy() || !receiver->IsAccessCheckNeeded()); 2617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(a1, a2, a0); // Receiver, name, value. 2619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a0, Operand(Smi::FromInt(strict_mode_))); 2621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ push(a0); // Strict mode. 2622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Do tail-call to the runtime system. 2624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference store_ic_property = 2625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ExternalReference(IC_Utility(IC::kStoreInterceptorProperty), 2626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm()->isolate()); 2627257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallExternalReference(store_ic_property, 4, 1); 2628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle store cache miss. 2630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm()->isolate()->builtins()->Builtins::StoreIC_Miss(); 2632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 2633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(INTERCEPTOR, name); 263644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 263744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 263844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 26393ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> StoreStubCompiler::CompileStoreGlobal( 26403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> object, 26413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 26423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : value 2645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the map of the global has not changed. 2652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a1, HeapObject::kMapOffset)); 2653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss, ne, a3, Operand(Handle<Map>(object->map()))); 2654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the value in the cell is not the hole. If it is, this 2656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // cell could have been deleted and reintroducing the global needs 2657257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // to update the property details in the property dictionary of the 2658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // global object. We bail out to the runtime system to do that. 26593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(t0, Operand(cell)); 2660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); 2661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t2, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset)); 2662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss, eq, t1, Operand(t2)); 2663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Store the value in the cell. 2665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a0, FieldMemOperand(t0, JSGlobalPropertyCell::kValueOffset)); 2666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, a0); // Stored value must be returned in v0. 26673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Cells are always rescanned, so no write barrier here. 26683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 2669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm()->isolate()->counters(); 2670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->named_store_global_inline(), 1, a1, a3); 2671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle store cache miss. 2674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->named_store_global_inline_miss(), 1, a1, a3); 2676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm()->isolate()->builtins()->StoreIC_Miss(); 2677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 2678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(NORMAL, name); 268144f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 268244f0eee88ff00398ff7f715fab053374d808c90dSteve Block 268344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 26843ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadNonexistent(Handle<String> name, 26853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 26863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> last) { 2687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : receiver 2689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the receiver is not a smi. 2694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a0, &miss); 2695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the maps of the full prototype chain. 2697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CheckPrototypes(object, a0, last, a3, a1, t0, name, &miss); 2698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If the last object in the prototype chain is a global object, 2700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // check that the global property cell is empty. 2701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (last->IsGlobalObject()) { 27023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateCheckPropertyCell( 27033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm(), Handle<GlobalObject>::cast(last), name, a1, &miss); 2704257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2705257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return undefined if maps of the full prototype chain is still the same. 2707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(v0, Heap::kUndefinedValueRootIndex); 2708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2711257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::LOAD_IC); 2712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 27143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NONEXISTENT, factory()->empty_string()); 271544f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 271644f0eee88ff00398ff7f715fab053374d808c90dSteve Block 271744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 27183ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadField(Handle<JSObject> object, 27193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 272044f0eee88ff00398ff7f715fab053374d808c90dSteve Block int index, 27213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : receiver 2724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, a0); 2730257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadField(object, holder, v0, a3, a1, t0, index, name, &miss); 2732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2733257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::LOAD_IC); 2734257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(FIELD, name); 27373100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 27383100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27393100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadCallback( 27413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 27423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 27433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 2745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : receiver 2747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 27513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(object, holder, a0, a2, a3, a1, t0, callback, name, 27523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::LOAD_IC); 2755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2756257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2757257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(CALLBACKS, name); 27583100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 27593100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27603100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27613ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadConstant(Handle<JSObject> object, 27623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value, 27643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : receiver 2767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2770257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2771257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2772257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadConstant(object, holder, a0, a3, a1, t0, value, name, &miss); 2773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::LOAD_IC); 2775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2776257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2777257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(CONSTANT_FUNCTION, name); 27783100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 27793100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27803100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 27813ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadInterceptor(Handle<JSObject> object, 27823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 27833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2784257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : receiver 2786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2787257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2788257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- [sp] : receiver 2789257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 27923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2793257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LookupPostInterceptor(holder, name, &lookup); 27943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(object, holder, &lookup, a0, a2, a3, a1, t0, name, 2795257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &miss); 2796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::LOAD_IC); 2798257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2799257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(INTERCEPTOR, name); 28013100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 28023100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28033100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28043ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> LoadStubCompiler::CompileLoadGlobal( 28053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> object, 28063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<GlobalObject> holder, 28073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSGlobalPropertyCell> cell, 28083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_dont_delete) { 2810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : receiver 2812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : name 2813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the map of the global has not changed. 28183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(a0, &miss); 2819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CheckPrototypes(object, a0, holder, a3, t0, a1, name, &miss); 2820257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2821257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the value from the cell. 28223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a3, Operand(cell)); 2823257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, FieldMemOperand(a3, JSGlobalPropertyCell::kValueOffset)); 2824257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check for deleted property if property can actually be deleted. 2826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (!is_dont_delete) { 2827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 2828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss, eq, t0, Operand(at)); 2829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 2830257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, t0); 2832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm()->isolate()->counters(); 2833257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->named_load_global_stub(), 1, a1, a3); 2834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 2835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->named_load_global_stub_miss(), 1, a1, a3); 2838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::LOAD_IC); 2839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(NORMAL, name); 28423100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 28433100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28443100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28453ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadField(Handle<String> name, 28463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 284844f0eee88ff00398ff7f715fab053374d808c90dSteve Block int index) { 2849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 2852257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2854257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the key is the cached one. 28573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a0, Operand(name)); 2858257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadField(receiver, holder, a1, a2, a3, t0, index, name, &miss); 2860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2862257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(FIELD, name); 28643100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 28653100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28663100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28673ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadCallback( 28683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<AccessorInfo> callback) { 2872257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2873257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 2875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2876257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2877257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2878257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the key is the cached one. 28803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a0, Operand(name)); 2881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 28823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadCallback(receiver, holder, a1, a0, a2, a3, t0, callback, name, 28833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss); 2884257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2885257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2886257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2887257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(CALLBACKS, name); 28883100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 28893100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28903100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 28913ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadConstant( 28923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name, 28933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 28943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 28953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> value) { 2896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2897257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 2899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the key is the cached one. 29043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a0, Operand(name)); 2905257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadConstant(receiver, holder, a1, a2, a3, t0, value, name, &miss); 2907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 2911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(CONSTANT_FUNCTION, name); 291244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 291344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 291444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 29153ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadInterceptor( 29163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> receiver, 29173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSObject> holder, 29183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2921257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 2922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the key is the cached one. 29273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a0, Operand(name)); 2928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 29293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch LookupResult lookup(isolate()); 2930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch LookupPostInterceptor(holder, name, &lookup); 29313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateLoadInterceptor(receiver, holder, &lookup, a1, a0, a2, a3, t0, name, 2932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch &miss); 2933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2934257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(INTERCEPTOR, name); 293744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 293844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 293944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 29403ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadArrayLength( 29413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 2945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the key is the cached one. 29503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a0, Operand(name)); 2951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2952257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadArrayLength(masm(), a1, a2, &miss); 2953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(CALLBACKS, name); 295744f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 295844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 295944f0eee88ff00398ff7f715fab053374d808c90dSteve Block 29603ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadStringLength( 29613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 2965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm()->isolate()->counters(); 2970257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->keyed_load_string_length(), 1, a2, a3); 2971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the key is the cached one. 29733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a0, Operand(name)); 2974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadStringLength(masm(), a1, a2, a3, &miss, true); 2976257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 2977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DecrementCounter(counters->keyed_load_string_length(), 1, a2, a3); 2978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2979257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 2980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(CALLBACKS, name); 298244f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 298344f0eee88ff00398ff7f715fab053374d808c90dSteve Block 298444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 29853ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadFunctionPrototype( 29863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 2987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 2988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 2989257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 2990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 2991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 2992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 2993257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm()->isolate()->counters(); 2995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); 2996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 2997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check the name hasn't changed. 29983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a0, Operand(name)); 2999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadFunctionPrototype(masm(), a1, a2, a3, &miss); 3001257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 3002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DecrementCounter(counters->keyed_load_function_prototype(), 1, a2, a3); 3003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateLoadMiss(masm(), Code::KEYED_LOAD_IC); 3004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(CALLBACKS, name); 300644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 300744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 300844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 30093ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadElement( 30103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 3011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 3013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 3014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 3015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3016589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 30173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = KeyedLoadElementStub(elements_kind).GetCode(); 30183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 30193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(a1, a2, receiver_map, stub, DO_SMI_CHECK); 3020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedLoadIC_Miss(); 3022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 3023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 30253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 3026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 30293ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedLoadStubCompiler::CompileLoadPolymorphic( 30303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 30313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_ics) { 3032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 3034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 3035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 3036257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3037257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3038257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a1, &miss); 3039257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3040257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 3041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(a1, HeapObject::kMapOffset)); 3042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int current = 0; current < receiver_count; ++current) { 30433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(handler_ics->at(current), RelocInfo::CODE_TARGET, 30443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch eq, a2, Operand(receiver_maps->at(current))); 3045257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 3048257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = isolate()->builtins()->KeyedLoadIC_Miss(); 3049257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 3050257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 30523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 305344f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 305444f0eee88ff00398ff7f715fab053374d808c90dSteve Block 305544f0eee88ff00398ff7f715fab053374d808c90dSteve Block 30563ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreField(Handle<JSObject> object, 305744f0eee88ff00398ff7f715fab053374d808c90dSteve Block int index, 30583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> transition, 30593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<String> name) { 3060257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3061257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : value 3062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : key 3063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : receiver 3064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 3065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm()->isolate()->counters(); 3070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->keyed_store_field(), 1, a3, t0); 3071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the name has not changed. 30733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss, ne, a1, Operand(name)); 3074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3 is used as scratch register. a1 and a2 keep their values if a jump to 3076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the miss label is generated. 30773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch GenerateStoreField(masm(), object, index, transition, a2, a1, a3, &miss); 3078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 3079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ DecrementCounter(counters->keyed_store_field(), 1, a3, t0); 3081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = masm()->isolate()->builtins()->KeyedStoreIC_Miss(); 3082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 3083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 30853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(transition.is_null() ? FIELD : MAP_TRANSITION, name); 308644f0eee88ff00398ff7f715fab053374d808c90dSteve Block} 308744f0eee88ff00398ff7f715fab053374d808c90dSteve Block 308844f0eee88ff00398ff7f715fab053374d808c90dSteve Block 30893ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStoreElement( 30903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Map> receiver_map) { 3091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : value 3093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : key 3094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : receiver 3095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 3096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a3 : scratch 3097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3098589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind = receiver_map->elements_kind(); 3099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch bool is_js_array = receiver_map->instance_type() == JS_ARRAY_TYPE; 31003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 31013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedStoreElementStub(is_js_array, elements_kind, grow_mode_).GetCode(); 31023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 31033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ DispatchMap(a2, a3, receiver_map, stub, DO_SMI_CHECK); 3104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = isolate()->builtins()->KeyedStoreIC_Miss(); 3106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 3107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 31093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string()); 3110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3111257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3112257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 31133ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> KeyedStoreStubCompiler::CompileStorePolymorphic( 31143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* receiver_maps, 31153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch CodeHandleList* handler_stubs, 31163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MapHandleList* transitioned_maps) { 3117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 3118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : value 3119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : key 3120257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : receiver 3121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 3122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a3 : scratch 3123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3124257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss; 3125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfSmi(a2, &miss); 3126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int receiver_count = receiver_maps->length(); 3128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a2, HeapObject::kMapOffset)); 31293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 0; i < receiver_count; ++i) { 31303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (transitioned_maps->at(i).is_null()) { 31313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET, eq, 31323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch a3, Operand(receiver_maps->at(i))); 31333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 31343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label next_map; 31353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&next_map, ne, a3, Operand(receiver_maps->at(i))); 31363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(a3, Operand(transitioned_maps->at(i))); 31373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(handler_stubs->at(i), RelocInfo::CODE_TARGET); 31383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&next_map); 31393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 3140257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3141257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3142257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss); 3143257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = isolate()->builtins()->KeyedStoreIC_Miss(); 3144257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 3145257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3146257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 31473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch return GetCode(NORMAL, factory()->empty_string(), MEGAMORPHIC); 31483100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 31493100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 31503100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 31513ef787dbeca8a5fb1086949cda830dccee07bfbdBen MurdochHandle<Code> ConstructStubCompiler::CompileConstructStub( 31523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<JSFunction> function) { 3153257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0 : argc 3154257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1 : constructor 3155257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ra : return address 3156257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // [sp] : last argument 3157257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label generic_stub_call; 3158257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3159257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use t7 for holding undefined which is used in several places below. 3160257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t7, Heap::kUndefinedValueRootIndex); 3161257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3162257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef ENABLE_DEBUGGER_SUPPORT 3163257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check to see whether there are any break points in the function code. If 3164257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // there are jump to the generic constructor stub which calls the actual 3165257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // code for the function thereby hitting the break points. 3166257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t5, FieldMemOperand(a1, JSFunction::kSharedFunctionInfoOffset)); 3167257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(t5, SharedFunctionInfo::kDebugInfoOffset)); 3168257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&generic_stub_call, ne, a2, Operand(t7)); 3169257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 3170257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3171257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the initial map and verify that it is in fact a map. 3172257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: constructor function 3173257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t7: undefined 3174257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(a1, JSFunction::kPrototypeOrInitialMapOffset)); 31753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(a2, &generic_stub_call); 3176257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(a2, a3, t0); 3177257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&generic_stub_call, ne, t0, Operand(MAP_TYPE)); 3178257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3179257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#ifdef DEBUG 3180257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Cannot construct functions this way. 3181257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: argc 3182257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: constructor function 3183257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: initial map 3184257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t7: undefined 3185257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(a3, FieldMemOperand(a2, Map::kInstanceTypeOffset)); 3186257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Check(ne, "Function constructed by construct stub.", 3187257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch a3, Operand(JS_FUNCTION_TYPE)); 3188257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch#endif 3189257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3190257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Now allocate the JSObject in new space. 3191257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: argc 3192257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: constructor function 3193257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: initial map 3194257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t7: undefined 3195257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(a3, FieldMemOperand(a2, Map::kInstanceSizeOffset)); 31963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(a3, t4, t5, t6, &generic_stub_call, SIZE_IN_WORDS); 3197257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3198257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocated the JSObject, now initialize the fields. Map is set to initial 3199257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // map and properties and elements are set to empty fixed array. 3200257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: argc 3201257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: constructor function 3202257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: initial map 3203257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: object size (in words) 3204257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t4: JSObject (not tagged) 3205257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t7: undefined 3206257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t6, Heap::kEmptyFixedArrayRootIndex); 3207257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t5, t4); 3208257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, MemOperand(t5, JSObject::kMapOffset)); 3209257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t6, MemOperand(t5, JSObject::kPropertiesOffset)); 3210257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t6, MemOperand(t5, JSObject::kElementsOffset)); 3211257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t5, t5, Operand(3 * kPointerSize)); 3212257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(0 * kPointerSize, JSObject::kMapOffset); 3213257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(1 * kPointerSize, JSObject::kPropertiesOffset); 3214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT_EQ(2 * kPointerSize, JSObject::kElementsOffset); 3215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Calculate the location of the first argument. The stack contains only the 3218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // argc arguments. 3219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(a1, a0, kPointerSizeLog2); 3220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a1, a1, sp); 3221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3222257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fill all the in-object properties with undefined. 3223257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: argc 3224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: first argument 3225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: object size (in words) 3226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t4: JSObject (not tagged) 3227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t5: First in-object property of JSObject (not tagged) 3228257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t7: undefined 3229257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fill the initialized properties with a constant value or a passed argument 3230257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // depending on the this.x = ...; assignment in the function. 32313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<SharedFunctionInfo> shared(function->shared()); 3232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = 0; i < shared->this_property_assignments_count(); i++) { 3233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (shared->IsThisPropertyAssignmentArgument(i)) { 3234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label not_passed, next; 3235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check if the argument assigned to the property is actually passed. 3236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int arg_number = shared->GetThisPropertyAssignmentArgument(i); 3237257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(¬_passed, less_equal, a0, Operand(arg_number)); 3238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Argument passed - find it on the stack. 3239257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, MemOperand(a1, (arg_number + 1) * -kPointerSize)); 3240257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, MemOperand(t5)); 3241257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t5, t5, kPointerSize); 3242257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ jmp(&next); 3243257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(¬_passed); 3244257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set the property to undefined. 3245257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t7, MemOperand(t5)); 3246257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t5, t5, Operand(kPointerSize)); 3247257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&next); 3248257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3249257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Set the property to the constant value. 3250257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Object> constant(shared->GetThisPropertyAssignmentConstant(i)); 3251257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(a2, Operand(constant)); 3252257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, MemOperand(t5)); 3253257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t5, t5, kPointerSize); 3254257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3255257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3256257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3257257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Fill the unused in-object property fields with undefined. 3258257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch ASSERT(function->has_initial_map()); 3259257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch for (int i = shared->this_property_assignments_count(); 3260257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch i < function->initial_map()->inobject_properties(); 3261257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch i++) { 3262257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t7, MemOperand(t5)); 3263257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t5, t5, kPointerSize); 3264257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3265257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3266257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a0: argc 3267257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t4: JSObject (not tagged) 3268257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Move argc to a1 and the JSObject to return to v0 and tag it. 3269257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(a1, a0); 3270257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, t4); 3271257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(v0, v0, Operand(kHeapObjectTag)); 3272257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3273257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0: JSObject 3274257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a1: argc 3275257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Remove caller arguments and receiver from the stack and return. 3276257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t0, a1, kPointerSizeLog2); 3277257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(sp, sp, t0); 3278257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(sp, sp, Operand(kPointerSize)); 3279257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Counters* counters = masm()->isolate()->counters(); 3280257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->constructed_objects(), 1, a1, a2); 3281257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter(counters->constructed_objects_stub(), 1, a1, a2); 3282257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3283257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3284257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Jump to the generic stub in case the specialized code cannot handle the 3285257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // construction. 3286257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&generic_stub_call); 3287257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> generic_construct_stub = 3288257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm()->isolate()->builtins()->JSConstructStubGeneric(); 3289257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(generic_construct_stub, RelocInfo::CODE_TARGET); 3290257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3291257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Return the generated code. 3292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return GetCode(); 32933100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} 32943100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 32953100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 32963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#undef __ 32973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch#define __ ACCESS_MASM(masm) 3298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadDictionaryElement( 33013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 33023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ---------- S t a t e -------------- 33033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ra : return address 33043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a0 : key 33053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a1 : receiver 33063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 33073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label slow, miss_force_generic; 33081e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key = a0; 33103fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register receiver = a1; 33111e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 33123fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key, &miss_force_generic); 33133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset)); 33143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sra(a2, a0, kSmiTagSize); 33153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadFromNumberDictionary(&slow, t0, a0, v0, a2, a3, t1); 33163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Ret(); 3317257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33183fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Slow case, key and receiver still in a0 and a1. 33193fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow); 33203fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ IncrementCounter( 33213fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->counters()->keyed_load_external_array_slow(), 33223fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 1, a2, a3); 33233fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Entry registers are intact. 33243fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ---------- S t a t e -------------- 33253fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ra : return address 33263fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a0 : key 33273fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a1 : receiver 33283fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 33293fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 33303fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 33313fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(slow_ic, RelocInfo::CODE_TARGET); 3332257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33333fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Miss case, call the runtime. 33343fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 3335257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ---------- S t a t e -------------- 33373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ra : return address 33383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a0 : key 33393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a1 : receiver 33403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 3341257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 33423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 33433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 33443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 33453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 3346257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3347257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3348589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdochstatic bool IsElementTypeSigned(ElementsKind elements_kind) { 33493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3350589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3351589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3352589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3353257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return true; 3354257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3355589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3356589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3357589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3358589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3359257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return false; 3360257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3361589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3362589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 33633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3364589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 3365589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3366589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3367589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 3368257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 3369257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch return false; 3370257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 33713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch return false; 3372257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3373257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3374257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3375257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadExternalArray( 3376257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3377589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 3378257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- S t a t e -------------- 3379257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 3380257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 3381257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 3382257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3383257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic, slow, failed_allocation; 3384257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3385257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register key = a0; 3386257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver = a1; 3387257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3388257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3389257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3390257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3391257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 3392257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(key, &miss_force_generic); 3393257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3394257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 3395257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: elements array 3396257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3397257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the index is in range. 3398257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); 3399257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sra(t2, key, kSmiTagSize); 3400257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Unsigned comparison catches both negative and too-large values. 340169a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Branch(&miss_force_generic, Ugreater_equal, key, Operand(t1)); 3402257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3403257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); 3404257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: base pointer of external storage 3405257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3406257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // We are not untagging smi key and instead work with it 3407257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // as if it was premultiplied by 2. 3408589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch STATIC_ASSERT((kSmiTag == 0) && (kSmiTagSize == 1)); 3409257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3410257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register value = a2; 34113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3412589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3413257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(t2, key, 1); 3414257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t3, a3, t2); 3415257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lb(value, MemOperand(t3, 0)); 3416257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3417589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3418589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 3419257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(t2, key, 1); 3420257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t3, a3, t2); 3421257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lbu(value, MemOperand(t3, 0)); 3422257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3423589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3424257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t3, a3, key); 3425257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lh(value, MemOperand(t3, 0)); 3426257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3427589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 3428257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t3, a3, key); 3429257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lhu(value, MemOperand(t3, 0)); 3430257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3431589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3432589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 3433257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t2, key, 1); 3434257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t3, a3, t2); 3435257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(value, MemOperand(t3, 0)); 3436257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3437589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3438257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t3, t2, 2); 3439257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t3, a3, t3); 3440257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3441257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3442257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lwc1(f0, MemOperand(t3, 0)); 3443257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3444257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(value, MemOperand(t3, 0)); 3445257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3446257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3447589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3448257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t2, key, 2); 3449257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t3, a3, t2); 3450257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3451257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3452257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f0, MemOperand(t3, 0)); 3453257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3454257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t3: pointer to the beginning of the double we want to load. 3455257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, MemOperand(t3, 0)); 3456257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, MemOperand(t3, Register::kSizeInBytes)); 3457257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3458257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3459589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 34603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3461589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3462589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3463589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 3464257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 3465257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3466257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3467257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3468257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For integer array types: 3469257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: value 3470257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For float array type: 3471257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // f0: value (if FPU is supported) 3472257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: value (if FPU is not supported) 3473257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For double array type: 3474257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // f0: value (if FPU is supported) 3475257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2/a3: value (if FPU is not supported) 3476257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3477589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_INT_ELEMENTS) { 3478257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For the Int and UnsignedInt array types, we need to see whether 3479257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the value can be represented in a Smi. If not, we need to convert 3480257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // it to a HeapNumber. 3481257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label box_int; 3482257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(t3, value, Operand(0xC0000000)); // Non-smi value gives neg result. 3483257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&box_int, lt, t3, Operand(zero_reg)); 3484257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tag integer as smi and return it. 3485257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(v0, value, kSmiTagSize); 3486257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3487257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3488257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&box_int); 3489257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a HeapNumber for the result and perform int-to-double 3490257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // conversion. 3491257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The arm version uses a temporary here to save r0, but we don't need to 3492257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // (a0 is not modified). 3493257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t1, Heap::kHeapNumberMapRootIndex); 3494257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(v0, a3, t0, t1, &slow); 3495257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3496257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3497257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3498257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mtc1(value, f0); 3499257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_w(f0, f0); 3500257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f0, MemOperand(v0, HeapNumber::kValueOffset - kHeapObjectTag)); 3501257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3502257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3503257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst1 = t2; 3504257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register dst2 = t3; 3505257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::Destination dest = 3506257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::kCoreRegisters; 3507257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::ConvertIntToDouble(masm, 3508257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value, 3509257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dest, 3510257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch f0, 3511257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dst1, 3512257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch dst2, 3513257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch t1, 3514257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch f2); 3515257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(dst1, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); 3516257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(dst2, FieldMemOperand(v0, HeapNumber::kExponentOffset)); 3517257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3518257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3519589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_UNSIGNED_INT_ELEMENTS) { 3520257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The test is different for unsigned int values. Since we need 3521257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // the value to be in the range of a positive smi, we can't 3522257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // handle either of the top two bits being set in the value. 3523257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3524257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3525257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label pl_box_int; 3526257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t2, value, Operand(0xC0000000)); 3527257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&pl_box_int, ne, t2, Operand(zero_reg)); 3528257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3529257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // It can fit in an Smi. 3530257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tag integer as smi and return it. 3531257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(v0, value, kSmiTagSize); 3532257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3533257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3534257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&pl_box_int); 3535257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a HeapNumber for the result and perform int-to-double 3536257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // conversion. Don't use a0 and a1 as AllocateHeapNumber clobbers all 3537257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // registers - also when jumping due to exhausted young space. 3538257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); 3539257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(v0, t2, t3, t6, &slow); 3540257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3541257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This is replaced by a macro: 3542257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // __ mtc1(value, f0); // LS 32-bits. 3543257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // __ mtc1(zero_reg, f1); // MS 32-bits are all zero. 3544257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // __ cvt_d_l(f0, f0); // Use 64 bit conv to get correct unsigned 32-bit. 3545257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 354669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Cvt_d_uw(f0, value, f22); 3547257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3548257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f0, MemOperand(v0, HeapNumber::kValueOffset - kHeapObjectTag)); 3549257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3550257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3551257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3552257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check whether unsigned integer fits into smi. 3553257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label box_int_0, box_int_1, done; 3554257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t2, value, Operand(0x80000000)); 3555257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&box_int_0, ne, t2, Operand(zero_reg)); 3556257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t2, value, Operand(0x40000000)); 3557257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&box_int_1, ne, t2, Operand(zero_reg)); 3558257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3559257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tag integer as smi and return it. 3560257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(v0, value, kSmiTagSize); 3561257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3562257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3563257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register hiword = value; // a2. 3564257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register loword = a3; 3565257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3566257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&box_int_0); 3567257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Integer does not have leading zeros. 3568257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateUInt2Double(masm, hiword, loword, t0, 0); 3569257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done); 3570257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3571257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&box_int_1); 3572257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Integer has one leading zero. 3573257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch GenerateUInt2Double(masm, hiword, loword, t0, 1); 3574257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3575257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3576257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 3577257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Integer was converted to double in registers hiword:loword. 3578257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Wrap it into a HeapNumber. Don't use a0 and a1 as AllocateHeapNumber 3579257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // clobbers all registers - also when jumping due to exhausted young 3580257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // space. 3581257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); 3582257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(t2, t3, t5, t6, &slow); 3583257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3584257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(hiword, FieldMemOperand(t2, HeapNumber::kExponentOffset)); 3585257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(loword, FieldMemOperand(t2, HeapNumber::kMantissaOffset)); 3586257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3587257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, t2); 3588257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3589257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3590589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 3591257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // For the floating-point array type, we need to always allocate a 3592257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // HeapNumber. 3593257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3594257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3595257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a HeapNumber for the result. Don't use a0 and a1 as 3596257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // AllocateHeapNumber clobbers all registers - also when jumping due to 3597257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // exhausted young space. 3598257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); 3599257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(v0, t3, t5, t6, &slow); 3600257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The float (single) value is already in fpu reg f0 (if we use float). 3601257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_d_s(f0, f0); 3602257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f0, MemOperand(v0, HeapNumber::kValueOffset - kHeapObjectTag)); 3603257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3604257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3605257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a HeapNumber for the result. Don't use a0 and a1 as 3606257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // AllocateHeapNumber clobbers all registers - also when jumping due to 3607257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // exhausted young space. 3608257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); 3609257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(v0, t3, t5, t6, &slow); 3610257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // FPU is not available, do manual single to double conversion. 3611257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3612257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a2: floating point value (binary32). 3613257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0: heap number for result 3614257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3615257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Extract mantissa to t4. 3616257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t4, value, Operand(kBinary32MantissaMask)); 3617257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3618257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Extract exponent to t5. 3619257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(t5, value, kBinary32MantissaBits); 3620257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t5, t5, Operand(kBinary32ExponentMask >> kBinary32MantissaBits)); 3621257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3622257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label exponent_rebiased; 3623257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&exponent_rebiased, eq, t5, Operand(zero_reg)); 3624257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3625257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t0, 0x7ff); 3626257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Xor(t1, t5, Operand(0xFF)); 36273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(t5, t0, t1); // Set t5 to 0x7ff only if t5 is equal to 0xff. 3628257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&exponent_rebiased, eq, t0, Operand(0xff)); 3629257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3630257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Rebias exponent. 3631257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t5, 3632257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch t5, 3633257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(-kBinary32ExponentBias + HeapNumber::kExponentBias)); 3634257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3635257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&exponent_rebiased); 3636257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(a2, value, Operand(kBinary32SignMask)); 3637257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch value = no_reg; 3638257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t0, t5, HeapNumber::kMantissaBitsInTopWord); 3639257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(a2, a2, t0); 3640257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3641257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Shift mantissa. 3642257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kMantissaShiftForHiWord = 3643257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; 3644257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3645257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kMantissaShiftForLoWord = 3646257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kBitsPerInt - kMantissaShiftForHiWord; 3647257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3648257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(t0, t4, kMantissaShiftForHiWord); 3649257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(a2, a2, t0); 3650257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(a0, t4, kMantissaShiftForLoWord); 3651257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3652257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, FieldMemOperand(v0, HeapNumber::kExponentOffset)); 3653257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a0, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); 3654257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3655257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3656257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3657589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3658257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3659257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3660257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a HeapNumber for the result. Don't use a0 and a1 as 3661257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // AllocateHeapNumber clobbers all registers - also when jumping due to 3662257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // exhausted young space. 3663257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); 3664257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(v0, t3, t5, t6, &slow); 3665257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The double value is already in f0 3666257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f0, FieldMemOperand(v0, HeapNumber::kValueOffset)); 3667257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3668257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3669257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Allocate a HeapNumber for the result. Don't use a0 and a1 as 3670257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // AllocateHeapNumber clobbers all registers - also when jumping due to 3671257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // exhausted young space. 3672257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t6, Heap::kHeapNumberMapRootIndex); 3673257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AllocateHeapNumber(v0, t3, t5, t6, &slow); 3674257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3675257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a2, FieldMemOperand(v0, HeapNumber::kMantissaOffset)); 3676257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(a3, FieldMemOperand(v0, HeapNumber::kExponentOffset)); 3677257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3678257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3679257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3680257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3681257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Tag integer as smi and return it. 3682257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(v0, value, kSmiTagSize); 3683257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3684257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3685257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3686257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Slow case, key and receiver still in a0 and a1. 3687257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 3688257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter( 3689257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->counters()->keyed_load_external_array_slow(), 3690257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1, a2, a3); 3691257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3692257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- S t a t e -------------- 3693257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 3694257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 3695257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 3696257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3697257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3698257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Push(a1, a0); 3699257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3700257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 3701257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3702257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 37033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 37043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 37053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(stub, RelocInfo::CODE_TARGET); 3706257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 3707257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3708257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3709257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreExternalArray( 3710257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch MacroAssembler* masm, 3711589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch ElementsKind elements_kind) { 3712257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- S t a t e -------------- 3713257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : value 3714257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : key 3715257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : receiver 3716257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 3717257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 3718257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3719257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label slow, check_heap_number, miss_force_generic; 3720257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3721257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Register usage. 3722257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register value = a0; 3723257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register key = a1; 3724257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver = a2; 3725257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3 mostly holds the elements array or the destination external array. 3726257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3727257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 3728257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 3729257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 373069a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch // Check that the key is a smi. 3731257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(key, &miss_force_generic); 3732257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 373369a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ lw(a3, FieldMemOperand(receiver, JSObject::kElementsOffset)); 373469a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch 3735257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the index is in range. 3736257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t1, FieldMemOperand(a3, ExternalArray::kLengthOffset)); 3737257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Unsigned comparison catches both negative and too-large values. 373869a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Branch(&miss_force_generic, Ugreater_equal, key, Operand(t1)); 3739257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3740257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Handle both smis and HeapNumbers in the fast path. Go to the 3741257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // runtime for all other kinds of values. 3742257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: external array. 3743257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3744589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_PIXEL_ELEMENTS) { 3745257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Double to pixel conversion is only implemented in the runtime for now. 3746257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(value, &slow); 3747257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3748257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ JumpIfNotSmi(value, &check_heap_number); 3749257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3750257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ SmiUntag(t1, value); 3751257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); 3752257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3753257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: base pointer of external storage. 3754257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t1: value (integer). 3755257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 37563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3757589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: { 3758257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Clamp the value to [0..255]. 3759257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // v0 is used as a scratch register here. 3760257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done; 3761257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(v0, Operand(255)); 3762257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Normal branch: nop in delay slot. 3763257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, gt, t1, Operand(v0)); 3764257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Use delay slot in this branch. 3765257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(USE_DELAY_SLOT, &done, lt, t1, Operand(zero_reg)); 3766257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, zero_reg); // In delay slot. 3767257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, t1); // Value is in range 0..255. 3768257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 3769257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(t1, v0); 37703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 37713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ srl(t8, key, 1); 37723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addu(t8, a3, t8); 3773257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sb(t1, MemOperand(t8, 0)); 3774257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3775257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3776589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3777589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 37783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ srl(t8, key, 1); 37793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addu(t8, a3, t8); 3780257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sb(t1, MemOperand(t8, 0)); 3781257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3782589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3783589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 37843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addu(t8, a3, key); 3785257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sh(t1, MemOperand(t8, 0)); 3786257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3787589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3788589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 37893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t8, key, 1); 3790257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t8, a3, t8); 3791257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t1, MemOperand(t8, 0)); 3792257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3793589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3794257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Perform int-to-float conversion and store to memory. 37953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ SmiUntag(t0, key); 3796257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch StoreIntAsFloat(masm, a3, t0, t1, t2, t3, t4); 3797257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3798589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 37993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t8, key, 2); 3800257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(a3, a3, t8); 3801257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: effective address of the double element 3802257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::Destination destination; 3803257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3804257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch destination = FloatingPointHelper::kFPURegisters; 3805257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3806257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch destination = FloatingPointHelper::kCoreRegisters; 3807257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3808257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch FloatingPointHelper::ConvertIntToDouble( 3809257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm, t1, destination, 3810257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch f0, t2, t3, // These are: double_dst, dst1, dst2. 3811257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch t0, f2); // These are: scratch2, single_scratch. 3812257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (destination == FloatingPointHelper::kFPURegisters) { 3813257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3814257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f0, MemOperand(a3, 0)); 3815257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3816257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t2, MemOperand(a3, 0)); 3817257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t3, MemOperand(a3, Register::kSizeInBytes)); 3818257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3819257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3820589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 38213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3822589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3823589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3824589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 3825257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 3826257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3827257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3828257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3829257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Entry registers are intact, a0 holds the value which is the return value. 38303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, a0); 3831257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3832257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3833589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind != EXTERNAL_PIXEL_ELEMENTS) { 3834257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: external array. 3835257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&check_heap_number); 3836257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ GetObjectType(value, t1, t2); 3837257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&slow, ne, t2, Operand(HEAP_NUMBER_TYPE)); 3838257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3839257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a3, ExternalArray::kExternalPointerOffset)); 3840257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3841257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // a3: base pointer of external storage. 3842257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3843257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // The WebGL specification leaves the behavior of storing NaN and 3844257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // +/-Infinity into integer arrays basically undefined. For more 3845257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // reproducible behavior, convert these to zero. 3846257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3847257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch if (CpuFeatures::IsSupported(FPU)) { 3848257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch CpuFeatures::Scope scope(FPU); 3849257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3850257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ ldc1(f0, FieldMemOperand(a0, HeapNumber::kValueOffset)); 3851257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3852589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 3853257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ cvt_s_d(f0, f0); 38543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t8, key, 1); 3855257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t8, a3, t8); 3856257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ swc1(f0, MemOperand(t8, 0)); 3857589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 38583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t8, key, 2); 3859257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t8, a3, t8); 3860257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sdc1(f0, MemOperand(t8, 0)); 3861257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 38623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ EmitECMATruncate(t3, f0, f2, t2, t1, t5); 3863257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 38643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 3865589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 3866589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 38673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ srl(t8, key, 1); 38683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addu(t8, a3, t8); 3869257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sb(t3, MemOperand(t8, 0)); 3870257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3871589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 3872589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 38733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addu(t8, a3, key); 3874257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sh(t3, MemOperand(t8, 0)); 3875257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3876589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 3877589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 38783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t8, key, 1); 3879257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t8, a3, t8); 3880257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t3, MemOperand(t8, 0)); 3881257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3882589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 3883589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 3884589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 3885589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 38863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 3887589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 3888589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 3889589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 3890257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 3891257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 3892257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3893257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 3894257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3895257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Entry registers are intact, a0 holds the value 3896257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // which is the return value. 38973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, a0); 3898257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3899257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 3900257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // FPU is not available, do manual conversions. 3901257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3902257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t3, FieldMemOperand(value, HeapNumber::kExponentOffset)); 3903257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t4, FieldMemOperand(value, HeapNumber::kMantissaOffset)); 3904257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3905589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch if (elements_kind == EXTERNAL_FLOAT_ELEMENTS) { 3906257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, nan_or_infinity_or_zero; 3907257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kMantissaInHiWordShift = 3908257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kBinary32MantissaBits - HeapNumber::kMantissaBitsInTopWord; 3909257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3910257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch static const int kMantissaInLoWordShift = 3911257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch kBitsPerInt - kMantissaInHiWordShift; 3912257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3913257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Test for all special exponent values: zeros, subnormal numbers, NaNs 3914257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // and infinities. All these should be converted to 0. 3915257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t5, HeapNumber::kExponentMask); 3916257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ and_(t6, t3, t5); 3917257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&nan_or_infinity_or_zero, eq, t6, Operand(zero_reg)); 3918257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3919257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xor_(t1, t6, t5); 3920257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t2, kBinary32ExponentMask); 39213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(t6, t2, t1); // Only if t6 is equal to t5. 3922257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&nan_or_infinity_or_zero, eq, t6, Operand(t5)); 3923257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3924257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Rebias exponent. 3925257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(t6, t6, HeapNumber::kExponentShift); 3926257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t6, 3927257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch t6, 3928257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Operand(kBinary32ExponentBias - HeapNumber::kExponentBias)); 3929257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3930257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t1, Operand(kBinary32MaxExponent)); 3931257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Slt(t1, t1, t6); 3932257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t2, t3, Operand(HeapNumber::kSignMask)); 3933257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(t2, t2, Operand(kBinary32ExponentMask)); 39343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movn(t3, t2, t1); // Only if t6 is gt kBinary32MaxExponent. 3935257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, gt, t6, Operand(kBinary32MaxExponent)); 3936257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3937257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Slt(t1, t6, Operand(kBinary32MinExponent)); 3938257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t2, t3, Operand(HeapNumber::kSignMask)); 39393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movn(t3, t2, t1); // Only if t6 is lt kBinary32MinExponent. 3940257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, lt, t6, Operand(kBinary32MinExponent)); 3941257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3942257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t7, t3, Operand(HeapNumber::kSignMask)); 3943257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t3, t3, Operand(HeapNumber::kMantissaMask)); 3944257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t3, t3, kMantissaInHiWordShift); 3945257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(t7, t7, t3); 3946257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(t4, t4, kMantissaInLoWordShift); 3947257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(t7, t7, t4); 3948257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t6, t6, kBinary32ExponentShift); 3949257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(t3, t7, t6); 3950257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3951257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 39523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t9, key, 1); 3953257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t9, a2, t9); 3954257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t3, MemOperand(t9, 0)); 3955257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3956257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Entry registers are intact, a0 holds the value which is the return 3957257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // value. 39583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, a0); 3959257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3960257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3961257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&nan_or_infinity_or_zero); 3962257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t7, t3, Operand(HeapNumber::kSignMask)); 3963257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t3, t3, Operand(HeapNumber::kMantissaMask)); 3964257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(t6, t6, t7); 3965257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t3, t3, kMantissaInHiWordShift); 3966257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(t6, t6, t3); 3967257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(t4, t4, kMantissaInLoWordShift); 3968257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(t3, t6, t4); 3969257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done); 3970589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch } else if (elements_kind == EXTERNAL_DOUBLE_ELEMENTS) { 3971257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t8, t0, 3); 3972257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t8, a3, t8); 3973257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // t8: effective address of destination element. 3974257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t4, MemOperand(t8, 0)); 3975257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t3, MemOperand(t8, Register::kSizeInBytes)); 39763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(v0, a0); 3977257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 3978257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } else { 39793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch bool is_signed_type = IsElementTypeSigned(elements_kind); 3980257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int meaningfull_bits = is_signed_type ? (kBitsPerInt - 1) : kBitsPerInt; 3981257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch int32_t min_value = is_signed_type ? 0x80000000 : 0x00000000; 3982257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3983257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label done, sign; 3984257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3985257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Test for all special exponent values: zeros, subnormal numbers, NaNs 3986257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // and infinities. All these should be converted to 0. 3987257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t5, HeapNumber::kExponentMask); 3988257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ and_(t6, t3, t5); 39893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(t3, zero_reg, t6); // Only if t6 is equal to zero. 3990257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, eq, t6, Operand(zero_reg)); 3991257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3992257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ xor_(t2, t6, t5); 39933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(t3, zero_reg, t2); // Only if t6 is equal to t5. 3994257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, eq, t6, Operand(t5)); 3995257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 3996257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Unbias exponent. 3997257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srl(t6, t6, HeapNumber::kExponentShift); 3998257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Subu(t6, t6, Operand(HeapNumber::kExponentBias)); 3999257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If exponent is negative then result is 0. 4000257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ slt(t2, t6, zero_reg); 40013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movn(t3, zero_reg, t2); // Only if exponent is negative. 4002257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, lt, t6, Operand(zero_reg)); 4003257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4004257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // If exponent is too big then result is minimal value. 4005257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ slti(t1, t6, meaningfull_bits - 1); 4006257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t2, min_value); 40073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(t3, t2, t1); // Only if t6 is ge meaningfull_bits - 1. 4008257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&done, ge, t6, Operand(meaningfull_bits - 1)); 4009257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4010257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t5, t3, Operand(HeapNumber::kSignMask)); 4011257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ And(t3, t3, Operand(HeapNumber::kMantissaMask)); 4012257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Or(t3, t3, Operand(1u << HeapNumber::kMantissaBitsInTopWord)); 4013257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4014257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t9, HeapNumber::kMantissaBitsInTopWord); 4015257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(t6, t9, t6); 4016257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ slt(t1, t6, zero_reg); 4017257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srlv(t2, t3, t6); 40183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(t3, t2, t1); // Only if t6 is positive. 4019257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&sign, ge, t6, Operand(zero_reg)); 4020257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4021257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(t6, zero_reg, t6); 4022257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sllv(t3, t3, t6); 4023257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ li(t9, meaningfull_bits); 4024257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(t6, t9, t6); 4025257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ srlv(t4, t4, t6); 4026257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ or_(t3, t3, t4); 4027257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4028257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&sign); 4029257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ subu(t2, t3, zero_reg); 40303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Movz(t3, t2, t5); // Only if t5 is zero. 4031257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4032257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&done); 4033257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4034257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Result is in t3. 4035257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This switch block should be exactly the same as above (FPU mode). 40363fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch switch (elements_kind) { 4037589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_BYTE_ELEMENTS: 4038589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_BYTE_ELEMENTS: 40393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ srl(t8, key, 1); 40403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addu(t8, a3, t8); 4041257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sb(t3, MemOperand(t8, 0)); 4042257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 4043589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_SHORT_ELEMENTS: 4044589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_SHORT_ELEMENTS: 40453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ addu(t8, a3, key); 4046257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sh(t3, MemOperand(t8, 0)); 4047257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 4048589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_INT_ELEMENTS: 4049589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_UNSIGNED_INT_ELEMENTS: 40503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(t8, key, 1); 4051257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ addu(t8, a3, t8); 4052257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sw(t3, MemOperand(t8, 0)); 4053257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 4054589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_PIXEL_ELEMENTS: 4055589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_FLOAT_ELEMENTS: 4056589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case EXTERNAL_DOUBLE_ELEMENTS: 4057589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_ELEMENTS: 40583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch case FAST_SMI_ONLY_ELEMENTS: 4059589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case FAST_DOUBLE_ELEMENTS: 4060589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case DICTIONARY_ELEMENTS: 4061589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch case NON_STRICT_ARGUMENTS_ELEMENTS: 4062257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch UNREACHABLE(); 4063257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch break; 4064257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4065257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4066257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4067257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch } 4068257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4069257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Slow case, key and receiver still in a0 and a1. 4070257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&slow); 4071257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ IncrementCounter( 4072257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->counters()->keyed_load_external_array_slow(), 4073257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 1, a2, a3); 4074257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Entry registers are intact. 4075257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- S t a t e -------------- 4076257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 4077257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 4078257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 4079257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 4080257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> slow_ic = 4081257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_Slow(); 4082257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(slow_ic, RelocInfo::CODE_TARGET); 4083257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4084257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Miss case, call the runtime. 4085257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 4086257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4087257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ---------- S t a t e -------------- 4088257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 4089257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 4090257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 4091257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 4092257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4093257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> miss_ic = 4094257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4095257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 4096257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4097257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4098257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4099257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastElement(MacroAssembler* masm) { 4100257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 4101257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 4102257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : key 4103257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : receiver 4104257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 4105257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Label miss_force_generic; 4106257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4107257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 4108257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 4109257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4110257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 41113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(a0, &miss_force_generic, at, USE_DELAY_SLOT); 41123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // The delay slot can be safely used here, a1 is an object pointer. 4113257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4114257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Get the elements array. 4115257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a2, FieldMemOperand(a1, JSObject::kElementsOffset)); 4116257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ AssertFastElements(a2); 4117257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4118257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is within bounds. 4119257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(a3, FieldMemOperand(a2, FixedArray::kLengthOffset)); 41203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(USE_DELAY_SLOT, &miss_force_generic, hs, a0, Operand(a3)); 4121257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4122257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Load the result and make sure it's not the hole. 4123257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(a3, a2, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 4124589d6979ff2ef66fca2d8fa51404c369ca5e9250Ben Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 4125257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ sll(t0, a0, kPointerSizeLog2 - kSmiTagSize); 4126257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Addu(t0, t0, a3); 4127257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ lw(t0, MemOperand(t0)); 4128257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ LoadRoot(t1, Heap::kTheHoleValueRootIndex); 4129257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Branch(&miss_force_generic, eq, t0, Operand(t1)); 41303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(USE_DELAY_SLOT); 4131257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ mov(v0, t0); 4132257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4133257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 41343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> stub = 41353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 41363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(stub, RelocInfo::CODE_TARGET); 4137257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch} 4138257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4139257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 41403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedLoadStubCompiler::GenerateLoadFastDoubleElement( 41413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm) { 41423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 41433fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ra : return address 41443fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a0 : key 41453fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a1 : receiver 41463fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 41473fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Label miss_force_generic, slow_allocate_heapnumber; 41483fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41493fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key_reg = a0; 41503fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register receiver_reg = a1; 41513fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register elements_reg = a2; 41523fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register heap_number_reg = a2; 41533fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register indexed_double_offset = a3; 41543fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch = t0; 41553fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch2 = t1; 41563fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch3 = t2; 41573fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register heap_number_map = t3; 41583fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41593fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 41603fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 41613fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41623fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is a smi. 41633fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key_reg, &miss_force_generic); 41643fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41653fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Get the elements array. 41663fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(elements_reg, 41673fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 41683fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41693fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 41703fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 41713fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch)); 41723fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Load the upper word of the double in the fixed array and test for NaN. 41743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sll(scratch2, key_reg, kDoubleSizeLog2 - kSmiTagSize); 41753fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Addu(indexed_double_offset, elements_reg, Operand(scratch2)); 41763fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch uint32_t upper_32_offset = FixedArray::kHeaderSize + sizeof(kHoleNanLower32); 41773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(scratch, FieldMemOperand(indexed_double_offset, upper_32_offset)); 41783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Branch(&miss_force_generic, eq, scratch, Operand(kHoleNanUpper32)); 41793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Non-NaN. Allocate a new heap number and copy the double value into it. 41813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ LoadRoot(heap_number_map, Heap::kHeapNumberMapRootIndex); 41823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ AllocateHeapNumber(heap_number_reg, scratch2, scratch3, 41833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch heap_number_map, &slow_allocate_heapnumber); 41843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Don't need to reload the upper 32 bits of the double, it's already in 41863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // scratch. 41873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(scratch, FieldMemOperand(heap_number_reg, 41883fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HeapNumber::kExponentOffset)); 41893fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(scratch, FieldMemOperand(indexed_double_offset, 41903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FixedArray::kHeaderSize)); 41913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ sw(scratch, FieldMemOperand(heap_number_reg, 41923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch HeapNumber::kMantissaOffset)); 41933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41943fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ mov(v0, heap_number_reg); 41953fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Ret(); 41963fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 41973fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&slow_allocate_heapnumber); 41983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> slow_ic = 41993fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_Slow(); 42003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(slow_ic, RelocInfo::CODE_TARGET); 42013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 42023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 42033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> miss_ic = 42043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedLoadIC_MissForceGeneric(); 42053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(miss_ic, RelocInfo::CODE_TARGET); 42063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 42073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 42083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 42093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastElement( 42103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch MacroAssembler* masm, 42113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 42123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ElementsKind elements_kind, 42133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 4214257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------- S t a t e ------------- 4215257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a0 : value 4216257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a1 : key 4217257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a2 : receiver 4218257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- ra : return address 4219257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a3 : scratch 4220257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // -- a4 : scratch (elements) 4221257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // ----------------------------------- 42223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, grow, slow; 42233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label finish_store, check_capacity; 4224257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4225257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register value_reg = a0; 4226257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register key_reg = a1; 4227257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Register receiver_reg = a2; 42283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch = t0; 42293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements_reg = a3; 42303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register length_reg = t1; 42313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2 = t2; 4232257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4233257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 4234257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // have been verified by the caller to not be a smi. 4235257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4236257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Check that the key is a smi. 42373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key_reg, &miss_force_generic); 4238257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 42393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 42403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfNotSmi(value_reg, &transition_elements_kind); 42413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 42425d4cdbf7a67d3662fa0bee4efdb7edd8daec9b0bBen Murdoch 424385b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Check that the key is within bounds. 42443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(elements_reg, 42453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 424685b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch if (is_js_array) { 424785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ lw(scratch, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 4248592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } else { 424985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 4250592a9fc1d8ea420377a2e7efd0600e20b058be2bBen Murdoch } 425185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch // Compare smis. 42523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 42533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&grow, hs, key_reg, Operand(scratch)); 42543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch)); 42563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 425785b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 42583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure elements is a fast element array, not 'cow'. 42593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(elements_reg, 42603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 42613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedArrayMapRootIndex, 42623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss_force_generic, 42633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 426485b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 42653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 42663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 42673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (elements_kind == FAST_SMI_ONLY_ELEMENTS) { 42683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(scratch, 42693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_reg, 42703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 42713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 42723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize); 42733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(scratch, scratch, scratch2); 42743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(value_reg, MemOperand(scratch)); 42753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } else { 42763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(elements_kind == FAST_ELEMENTS); 42773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(scratch, 42783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_reg, 42793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 42803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 42813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sll(scratch2, key_reg, kPointerSizeLog2 - kSmiTagSize); 42823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(scratch, scratch, scratch2); 42833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(value_reg, MemOperand(scratch)); 42843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ mov(receiver_reg, value_reg); 42853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch ASSERT(elements_kind == FAST_ELEMENTS); 42863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWrite(elements_reg, // Object. 42873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, // Address. 42883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, // Value. 42893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kRAHasNotBeenSaved, 42903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch kDontSaveFPRegs); 42913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 4292257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // value_reg (a0) is preserved. 4293257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch // Done. 4294257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Ret(); 4295257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch 4296257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ bind(&miss_force_generic); 4297257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch Handle<Code> ic = 4298257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 4299257744e915dfc84d6d07a6b2accf8402d9ffc708Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 43003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 43023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 43033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_miss, RelocInfo::CODE_TARGET); 43043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 43063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array by a single element if possible. 43073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 43083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 43103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. 43113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss_force_generic, ne, key_reg, Operand(scratch)); 43123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 43143ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 43153ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(length_reg, 43163ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 43173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(elements_reg, 43183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 43193ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); 43203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&check_capacity, ne, elements_reg, Operand(at)); 43213ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43223ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedArray::SizeFor(JSArray::kPreallocatedArrayElements); 43233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, elements_reg, scratch, scratch2, &slow, 43243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TAG_OBJECT); 43253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch, Heap::kFixedArrayMapRootIndex); 43273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(scratch, FieldMemOperand(elements_reg, JSObject::kMapOffset)); 43283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(scratch, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements))); 43293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 43303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch, Heap::kTheHoleValueRootIndex); 43313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch for (int i = 1; i < JSArray::kPreallocatedArrayElements; ++i) { 43323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(scratch, FieldMemOperand(elements_reg, FixedArray::SizeFor(i))); 43333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 43343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43353ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Store the element at index zero. 43363ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(value_reg, FieldMemOperand(elements_reg, FixedArray::SizeFor(0))); 43373ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43383ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 43393ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(elements_reg, 43403ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 43413ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg, 43423ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, kRAHasNotBeenSaved, kDontSaveFPRegs, 43433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 43443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 43463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(length_reg, Operand(Smi::FromInt(1))); 43473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 43483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Ret(); 43493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 43513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for cow elements, in general they are not handled by this stub 43523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ CheckMap(elements_reg, 43533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch, 43543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Heap::kFixedCOWArrayMapRootIndex, 43553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &miss_force_generic, 43563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch DONT_DO_SMI_CHECK); 43573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(scratch, FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 43593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&slow, hs, length_reg, Operand(scratch)); 43603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 43623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(length_reg, length_reg, Operand(Smi::FromInt(1))); 43633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 43643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 43653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 43663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 43673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 43683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_slow, RelocInfo::CODE_TARGET); 43693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 43701e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block} 43711e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 43721e0659c275bb392c045087af4f6b0d7565cb3d77Steve Block 43733fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdochvoid KeyedStoreStubCompiler::GenerateStoreFastDoubleElement( 43743fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch MacroAssembler* masm, 43753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch bool is_js_array, 43763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch KeyedAccessGrowMode grow_mode) { 43773fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------- S t a t e ------------- 43783fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a0 : value 43793fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a1 : key 43803fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a2 : receiver 43813fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- ra : return address 43823fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- a3 : scratch 43833fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- t0 : scratch (elements_reg) 43843fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- t1 : scratch (mantissa_reg) 43853fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- t2 : scratch (exponent_reg) 43863fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // -- t3 : scratch4 43873fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // ----------------------------------- 43883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label miss_force_generic, transition_elements_kind, grow, slow; 43893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label finish_store, check_capacity; 43903fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 43913fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register value_reg = a0; 43923fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register key_reg = a1; 43933fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register receiver_reg = a2; 43943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register elements_reg = a3; 43953ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch1 = t0; 43963ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch2 = t1; 43973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register scratch3 = t2; 43983fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Register scratch4 = t3; 43993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Register length_reg = t3; 44003fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44013fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // This stub is meant to be tail-jumped to, the receiver must already 44023fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // have been verified by the caller to not be a smi. 44033fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ JumpIfNotSmi(key_reg, &miss_force_generic); 44043fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44053fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ lw(elements_reg, 44063fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 44073fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44083fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Check that the key is within bounds. 44093fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch if (is_js_array) { 44103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(scratch1, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 44113fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } else { 44123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(scratch1, 44133fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch FieldMemOperand(elements_reg, FixedArray::kLengthOffset)); 44143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch } 44153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Compare smis, unsigned compare catches both negative and out-of-bound 44163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // indexes. 44173ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (grow_mode == ALLOW_JSARRAY_GROWTH) { 44183ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&grow, hs, key_reg, Operand(scratch1)); 441985b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } else { 44203ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss_force_generic, hs, key_reg, Operand(scratch1)); 442185b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch } 442285b71799222b55eb5dd74ea26efe0c64ab655c8cBen Murdoch 44233ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&finish_store); 44243ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44253ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ StoreNumberToDoubleElements(value_reg, 44263ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch key_reg, 44273ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch receiver_reg, 44283ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch elements_reg, 44293ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, 44303ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch2, 44313ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch3, 44323ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch4, 44333ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch &transition_elements_kind); 44343ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 443569a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ Ret(USE_DELAY_SLOT); 443669a99ed0b2b2ef69d393c371b03db3a98aaf880eBen Murdoch __ mov(v0, value_reg); // In delay slot. 44373fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 44383fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch // Handle store cache miss, replacing the ic with the generic stub. 44393fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ bind(&miss_force_generic); 44403fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch Handle<Code> ic = 44413fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch masm->isolate()->builtins()->KeyedStoreIC_MissForceGeneric(); 44423fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch __ Jump(ic, RelocInfo::CODE_TARGET); 44433ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44443ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&transition_elements_kind); 44453ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_miss = masm->isolate()->builtins()->KeyedStoreIC_Miss(); 44463ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_miss, RelocInfo::CODE_TARGET); 44473ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44483ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch if (is_js_array && grow_mode == ALLOW_JSARRAY_GROWTH) { 44493ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array by a single element if possible. 44503ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&grow); 44513ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44523ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure the array is only growing by a single element, anything else 44533ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // must be handled by the runtime. 44543ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&miss_force_generic, ne, key_reg, Operand(scratch1)); 44553ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44563ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Transition on values that can't be stored in a FixedDoubleArray. 44573ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Label value_is_smi; 44583ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ JumpIfSmi(value_reg, &value_is_smi); 44593ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(scratch1, FieldMemOperand(value_reg, HeapObject::kMapOffset)); 44603ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); 44613ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&transition_elements_kind, ne, scratch1, Operand(at)); 44623ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&value_is_smi); 44633ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44643ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Check for the empty array, and preallocate a small backing store if 44653ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // possible. 44663ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(length_reg, 44673ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 44683ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(elements_reg, 44693ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 44703ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(at, Heap::kEmptyFixedArrayRootIndex); 44713ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&check_capacity, ne, elements_reg, Operand(at)); 44723ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44733ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch int size = FixedDoubleArray::SizeFor(JSArray::kPreallocatedArrayElements); 44743ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ AllocateInNewSpace(size, elements_reg, scratch1, scratch2, &slow, 44753ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch TAG_OBJECT); 44763ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44773ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Initialize the new FixedDoubleArray. Leave elements unitialized for 44783ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // efficiency, they are guaranteed to be initialized before use. 44793ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ LoadRoot(scratch1, Heap::kFixedDoubleArrayMapRootIndex); 44803ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(scratch1, FieldMemOperand(elements_reg, JSObject::kMapOffset)); 44813ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(scratch1, Operand(Smi::FromInt(JSArray::kPreallocatedArrayElements))); 44823ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(scratch1, 44833ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset)); 44843ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44853ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Install the new backing store in the JSArray. 44863ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(elements_reg, 44873ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 44883ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ RecordWriteField(receiver_reg, JSObject::kElementsOffset, elements_reg, 44893ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch scratch1, kRAHasNotBeenSaved, kDontSaveFPRegs, 44903ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 44913ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44923ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Increment the length of the array. 44933ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ li(length_reg, Operand(Smi::FromInt(1))); 44943ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 44959413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch __ lw(elements_reg, 44969413bcbe2192ed4d701281130490e0ba336debdcBen Murdoch FieldMemOperand(receiver_reg, JSObject::kElementsOffset)); 44973ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 44983ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 44993ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&check_capacity); 45003ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Make sure that the backing store can hold additional elements. 45013ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ lw(scratch1, 45023ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch FieldMemOperand(elements_reg, FixedDoubleArray::kLengthOffset)); 45033ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Branch(&slow, hs, length_reg, Operand(scratch1)); 45043ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45053ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch // Grow the array and finish the store. 45063ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Addu(length_reg, length_reg, Operand(Smi::FromInt(1))); 45073ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ sw(length_reg, FieldMemOperand(receiver_reg, JSArray::kLengthOffset)); 45083ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ jmp(&finish_store); 45093ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch 45103ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ bind(&slow); 45113ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch Handle<Code> ic_slow = masm->isolate()->builtins()->KeyedStoreIC_Slow(); 45123ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch __ Jump(ic_slow, RelocInfo::CODE_TARGET); 45133ef787dbeca8a5fb1086949cda830dccee07bfbdBen Murdoch } 45143fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch} 45153fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45163fb3ca8c7ca439d408449a395897395c0faae8d1Ben Murdoch 45173100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu#undef __ 45183100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 45193100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu} } // namespace v8::internal 45203100271588b61cbc1dc472a3f2f105d2eed8497fAndrei Popescu 4521f7060e27768c550ace7ec48ad8c093466db52dfaLeon Clarke#endif // V8_TARGET_ARCH_MIPS 4522