1b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Copyright 2012 the V8 project authors. All rights reserved. 2b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Use of this source code is governed by a BSD-style license that can be 3b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// found in the LICENSE file. 4b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 5b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/v8.h" 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#if V8_TARGET_ARCH_MIPS 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic-compiler.h" 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/stub-cache.h" 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ---------------------------------------------------------------------------- 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Static IC stub generators. 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm) 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type, 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* global_object) { 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Register usage: 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // type: holds the receiver instance type on entry. 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(global_object, eq, type, Operand(JS_GLOBAL_OBJECT_TYPE)); 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(global_object, eq, type, Operand(JS_BUILTINS_OBJECT_TYPE)); 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(global_object, eq, type, Operand(JS_GLOBAL_PROXY_TYPE)); 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Helper function used from LoadIC GenerateNormal. 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// elements: Property dictionary. It is not clobbered if a jump to the miss 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// label is done. 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// name: Property name. It is not clobbered if a jump to the miss label is 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// done 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// result: Register for the result. It is only updated if a jump to the miss 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// label is not done. Can be the same as elements or name clobbering 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// one of these in the case of not jumping to the miss label. 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The two scratch registers need to be different from elements, name and 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// result. 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The generated code assumes that the receiver has slow properties, 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// is not a global object and does not have interceptors. 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The address returned from GenerateStringDictionaryProbes() in scratch2 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// is used. 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss, 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements, Register name, 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, Register scratch1, 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2) { 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Main use of the scratch registers. 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch1: Used as temporary and to hold the capacity of the property 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // dictionary. 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch2: Used as temporary. 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Probe the dictionary. 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss, &done, elements, 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, scratch1, scratch2); 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If probing finds an entry check that the value is a normal 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // property. 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); // scratch2 == elements + 4 * index. 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kElementsStartOffset = 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kHeaderSize + 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kElementsStartIndex * kPointerSize; 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(at, scratch1, 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(PropertyDetails::TypeField::kMask << kSmiTagSize)); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(miss, ne, at, Operand(zero_reg)); 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the value at the masked, scaled index and return. 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(result, 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Helper function used from StoreIC::GenerateNormal. 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// elements: Property dictionary. It is not clobbered if a jump to the miss 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// label is done. 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// name: Property name. It is not clobbered if a jump to the miss label is 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// done 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// value: The value to store. 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The two scratch registers need to be different from elements, name and 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// result. 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The generated code assumes that the receiver has slow properties, 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// is not a global object and does not have interceptors. 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The address returned from GenerateStringDictionaryProbes() in scratch2 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// is used. 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateDictionaryStore(MacroAssembler* masm, Label* miss, 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements, Register name, 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, Register scratch1, 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2) { 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Main use of the scratch registers. 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch1: Used as temporary and to hold the capacity of the property 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // dictionary. 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch2: Used as temporary. 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Probe the dictionary. 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss, &done, elements, 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, scratch1, scratch2); 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If probing finds an entry in the dictionary check that the value 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a normal property that is not read only. 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); // scratch2 == elements + 4 * index. 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kElementsStartOffset = 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kHeaderSize + 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kElementsStartIndex * kPointerSize; 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kTypeAndReadOnlyMask = 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (PropertyDetails::TypeField::kMask | 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyDetails::AttributesField::encode(READ_ONLY)) 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << kSmiTagSize; 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(at, scratch1, Operand(kTypeAndReadOnlyMask)); 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(miss, ne, at, Operand(zero_reg)); 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store the value at the masked, scaled index and return. 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kValueOffset = kElementsStartOffset + kPointerSize; 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag)); 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sw(value, MemOperand(scratch2)); 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier. Make sure not to clobber the value. 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch1, value); 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWrite(elements, scratch2, scratch1, kRAHasNotBeenSaved, 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs); 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Checks the receiver for special cases (value type, slow case bits). 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Falls through for regular JS object. 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver, Register map, 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int interceptor_bit, Label* slow) { 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the object isn't a smi. 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(receiver, slow); 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the map of the receiver. 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check bit field. 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lbu(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(at, scratch, 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(slow, ne, at, Operand(zero_reg)); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the object is some kind of JS object EXCEPT JS Value type. 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In the case that the object is a value-wrapper object, 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we enter the runtime system to make sure that indexing into string 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // objects work as intended. 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lbu(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(slow, lt, scratch, Operand(JS_OBJECT_TYPE)); 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 160b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 161b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Loads an indexed element from a fast case array. 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// If not_fast_array is NULL, doesn't perform the elements map check. 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key, Register elements, 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, Register scratch2, 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, Label* not_fast_array, 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* out_of_range) { 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Register use: 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // receiver - holds the receiver on entry. 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unchanged unless 'result' is the same register. 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // key - holds the smi key on entry. 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unchanged unless 'result' is the same register. 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 177b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // elements - holds the elements of the receiver on exit. 178b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 179b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result - holds the result on exit if the load succeeded. 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allowed to be the the same as 'receiver' or 'key'. 181b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unchanged on bailout so 'receiver' and 'key' can be safely 182b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // used by further computation. 183b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Scratch registers: 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 186b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch1 - used to hold elements map and elements length. 187b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Holds the elements map if not_fast_array branch is taken. 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch2 - used to hold the loaded value. 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 191b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 192b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (not_fast_array != NULL) { 193b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the object is in fast mode (not dictionary). 194b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); 195b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(at, Heap::kFixedArrayMapRootIndex); 196b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(not_fast_array, ne, scratch1, Operand(at)); 197b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 198b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ AssertFastElements(elements); 199b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 200b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 201b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the key (index) is within bounds. 202b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); 203b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(out_of_range, hs, key, Operand(scratch1)); 204b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 205b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fast case: Do the load. 206b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch1, elements, 207b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 208b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The key is a smi. 209b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kSmiTag == 0 && kSmiTagSize < kPointerSizeLog2); 210b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sll(at, key, kPointerSizeLog2 - kSmiTagSize); 211b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addu(at, at, scratch1); 212b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch2, MemOperand(at)); 213b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 214b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(at, Heap::kTheHoleValueRootIndex); 215b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In case the loaded value is the_hole we have to consult GetProperty 216b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to ensure the prototype chain is searched. 217b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(out_of_range, eq, scratch2, Operand(at)); 218b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, scratch2); 219b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 220b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 221b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 222b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Checks whether a key is an array index string or a unique name. 223b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Falls through if a key is a unique name. 224b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateKeyNameCheck(MacroAssembler* masm, Register key, 225b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map, Register hash, 226b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* index_string, Label* not_unique) { 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The key is not a smi. 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label unique; 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Is it a name? 230b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ GetObjectType(key, map, hash); 231b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(not_unique, hi, hash, Operand(LAST_UNIQUE_NAME_TYPE)); 232b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&unique, eq, hash, Operand(LAST_UNIQUE_NAME_TYPE)); 234b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Is the string an array index, with cached numeric value? 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(hash, FieldMemOperand(key, Name::kHashFieldOffset)); 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(at, hash, Operand(Name::kContainsCachedArrayIndexMask)); 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(index_string, eq, at, Operand(zero_reg)); 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Is the string internalized? We know it's a string, so a single 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit test is enough. 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // map: key map 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lbu(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kInternalizedTag == 0); 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(at, hash, Operand(kIsNotInternalizedMask)); 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(not_unique, ne, at, Operand(zero_reg)); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&unique); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LoadIC::GenerateNormal(MacroAssembler* masm) { 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dictionary = a0; 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow; 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(dictionary, FieldMemOperand(LoadDescriptor::ReceiverRegister(), 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSObject::kPropertiesOffset)); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryLoad(masm, &slow, dictionary, 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadDescriptor::NameRegister(), v0, a3, t0); 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Dictionary load failed, go slow (but don't miss). 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateRuntimeGetProperty(masm); 268b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A register that isn't one of the parameters to the load ic. 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const Register LoadIC_TempRegister() { return a3; } 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LoadIC::GenerateMiss(MacroAssembler* masm) { 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The return address is in ra. 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0); 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister()); 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister()); 283b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform tail call to the entry. 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = ExternalReference(IC_Utility(kLoadIC_Miss), isolate); 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(ref, 2, 1); 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 291b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The return address is in ra. 292b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 293b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister()); 294b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister()); 295b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 296b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallRuntime(Runtime::kGetProperty, 2, 1); 297b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 298b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 299b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 300b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic MemOperand GenerateMappedArgumentsLookup( 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Register object, Register key, Register scratch1, 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2, Register scratch3, Label* unmapped_case, 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* slow_case) { 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap* heap = masm->isolate()->heap(); 305b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 306b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the receiver is a JSObject. Because of the map check 307b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // later, we do not need to check for interceptors or whether it 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // requires access checks. 309b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(object, slow_case); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the object is some kind of JSObject. 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ GetObjectType(object, scratch1, scratch2); 312b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(slow_case, lt, scratch2, Operand(FIRST_JS_RECEIVER_TYPE)); 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the key is a positive smi. 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(scratch1, key, Operand(0x80000001)); 316b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(slow_case, ne, scratch1, Operand(zero_reg)); 317b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the elements into scratch1 and check its map. 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Handle<Map> arguments_map(heap->sloppy_arguments_elements_map()); 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch1, FieldMemOperand(object, JSObject::kElementsOffset)); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(scratch1, scratch2, arguments_map, slow_case, DONT_DO_SMI_CHECK); 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if element is in the range of mapped arguments. If not, jump 323b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to the unmapped lookup with the parameter map in scratch1. 324b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch2, FieldMemOperand(scratch1, FixedArray::kLengthOffset)); 325b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Subu(scratch2, scratch2, Operand(Smi::FromInt(2))); 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(unmapped_case, Ugreater_equal, key, Operand(scratch2)); 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load element index and check whether it is the hole. 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kOffset = 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FixedArray::kHeaderSize + 2 * kPointerSize - kHeapObjectTag; 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ li(scratch3, Operand(kPointerSize >> 1)); 333b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mul(scratch3, key, scratch3); 334b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch3, scratch3, Operand(kOffset)); 335b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch2, scratch1, scratch3); 337b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch2, MemOperand(scratch2)); 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(scratch3, Heap::kTheHoleValueRootIndex); 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(unmapped_case, eq, scratch2, Operand(scratch3)); 340b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load value from context and return it. We can reuse scratch1 because 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we do not jump to the unmapped lookup (which requires the parameter 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // map in scratch1). 344b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch1, FieldMemOperand(scratch1, FixedArray::kHeaderSize)); 345b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ li(scratch3, Operand(kPointerSize >> 1)); 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mul(scratch3, scratch2, scratch3); 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch3, scratch3, Operand(Context::kHeaderSize - kHeapObjectTag)); 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch2, scratch1, scratch3); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MemOperand(scratch2); 350b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 351b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 352b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 353b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic MemOperand GenerateUnmappedArgumentsLookup(MacroAssembler* masm, 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key, 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register parameter_map, 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 357b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* slow_case) { 358b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Element is in arguments backing store, which is referenced by the 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // second element of the parameter_map. The parameter_map register 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // must be loaded with the parameter map of the arguments object and is 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // overwritten. 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kBackingStoreOffset = FixedArray::kHeaderSize + kPointerSize; 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register backing_store = parameter_map; 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(backing_store, FieldMemOperand(parameter_map, kBackingStoreOffset)); 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckMap(backing_store, scratch, Heap::kFixedArrayMapRootIndex, slow_case, 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DONT_DO_SMI_CHECK); 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch, FieldMemOperand(backing_store, FixedArray::kLengthOffset)); 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(slow_case, Ugreater_equal, key, Operand(scratch)); 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ li(scratch, Operand(kPointerSize >> 1)); 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Mul(scratch, key, scratch); 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch, scratch, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch, backing_store, scratch); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return MemOperand(scratch); 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedStoreIC::GenerateSloppyArguments(MacroAssembler* masm) { 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = StoreDescriptor::ReceiverRegister(); 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key = StoreDescriptor::NameRegister(); 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = StoreDescriptor::ValueRegister(); 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value.is(a0)); 382b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 383b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, notin; 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store address is returned in register (of MemOperand) mapped_location. 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand mapped_location = GenerateMappedArgumentsLookup( 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, receiver, key, a3, t0, t1, ¬in, &slow); 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sw(value, mapped_location); 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(t5, value); 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(mapped_location.offset(), 0); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWrite(a3, mapped_location.rm(), t5, kRAHasNotBeenSaved, 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs); 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(USE_DELAY_SLOT); 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(v0, value); // (In delay slot) return the value stored in v0. 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(¬in); 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The unmapped lookup expects that the parameter map is in a3. 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store address is returned in register (of MemOperand) unmapped_location. 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MemOperand unmapped_location = 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateUnmappedArgumentsLookup(masm, key, a3, t0, &slow); 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sw(value, unmapped_location); 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(t5, value); 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(unmapped_location.offset(), 0); 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWrite(a3, unmapped_location.rm(), t5, kRAHasNotBeenSaved, 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs); 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(USE_DELAY_SLOT); 405b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(v0, a0); // (In delay slot) return the value stored in v0. 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMiss(masm); 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The return address is in ra. 413b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 414b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, a3, t0); 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform tail call to the entry. 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = 421b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(kKeyedLoadIC_Miss), isolate); 422b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 423b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(ref, 2, 1); 424b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 425b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 426b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 427b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { 428b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The return address is in ra. 429b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 430b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); 431b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallRuntime(Runtime::kKeyedGetProperty, 2, 1); 433b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 434b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 435b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 436b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedLoadIC::GenerateGeneric(MacroAssembler* masm) { 437b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The return address is in ra. 438b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, check_name, index_smi, index_name, property_array_property; 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label probe_dictionary, check_number_dictionary; 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key = LoadDescriptor::NameRegister(); 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = LoadDescriptor::ReceiverRegister(); 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(key.is(a2)); 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(receiver.is(a1)); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the key is a smi. 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(key, &check_name); 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&index_smi); 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Now the key is known to be a smi. This place is also jumped to from below 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // where a numeric string is converted to a smi. 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateKeyedLoadReceiverCheck(masm, receiver, a0, a3, 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kHasIndexedInterceptor, &slow); 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the receiver's map to see if it has fast elements. 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckFastElements(a0, a3, &check_number_dictionary); 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 460b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateFastArrayLoad(masm, receiver, key, a0, a3, t0, v0, NULL, &slow); 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, t0, a3); 462b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 463b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 464b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_number_dictionary); 465b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t0, FieldMemOperand(receiver, JSObject::kElementsOffset)); 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(a3, FieldMemOperand(t0, JSObject::kMapOffset)); 467b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 468b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check whether the elements is a number dictionary. 469b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a3: elements map 470b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // t0: elements 471b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(at, Heap::kHashTableMapRootIndex); 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&slow, ne, a3, Operand(at)); 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sra(a0, key, kSmiTagSize); 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadFromNumberDictionary(&slow, t0, key, v0, a0, a3, t1); 475b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow case, key and receiver still in a2 and a1. 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, t0, 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch a3); 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateRuntimeGetProperty(masm); 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_name); 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateKeyNameCheck(masm, key, a0, a3, &index_name, &slow); 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 486b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateKeyedLoadReceiverCheck(masm, receiver, a0, a3, 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kHasNamedInterceptor, &slow); 488b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 489b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 490b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the receiver is a fast-case object, check the keyed lookup 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // cache. Otherwise probe the dictionary. 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(a3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t0, FieldMemOperand(a3, HeapObject::kMapOffset)); 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(at, Heap::kHashTableMapRootIndex); 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&probe_dictionary, eq, t0, Operand(at)); 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the map of the receiver, compute the keyed lookup cache hash 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // based on 32 bits of the map pointer and the name hash. 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(a0, FieldMemOperand(receiver, HeapObject::kMapOffset)); 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sra(a3, a0, KeyedLookupCache::kMapHashShift); 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t0, FieldMemOperand(key, Name::kHashFieldOffset)); 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sra(at, t0, Name::kHashShift); 503b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ xor_(a3, a3, at); 504b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int mask = KeyedLookupCache::kCapacityMask & KeyedLookupCache::kHashMask; 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(a3, a3, Operand(mask)); 506b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the key (consisting of map and unique name) from the cache and 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // check for match. 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label load_in_object_property; 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch static const int kEntriesPerBucket = KeyedLookupCache::kEntriesPerBucket; 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label hit_on_nth_entry[kEntriesPerBucket]; 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference cache_keys = 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::keyed_lookup_cache_keys(isolate); 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ li(t0, Operand(cache_keys)); 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sll(at, a3, kPointerSizeLog2 + 1); 516b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addu(t0, t0, at); 517b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = 0; i < kEntriesPerBucket - 1; i++) { 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label try_next_entry; 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t1, MemOperand(t0, kPointerSize * i * 2)); 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&try_next_entry, ne, a0, Operand(t1)); 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t1, MemOperand(t0, kPointerSize * (i * 2 + 1))); 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&hit_on_nth_entry[i], eq, key, Operand(t1)); 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&try_next_entry); 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 526b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t1, MemOperand(t0, kPointerSize * (kEntriesPerBucket - 1) * 2)); 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&slow, ne, a0, Operand(t1)); 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t1, MemOperand(t0, kPointerSize * ((kEntriesPerBucket - 1) * 2 + 1))); 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&slow, ne, key, Operand(t1)); 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 532b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get field offset. 533b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a0 : receiver's map 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a3 : lookup cache index 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference cache_field_offsets = 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference::keyed_lookup_cache_field_offsets(isolate); 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Hit on nth entry. 539b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch for (int i = kEntriesPerBucket - 1; i >= 0; i--) { 540b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&hit_on_nth_entry[i]); 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ li(t0, Operand(cache_field_offsets)); 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sll(at, a3, kPointerSizeLog2); 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addu(at, t0, at); 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t1, MemOperand(at, kPointerSize * i)); 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lbu(t2, FieldMemOperand(a0, Map::kInObjectPropertiesOffset)); 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Subu(t1, t1, t2); 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&property_array_property, ge, t1, Operand(zero_reg)); 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (i != 0) { 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&load_in_object_property); 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load in-object property. 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&load_in_object_property); 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lbu(t2, FieldMemOperand(a0, Map::kInstanceSizeOffset)); 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addu(t2, t2, t1); // Index from start of object. 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Subu(receiver, receiver, Operand(kHeapObjectTag)); // Remove the heap tag. 558b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sll(at, t2, kPointerSizeLog2); 559b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addu(at, receiver, at); 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(v0, MemOperand(at)); 561b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), 1, 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t0, a3); 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 564b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load property array property. 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&property_array_property); 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(receiver, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 568b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(receiver, receiver, FixedArray::kHeaderSize - kHeapObjectTag); 569b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sll(v0, t1, kPointerSizeLog2); 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(v0, v0, receiver); 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(v0, MemOperand(v0)); 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(isolate->counters()->keyed_load_generic_lookup_cache(), 1, 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t0, a3); 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 575b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 576b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do a quick inline probe of the receiver's dictionary, if it 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // exists. 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&probe_dictionary); 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a3: elements 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(a0, FieldMemOperand(receiver, HeapObject::kMapOffset)); 582b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lbu(a0, FieldMemOperand(a0, Map::kInstanceTypeOffset)); 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateGlobalInstanceTypeCheck(masm, a0, &slow); 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the property to v0. 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryLoad(masm, &slow, a3, key, v0, t1, t0); 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(), 1, t0, 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch a3); 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&index_name); 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IndexFromHash(a3, key); 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Now jump to the place where smi keys are handled. 593b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&index_smi); 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedLoadIC::GenerateString(MacroAssembler* masm) { 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Return address is in ra. 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = LoadDescriptor::ReceiverRegister(); 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register index = LoadDescriptor::NameRegister(); 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch = a3; 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result = v0; 605b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!scratch.is(receiver) && !scratch.is(index)); 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StringCharAtGenerator char_at_generator(receiver, index, scratch, result, 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &miss, // When not a string. 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &miss, // When not a number. 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &miss, // When index out of range. 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STRING_INDEX_IS_ARRAY_INDEX); 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char_at_generator.GenerateFast(masm); 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 614b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 615b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StubRuntimeCallHelper call_helper; 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch char_at_generator.GenerateSlow(masm, call_helper); 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMiss(masm); 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void KeyedStoreGenerateGenericHelper( 624b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length, 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, Register key, Register receiver, Register receiver_map, 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements_map, Register elements) { 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label transition_smi_elements; 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label finish_object_store, non_double_value, transition_double_elements; 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label fast_double_without_map_check; 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fast case: Do the store, could be either Object or double. 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(fast_object); 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch_value = t0; 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register address = t1; 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (check_map == kCheckMap) { 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(fast_double, ne, elements_map, 639b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(masm->isolate()->factory()->fixed_array_map())); 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // HOLECHECK: guards "A[i] = V" 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to go to the runtime if the current value is the hole because 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // there may be a callback on the element. 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label holecheck_passed1; 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(address, elements, FixedArray::kHeaderSize - kHeapObjectTag); 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sll(at, key, kPointerSizeLog2 - kSmiTagSize); 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addu(address, address, at); 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch_value, MemOperand(address)); 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&holecheck_passed1, ne, scratch_value, 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(masm->isolate()->factory()->the_hole_value())); 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch_value, 653b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch slow); 654b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 655b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&holecheck_passed1); 656b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 657b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Smi stores don't require further checks. 658b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label non_smi_value; 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(value, &non_smi_value); 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (increment_length == kIncrementLength) { 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add 1 to receiver->length. 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch_value, key, Operand(Smi::FromInt(1))); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sw(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's irrelevant whether array is smi-only or not when writing a smi. 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize); 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(address, address, scratch_value); 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sw(value, MemOperand(address)); 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 673b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&non_smi_value); 674b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Escape to elements kind transition case. 675b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckFastObjectElements(receiver_map, scratch_value, 676b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &transition_smi_elements); 677b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 678b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fast elements array, store the value to the elements backing store. 679b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&finish_object_store); 680b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (increment_length == kIncrementLength) { 681b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add 1 to receiver->length. 682b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch_value, key, Operand(Smi::FromInt(1))); 683b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sw(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); 684b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 685b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 686b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sll(scratch_value, key, kPointerSizeLog2 - kSmiTagSize); 687b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(address, address, scratch_value); 688b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sw(value, MemOperand(address)); 689b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update write barrier for the elements array address. 690b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch_value, value); // Preserve the value which is returned. 691b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWrite(elements, address, scratch_value, kRAHasNotBeenSaved, 692b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 693b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 694b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 695b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(fast_double); 696b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (check_map == kCheckMap) { 697b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for fast double array case. If this fails, call through to the 698b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // runtime. 699b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(at, Heap::kFixedDoubleArrayMapRootIndex); 700b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(slow, ne, elements_map, Operand(at)); 701b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 702b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 703b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // HOLECHECK: guards "A[i] double hole?" 704b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to see if the double version of the hole is present. If so 705b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // go to the runtime. 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(address, elements, Operand(FixedDoubleArray::kHeaderSize + 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kHoleNanUpper32Offset - kHeapObjectTag)); 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sll(at, key, kPointerSizeLog2); 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ addu(address, address, at); 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(scratch_value, MemOperand(address)); 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&fast_double_without_map_check, ne, scratch_value, 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(kHoleNanUpper32)); 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch_value, 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch slow); 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&fast_double_without_map_check); 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ StoreNumberToDoubleElements(value, key, 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements, // Overwritten. 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch a3, // Scratch regs... 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch t0, t1, &transition_double_elements); 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (increment_length == kIncrementLength) { 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add 1 to receiver->length. 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Addu(scratch_value, key, Operand(Smi::FromInt(1))); 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ sw(scratch_value, FieldMemOperand(receiver, JSArray::kLengthOffset)); 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&transition_smi_elements); 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Transition the array appropriately depending on the value type. 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t0, FieldMemOperand(value, HeapObject::kMapOffset)); 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(at, Heap::kHeapNumberMapRootIndex); 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&non_double_value, ne, t0, Operand(at)); 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Value is a double. Transition FAST_SMI_ELEMENTS -> 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FAST_DOUBLE_ELEMENTS and complete the store. 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadTransitionedArrayMapConditional( 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, t0, slow); 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteMode mode = 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS); 740b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value, 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch receiver_map, mode, slow); 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 743b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&fast_double_without_map_check); 744b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 745b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&non_double_value); 746b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS 747b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, 748b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch receiver_map, t0, slow); 749b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsTransitionGenerator::GenerateMapChangeElementsTransition( 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, receiver, key, value, receiver_map, mode, slow); 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&finish_object_store); 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&transition_double_elements); 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch receiver_map, t0, slow); 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsTransitionGenerator::GenerateDoubleToObject( 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, receiver, key, value, receiver_map, mode, slow); 764b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 765b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&finish_object_store); 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedStoreIC::GenerateGeneric(MacroAssembler* masm, 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StrictMode strict_mode) { 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ---------- S t a t e -------------- 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- a0 : value 773b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- a1 : key 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- a2 : receiver 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- ra : return address 776b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, fast_object, fast_object_grow; 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label fast_double, fast_double_grow; 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label array, extra, check_if_double_array; 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Register usage. 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = StoreDescriptor::ValueRegister(); 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key = StoreDescriptor::NameRegister(); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = StoreDescriptor::ReceiverRegister(); 785b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value.is(a0)); 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver_map = a3; 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements_map = t2; 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements = t3; // Elements array of the receiver. 789b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // t0 and t1 are used as general scratch registers. 790b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the key is a smi. 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(key, &slow); 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the object isn't a smi. 794b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(receiver, &slow); 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the map of the object. 796b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the receiver does not require access checks and is not observed. 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The generic stub does not perform map checks or handle observed objects. 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lbu(t0, FieldMemOperand(receiver_map, Map::kBitFieldOffset)); 800b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ And(t0, t0, 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved)); 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&slow, ne, t0, Operand(zero_reg)); 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the object is a JS array or not. 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lbu(t0, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset)); 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&array, eq, t0, Operand(JS_ARRAY_TYPE)); 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the object is some kind of JSObject. 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&slow, lt, t0, Operand(FIRST_JS_OBJECT_TYPE)); 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Object case: Check key against length in the elements array. 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check array bounds. Both the key and the length of FixedArray are smis. 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&fast_object, lo, key, Operand(t0)); 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow case, handle jump to runtime. 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Entry registers are intact. 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a0: value. 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a1: key. 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // a2: receiver. 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyICCompiler::GenerateRuntimeSetProperty(masm, strict_mode); 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Extra capacity case: Check if there is extra capacity to 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // perform the store and update the length. Used for adding one 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // element to the array by writing to array[array.length]. 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&extra); 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Condition code from comparing key and array length is still available. 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Only support writing to array[array.length]. 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&slow, ne, key, Operand(t0)); 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for room in the elements backing store. 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Both the key and the length of FixedArray are smis. 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t0, FieldMemOperand(elements, FixedArray::kLengthOffset)); 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&slow, hs, key, Operand(t0)); 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&check_if_double_array, ne, elements_map, 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Heap::kFixedArrayMapRootIndex); 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&fast_object_grow); 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 840b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_if_double_array); 841b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&slow, ne, elements_map, Heap::kFixedDoubleArrayMapRootIndex); 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&fast_double_grow); 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Array case: Get the length and the elements array from the JS 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // array. Check that the array is in fast mode (and writable); if it 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is the length is always a smi. 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&array); 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the key against the length in the array. 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(t0, FieldMemOperand(receiver, JSArray::kLengthOffset)); 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Branch(&extra, hs, key, Operand(t0)); 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch KeyedStoreGenerateGenericHelper( 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, &fast_object, &fast_double, &slow, kCheckMap, kDontIncrementLength, 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value, key, receiver, receiver_map, elements_map, elements); 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch KeyedStoreGenerateGenericHelper(masm, &fast_object_grow, &fast_double_grow, 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &slow, kDontCheckMap, kIncrementLength, value, 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch key, receiver, receiver_map, elements_map, 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch elements); 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Push receiver, key and value for runtime call. 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreDescriptor::ValueRegister()); 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(kKeyedStoreIC_Miss), masm->isolate()); 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(ref, 3, 1); 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = StoreDescriptor::ReceiverRegister(); 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name = StoreDescriptor::NameRegister(); 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(receiver.is(a1)); 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name.is(a2)); 880b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(a0)); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the receiver from the stack and probe the stub cache. 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::ComputeHandlerFlags(Code::STORE_IC)); 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm->isolate()->stub_cache()->GenerateProbe(masm, flags, false, receiver, 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, a3, t0, t1, t2); 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Cache miss: Jump to runtime. 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMiss(masm); 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StoreIC::GenerateMiss(MacroAssembler* masm) { 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch StoreDescriptor::ValueRegister()); 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform tail call to the entry. 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference ref = 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ TailCallExternalReference(ref, 3, 1); 900b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 901b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StoreIC::GenerateNormal(MacroAssembler* masm) { 904b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 905b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = StoreDescriptor::ReceiverRegister(); 906b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name = StoreDescriptor::NameRegister(); 907b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = StoreDescriptor::ValueRegister(); 908b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dictionary = a3; 909b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(receiver.is(a1)); 910b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name.is(a2)); 911b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value.is(a0)); 912b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 913b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ lw(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 914b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 915b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryStore(masm, &miss, dictionary, name, value, t0, t1); 916b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = masm->isolate()->counters(); 917b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->store_normal_hit(), 1, t0, t1); 918b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 919b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 920b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 921b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(counters->store_normal_miss(), 1, t0, t1); 922b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMiss(masm); 923b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 924b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 925b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 926b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 927b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 928b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 929b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition CompareIC::ComputeCondition(Token::Value op) { 930b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 931b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::EQ_STRICT: 932b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::EQ: 933b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return eq; 934b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::LT: 935b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return lt; 936b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::GT: 937b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return gt; 938b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::LTE: 939b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return le; 940b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::GTE: 941b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ge; 942b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 943b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 944b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return kNoCondition; 945b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 946b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 947b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 948b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 949b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CompareIC::HasInlinedSmiCode(Address address) { 950b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The address of the instruction following the call. 951b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address andi_instruction_address = 952b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address + Assembler::kCallTargetAddressOffset; 953b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 954b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the instruction following the call is not a andi at, rx, #yyy, nothing 955b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // was inlined. 956b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr instr = Assembler::instr_at(andi_instruction_address); 957b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Assembler::IsAndImmediate(instr) && 958b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::GetRt(instr) == static_cast<uint32_t>(zero_reg.code()); 959b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 960b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 961b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 962b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid PatchInlinedSmiCode(Address address, InlinedSmiCheck check) { 963b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address andi_instruction_address = 964b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch address + Assembler::kCallTargetAddressOffset; 965b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 966b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the instruction following the call is not a andi at, rx, #yyy, nothing 967b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // was inlined. 968b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr instr = Assembler::instr_at(andi_instruction_address); 969b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!(Assembler::IsAndImmediate(instr) && 970b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::GetRt(instr) == static_cast<uint32_t>(zero_reg.code()))) { 971b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 972b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 973b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 974b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The delta to the start of the map check instruction and the 975b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // condition code uses at the patched jump. 976b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int delta = Assembler::GetImmediate16(instr); 977b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delta += Assembler::GetRs(instr) * kImm16Mask; 978b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the delta is 0 the instruction is andi at, zero_reg, #0 which also 979b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // signals that nothing was inlined. 980b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (delta == 0) { 981b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 982b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 983b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 984b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trace_ic) { 985b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("[ patching ic at %p, andi=%p, delta=%d\n", address, 986b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch andi_instruction_address, delta); 987b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 988b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 989b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address patch_address = 990b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch andi_instruction_address - delta * Instruction::kInstrSize; 991b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr instr_at_patch = Assembler::instr_at(patch_address); 992b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr branch_instr = 993b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::instr_at(patch_address + Instruction::kInstrSize); 994b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is patching a conditional "jump if not smi/jump if smi" site. 995b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Enabling by changing from 996b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // andi at, rx, 0 997b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Branch <target>, eq, at, Operand(zero_reg) 998b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to: 999b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // andi at, rx, #kSmiTagMask 1000b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Branch <target>, ne, at, Operand(zero_reg) 1001b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and vice-versa to be disabled again. 1002b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch CodePatcher patcher(patch_address, 2); 1003b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = Register::from_code(Assembler::GetRs(instr_at_patch)); 1004b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (check == ENABLE_INLINED_SMI_CHECK) { 1005b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsAndImmediate(instr_at_patch)); 1006b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(0, Assembler::GetImmediate16(instr_at_patch)); 1007b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->andi(at, reg, kSmiTagMask); 1008b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1009b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(check == DISABLE_INLINED_SMI_CHECK); 1010b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsAndImmediate(instr_at_patch)); 1011b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->andi(at, reg, 0); 1012b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1013b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsBranch(branch_instr)); 1014b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Assembler::IsBeq(branch_instr)) { 1015b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.ChangeBranchCondition(ne); 1016b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 1017b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsBne(branch_instr)); 1018b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.ChangeBranchCondition(eq); 1019b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 1020b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1021b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 1022b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} // namespace v8::internal 1023b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 1024b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_MIPS 1025