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#if V8_TARGET_ARCH_ARM 6b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 7b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/codegen.h" 8b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic.h" 9b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/ic-compiler.h" 10b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#include "src/ic/stub-cache.h" 11b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 12b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace v8 { 13b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochnamespace internal { 14b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 15b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 16b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// ---------------------------------------------------------------------------- 17b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Static IC stub generators. 18b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 19b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 20b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#define __ ACCESS_MASM(masm) 21b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 22b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 23b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, Register type, 24b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* global_object) { 25b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Register usage: 26b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // type: holds the receiver instance type on entry. 27b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(type, Operand(JS_GLOBAL_OBJECT_TYPE)); 28b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, global_object); 29b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); 30b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, global_object); 31b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 32b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 33b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 34b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Helper function used from LoadIC GenerateNormal. 35b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 36b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// elements: Property dictionary. It is not clobbered if a jump to the miss 37b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// label is done. 38b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// name: Property name. It is not clobbered if a jump to the miss label is 39b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// done 40b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// result: Register for the result. It is only updated if a jump to the miss 41b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// label is not done. Can be the same as elements or name clobbering 42b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// one of these in the case of not jumping to the miss label. 43b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The two scratch registers need to be different from elements, name and 44b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// result. 45b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The generated code assumes that the receiver has slow properties, 46b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// is not a global object and does not have interceptors. 47b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss, 48b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements, Register name, 49b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register result, Register scratch1, 50b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2) { 51b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Main use of the scratch registers. 52b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch1: Used as temporary and to hold the capacity of the property 53b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // dictionary. 54b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch2: Used as temporary. 55b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 56b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 57b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Probe the dictionary. 58b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss, &done, elements, 59b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, scratch1, scratch2); 60b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 61b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If probing finds an entry check that the value is a normal 62b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // property. 63b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); // scratch2 == elements + 4 * index 64b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kElementsStartOffset = 65b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kHeaderSize + 66b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kElementsStartIndex * kPointerSize; 67b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 68b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); 69b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tst(scratch1, Operand(PropertyDetails::TypeField::kMask << kSmiTagSize)); 70b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, miss); 71b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 72b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the value at the masked, scaled index and return. 73b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(result, 74b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); 75b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 76b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 77b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 78b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Helper function used from StoreIC::GenerateNormal. 79b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// 80b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// elements: Property dictionary. It is not clobbered if a jump to the miss 81b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// label is done. 82b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// name: Property name. It is not clobbered if a jump to the miss label is 83b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// done 84b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// value: The value to store. 85b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The two scratch registers need to be different from elements, name and 86b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// result. 87b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// The generated code assumes that the receiver has slow properties, 88b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// is not a global object and does not have interceptors. 89b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateDictionaryStore(MacroAssembler* masm, Label* miss, 90b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements, Register name, 91b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, Register scratch1, 92b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch2) { 93b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Main use of the scratch registers. 94b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch1: Used as temporary and to hold the capacity of the property 95b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // dictionary. 96b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // scratch2: Used as temporary. 97b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label done; 98b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 99b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Probe the dictionary. 100b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss, &done, elements, 101b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch name, scratch1, scratch2); 102b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 103b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If probing finds an entry in the dictionary check that the value 104b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is a normal property that is not read only. 105b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&done); // scratch2 == elements + 4 * index 106b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kElementsStartOffset = 107b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kHeaderSize + 108b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch NameDictionary::kElementsStartIndex * kPointerSize; 109b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; 110b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kTypeAndReadOnlyMask = 111b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch (PropertyDetails::TypeField::kMask | 112b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PropertyDetails::AttributesField::encode(READ_ONLY)) 113b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch << kSmiTagSize; 114b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); 115b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tst(scratch1, Operand(kTypeAndReadOnlyMask)); 116b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, miss); 117b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 118b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Store the value at the masked, scaled index and return. 119b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch const int kValueOffset = kElementsStartOffset + kPointerSize; 120b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(scratch2, scratch2, Operand(kValueOffset - kHeapObjectTag)); 121b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(value, MemOperand(scratch2)); 122b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 123b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update the write barrier. Make sure not to clobber the value. 124b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(scratch1, value); 125b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ RecordWrite(elements, scratch2, scratch1, kLRHasNotBeenSaved, 126b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs); 127b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 128b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 129b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 130b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Checks the receiver for special cases (value type, slow case bits). 131b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Falls through for regular JS object. 132b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateKeyedLoadReceiverCheck(MacroAssembler* masm, 133b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver, Register map, 134b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch, 135b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int interceptor_bit, Label* slow) { 136b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the object isn't a smi. 137b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(receiver, slow); 138b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the map of the receiver. 139b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 140b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check bit field. 141b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(scratch, FieldMemOperand(map, Map::kBitFieldOffset)); 142b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tst(scratch, 143b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand((1 << Map::kIsAccessCheckNeeded) | (1 << interceptor_bit))); 144b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, slow); 145b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the object is some kind of JS object EXCEPT JS Value type. 146b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // In the case that the object is a value-wrapper object, 147b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // we enter the runtime system to make sure that indexing into string 148b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // objects work as intended. 149b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(JS_OBJECT_TYPE > JS_VALUE_TYPE); 150b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(scratch, FieldMemOperand(map, Map::kInstanceTypeOffset)); 151b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(scratch, Operand(JS_OBJECT_TYPE)); 152b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lt, slow); 153b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 154b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 155b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 156b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Loads an indexed element from a fast case array. 157b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateFastArrayLoad(MacroAssembler* masm, Register receiver, 158b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key, Register elements, 159b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register scratch1, Register scratch2, 160014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register result, Label* slow, 161014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LanguageMode language_mode) { 162b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Register use: 163b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 164b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // receiver - holds the receiver on entry. 165b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unchanged unless 'result' is the same register. 166b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 167b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // key - holds the smi key on entry. 168b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unchanged unless 'result' is the same register. 169b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 170b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // result - holds the result on exit if the load succeeded. 171b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Allowed to be the the same as 'receiver' or 'key'. 172b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Unchanged on bailout so 'receiver' and 'key' can be safely 173b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // used by further computation. 174b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 175b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Scratch registers: 176b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 177014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // elements - holds the elements of the receiver and its prototypes. 178014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 179014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // scratch1 - used to hold elements length, bit fields, base addresses. 180b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // 181014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // scratch2 - used to hold maps, prototypes, and the loaded value. 182014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label check_prototypes, check_next_prototype; 183014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Label done, in_bounds, absent; 184b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 185b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 186014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ AssertFastElements(elements); 187014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 188b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the key (index) is within bounds. 189b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch1, FieldMemOperand(elements, FixedArray::kLengthOffset)); 190b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(key, Operand(scratch1)); 191014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(lo, &in_bounds); 192014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Out-of-bounds. Check the prototype chain to see if we can just return 193014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // 'undefined'. 194014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(key, Operand(0)); 195014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(lt, slow); // Negative keys can't take the fast OOB path. 196014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&check_prototypes); 197014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(scratch2, FieldMemOperand(receiver, HeapObject::kMapOffset)); 198014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&check_next_prototype); 199014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(scratch2, FieldMemOperand(scratch2, Map::kPrototypeOffset)); 200014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // scratch2: current prototype 201014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(scratch2, Heap::kNullValueRootIndex); 202014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(eq, &absent); 203014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(elements, FieldMemOperand(scratch2, JSObject::kElementsOffset)); 204014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(scratch2, FieldMemOperand(scratch2, HeapObject::kMapOffset)); 205014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // elements: elements of current prototype 206014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // scratch2: map of current prototype 207014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareInstanceType(scratch2, scratch1, JS_OBJECT_TYPE); 208014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(lo, slow); 209014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldrb(scratch1, FieldMemOperand(scratch2, Map::kBitFieldOffset)); 210014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ tst(scratch1, Operand((1 << Map::kIsAccessCheckNeeded) | 211014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch (1 << Map::kHasIndexedInterceptor))); 212014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(ne, slow); 213014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(elements, Heap::kEmptyFixedArrayRootIndex); 214014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(ne, slow); 215014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&check_next_prototype); 216014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 217014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&absent); 218014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch if (is_strong(language_mode)) { 219014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Strong mode accesses must throw in this case, so call the runtime. 220014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(slow); 221014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } else { 222014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(result, Heap::kUndefinedValueRootIndex); 223014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ jmp(&done); 224014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch } 225014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 226014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&in_bounds); 227b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fast case: Do the load. 228b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(scratch1, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 229b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(scratch2, MemOperand::PointerAddressFromSmiKey(scratch1, key)); 230014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(scratch2, Heap::kTheHoleValueRootIndex); 231014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // In case the loaded value is the_hole we have to check the prototype chain. 232014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(eq, &check_prototypes); 233b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(result, scratch2); 234014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ bind(&done); 235b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 236b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 237b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 238b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Checks whether a key is an array index string or a unique name. 239b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// Falls through if a key is a unique name. 240b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic void GenerateKeyNameCheck(MacroAssembler* masm, Register key, 241b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register map, Register hash, 242b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label* index_string, Label* not_unique) { 243b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The key is not a smi. 244b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label unique; 245b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Is it a name? 246b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareObjectType(key, map, hash, LAST_UNIQUE_NAME_TYPE); 247b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(hi, not_unique); 248b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(LAST_UNIQUE_NAME_TYPE == FIRST_NONSTRING_TYPE); 249b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &unique); 250b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 251b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Is the string an array index, with cached numeric value? 252b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(hash, FieldMemOperand(key, Name::kHashFieldOffset)); 253b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tst(hash, Operand(Name::kContainsCachedArrayIndexMask)); 254b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, index_string); 255b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 256b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Is the string internalized? We know it's a string, so a single 257b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // bit test is enough. 258b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // map: key map 259b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(hash, FieldMemOperand(map, Map::kInstanceTypeOffset)); 260b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch STATIC_ASSERT(kInternalizedTag == 0); 261b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tst(hash, Operand(kIsNotInternalizedMask)); 262b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, not_unique); 263b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 264b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&unique); 265b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 266b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 267b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 268014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LoadIC::GenerateNormal(MacroAssembler* masm, LanguageMode language_mode) { 269b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register dictionary = r0; 270b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); 271b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); 272b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 273b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow; 274b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 275b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(dictionary, FieldMemOperand(LoadDescriptor::ReceiverRegister(), 276b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch JSObject::kPropertiesOffset)); 277b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryLoad(masm, &slow, dictionary, 278b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch LoadDescriptor::NameRegister(), r0, r3, r4); 279b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 280b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 281b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Dictionary load failed, go slow (but don't miss). 282b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 283014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateRuntimeGetProperty(masm, language_mode); 284b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 285b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 286b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 287b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch// A register that isn't one of the parameters to the load ic. 288b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochstatic const Register LoadIC_TempRegister() { return r3; } 289b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 290b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 291958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void LoadIC_PushArgs(MacroAssembler* masm) { 292958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register receiver = LoadDescriptor::ReceiverRegister(); 293958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Register name = LoadDescriptor::NameRegister(); 294014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register slot = LoadDescriptor::SlotRegister(); 295014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register vector = LoadWithVectorDescriptor::VectorRegister(); 296958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 297014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ Push(receiver, name, slot, vector); 298958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier} 299958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 300958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 301b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid LoadIC::GenerateMiss(MacroAssembler* masm) { 302b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The return address is in lr. 303b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 304b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 305014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!AreAliased(r4, r5, LoadWithVectorDescriptor::SlotRegister(), 306014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadWithVectorDescriptor::VectorRegister())); 307958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(isolate->counters()->load_miss(), 1, r4, r5); 308b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 309958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier LoadIC_PushArgs(masm); 310b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 311b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform tail call to the entry. 312014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kLoadIC_Miss); 313b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 314b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 315b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 316014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, 317014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LanguageMode language_mode) { 318b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The return address is in lr. 319b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 320b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ mov(LoadIC_TempRegister(), LoadDescriptor::ReceiverRegister()); 321b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(LoadIC_TempRegister(), LoadDescriptor::NameRegister()); 322b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 323014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Do tail-call to runtime routine. 324014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(is_strong(language_mode) ? Runtime::kGetPropertyStrong 325014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : Runtime::kGetProperty); 326b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 327b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 328b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 329b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid KeyedLoadIC::GenerateMiss(MacroAssembler* masm) { 330b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The return address is in lr. 331b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 332b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 333014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!AreAliased(r4, r5, LoadWithVectorDescriptor::SlotRegister(), 334014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LoadWithVectorDescriptor::VectorRegister())); 335958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ IncrementCounter(isolate->counters()->keyed_load_miss(), 1, r4, r5); 336b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 337958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier LoadIC_PushArgs(masm); 338b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 339b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform tail call to the entry. 340014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kKeyedLoadIC_Miss); 341b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 342b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 343b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 344014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid KeyedLoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm, 345014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LanguageMode language_mode) { 346b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The return address is in lr. 347b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 348b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); 349b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 350014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Perform tail call to the entry. 351014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Do tail-call to runtime routine. 352014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(is_strong(language_mode) ? Runtime::kKeyedGetPropertyStrong 353014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch : Runtime::kKeyedGetProperty); 354b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 355b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 356b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 357014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid KeyedLoadIC::GenerateMegamorphic(MacroAssembler* masm, 358014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LanguageMode language_mode) { 359b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The return address is in lr. 360b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, check_name, index_smi, index_name, property_array_property; 361b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label probe_dictionary, check_number_dictionary; 362b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 363b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key = LoadDescriptor::NameRegister(); 364b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = LoadDescriptor::ReceiverRegister(); 365b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(key.is(r2)); 366b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(receiver.is(r1)); 367b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 368b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Isolate* isolate = masm->isolate(); 369b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 370b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the key is a smi. 371b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(key, &check_name); 372b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&index_smi); 373b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Now the key is known to be a smi. This place is also jumped to from below 374b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // where a numeric string is converted to a smi. 375b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 376b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateKeyedLoadReceiverCheck(masm, receiver, r0, r3, 377b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kHasIndexedInterceptor, &slow); 378b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 379b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the receiver's map to see if it has fast elements. 380b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CheckFastElements(r0, r3, &check_number_dictionary); 381b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 382014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateFastArrayLoad(masm, receiver, key, r0, r3, r4, r0, &slow, 383014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch language_mode); 384b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(isolate->counters()->keyed_load_generic_smi(), 1, r4, r3); 385b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 386b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 387b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_number_dictionary); 388b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r4, FieldMemOperand(receiver, JSObject::kElementsOffset)); 389b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(r4, JSObject::kMapOffset)); 390b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 391b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check whether the elements is a number dictionary. 392b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r3: elements map 393b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r4: elements 394b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 395b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r3, ip); 396b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &slow); 397b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ SmiUntag(r0, key); 398b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadFromNumberDictionary(&slow, r4, key, r0, r0, r3, r5); 399b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 400b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 401b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow case, key and receiver still in r2 and r1. 402b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 403b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(isolate->counters()->keyed_load_generic_slow(), 1, r4, 404b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r3); 405014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateRuntimeGetProperty(masm, language_mode); 406b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 407b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_name); 408b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateKeyNameCheck(masm, key, r0, r3, &index_name, &slow); 409b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 410b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateKeyedLoadReceiverCheck(masm, receiver, r0, r3, 411b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Map::kHasNamedInterceptor, &slow); 412b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 413014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // If the receiver is a fast-case object, check the stub cache. Otherwise 414014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // probe the dictionary. 415b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r3, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 416b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r4, FieldMemOperand(r3, HeapObject::kMapOffset)); 417b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadRoot(ip, Heap::kHashTableMapRootIndex); 418b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r4, ip); 419b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &probe_dictionary); 420b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 421014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The handlers in the stub cache expect a vector and slot. Since we won't 422014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // change the IC from any downstream misses, a dummy vector can be used. 423014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register vector = LoadWithVectorDescriptor::VectorRegister(); 424014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register slot = LoadWithVectorDescriptor::SlotRegister(); 425014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!AreAliased(vector, slot, r4, r5, r6, r9)); 426014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<TypeFeedbackVector> dummy_vector = 427014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TypeFeedbackVector::DummyVector(masm->isolate()); 428014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int slot_index = dummy_vector->GetIndex( 429014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedLoadICSlot)); 430014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(vector, Heap::kDummyVectorRootIndex); 431014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(slot, Operand(Smi::FromInt(slot_index))); 432b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 433014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 434014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Code::ComputeHandlerFlags(Code::LOAD_IC)); 435014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch masm->isolate()->stub_cache()->GenerateProbe(masm, Code::KEYED_LOAD_IC, flags, 436014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver, key, r4, r5, r6, r9); 437014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Cache miss. 438014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateMiss(masm); 439b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 440b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Do a quick inline probe of the receiver's dictionary, if it 441b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // exists. 442b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&probe_dictionary); 443b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r3: elements 444b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(r0, FieldMemOperand(receiver, HeapObject::kMapOffset)); 445b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(r0, FieldMemOperand(r0, Map::kInstanceTypeOffset)); 446b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateGlobalInstanceTypeCheck(masm, r0, &slow); 447b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Load the property to r0. 448b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateDictionaryLoad(masm, &slow, r3, key, r0, r5, r4); 449b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IncrementCounter(isolate->counters()->keyed_load_generic_symbol(), 1, r4, 450b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch r3); 451b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 452b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 453b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&index_name); 454b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ IndexFromHash(r3, key); 455b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Now jump to the place where smi keys are handled. 456b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&index_smi); 457b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 458b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 459b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 460014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochstatic void StoreIC_PushArgs(MacroAssembler* masm) { 461b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Push(StoreDescriptor::ReceiverRegister(), StoreDescriptor::NameRegister(), 462014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StoreDescriptor::ValueRegister(), 463014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VectorStoreICDescriptor::SlotRegister(), 464014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch VectorStoreICDescriptor::VectorRegister()); 465014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} 466b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 467014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 468014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { 469014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StoreIC_PushArgs(masm); 470014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 471014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); 472b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 473b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 474b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 475958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernierstatic void KeyedStoreGenerateMegamorphicHelper( 476b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch MacroAssembler* masm, Label* fast_object, Label* fast_double, Label* slow, 477b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch KeyedStoreCheckMap check_map, KeyedStoreIncrementLength increment_length, 478b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value, Register key, Register receiver, Register receiver_map, 479b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements_map, Register elements) { 480b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label transition_smi_elements; 481b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label finish_object_store, non_double_value, transition_double_elements; 482b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label fast_double_without_map_check; 483b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 484b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fast case: Do the store, could be either Object or double. 485b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(fast_object); 486014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register scratch = r4; 487b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register address = r5; 488014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!AreAliased(value, key, receiver, receiver_map, elements_map, elements, 489014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch scratch, address)); 490014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 491b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (check_map == kCheckMap) { 492b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); 493b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(elements_map, 494b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(masm->isolate()->factory()->fixed_array_map())); 495b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, fast_double); 496b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 497b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 498b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // HOLECHECK: guards "A[i] = V" 499b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to go to the runtime if the current value is the hole because 500b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // there may be a callback on the element 501b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label holecheck_passed1; 502b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 503014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(scratch, MemOperand::PointerAddressFromSmiKey(address, key, PreIndex)); 504014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(scratch, Operand(masm->isolate()->factory()->the_hole_value())); 505b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &holecheck_passed1); 506014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch, slow); 507b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 508b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&holecheck_passed1); 509b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 510b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Smi stores don't require further checks. 511b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label non_smi_value; 512b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfNotSmi(value, &non_smi_value); 513b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 514b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (increment_length == kIncrementLength) { 515b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add 1 to receiver->length. 516014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(scratch, key, Operand(Smi::FromInt(1))); 517014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); 518b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 519b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // It's irrelevant whether array is smi-only or not when writing a smi. 520b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 521b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(value, MemOperand::PointerAddressFromSmiKey(address, key)); 522b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 523b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 524b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&non_smi_value); 525b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Escape to elements kind transition case. 526014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CheckFastObjectElements(receiver_map, scratch, &transition_smi_elements); 527b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 528b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Fast elements array, store the value to the elements backing store. 529b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&finish_object_store); 530b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (increment_length == kIncrementLength) { 531b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add 1 to receiver->length. 532014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(scratch, key, Operand(Smi::FromInt(1))); 533014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); 534b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 535b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(address, elements, Operand(FixedArray::kHeaderSize - kHeapObjectTag)); 536b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(address, address, Operand::PointerOffsetFromSmiKey(key)); 537b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ str(value, MemOperand(address)); 538b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Update write barrier for the elements array address. 539014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(scratch, value); // Preserve the value which is returned. 540014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ RecordWrite(elements, address, scratch, kLRHasNotBeenSaved, 541b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kDontSaveFPRegs, EMIT_REMEMBERED_SET, OMIT_SMI_CHECK); 542b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 543b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 544b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(fast_double); 545b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (check_map == kCheckMap) { 546b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for fast double array case. If this fails, call through to the 547b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // runtime. 548b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ CompareRoot(elements_map, Heap::kFixedDoubleArrayMapRootIndex); 549b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, slow); 550b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 551b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 552b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // HOLECHECK: guards "A[i] double hole?" 553b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // We have to see if the double version of the hole is present. If so 554b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // go to the runtime. 555b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ add(address, elements, 556b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand((FixedDoubleArray::kHeaderSize + sizeof(kHoleNanLower32)) - 557b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch kHeapObjectTag)); 558014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(scratch, MemOperand(address, key, LSL, kPointerSizeLog2, PreIndex)); 559014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(scratch, Operand(kHoleNanUpper32)); 560b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &fast_double_without_map_check); 561014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ JumpIfDictionaryInPrototypeChain(receiver, elements_map, scratch, slow); 562b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 563b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&fast_double_without_map_check); 564014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ StoreNumberToDoubleElements(value, key, elements, scratch, d0, 565b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch &transition_double_elements); 566b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (increment_length == kIncrementLength) { 567b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Add 1 to receiver->length. 568014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ add(scratch, key, Operand(Smi::FromInt(1))); 569014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ str(scratch, FieldMemOperand(receiver, JSArray::kLengthOffset)); 570b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 571b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 572b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 573b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&transition_smi_elements); 574b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Transition the array appropriately depending on the value type. 575014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ ldr(scratch, FieldMemOperand(value, HeapObject::kMapOffset)); 576014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ CompareRoot(scratch, Heap::kHeapNumberMapRootIndex); 577b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &non_double_value); 578b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 579b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Value is a double. Transition FAST_SMI_ELEMENTS -> 580b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // FAST_DOUBLE_ELEMENTS and complete the store. 581b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadTransitionedArrayMapConditional( 582014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS, receiver_map, scratch, slow); 583b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSiteMode mode = 584b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_DOUBLE_ELEMENTS); 585b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsTransitionGenerator::GenerateSmiToDouble(masm, receiver, key, value, 586b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch receiver_map, mode, slow); 587b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 588b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&fast_double_without_map_check); 589b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 590b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&non_double_value); 591b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Value is not a double, FAST_SMI_ELEMENTS -> FAST_ELEMENTS 592b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_SMI_ELEMENTS, FAST_ELEMENTS, 593014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver_map, scratch, slow); 594b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mode = AllocationSite::GetMode(FAST_SMI_ELEMENTS, FAST_ELEMENTS); 595b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsTransitionGenerator::GenerateMapChangeElementsTransition( 596b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, receiver, key, value, receiver_map, mode, slow); 597b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 598b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&finish_object_store); 599b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 600b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&transition_double_elements); 601b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Elements are FAST_DOUBLE_ELEMENTS, but value is an Object that's not a 602b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // HeapNumber. Make sure that the receiver is a Array with FAST_ELEMENTS and 603b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // transition array from FAST_DOUBLE_ELEMENTS to FAST_ELEMENTS 604b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ LoadTransitionedArrayMapConditional(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS, 605014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver_map, scratch, slow); 606b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch mode = AllocationSite::GetMode(FAST_DOUBLE_ELEMENTS, FAST_ELEMENTS); 607b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch ElementsTransitionGenerator::GenerateDoubleToObject( 608b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, receiver, key, value, receiver_map, mode, slow); 609b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 610b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&finish_object_store); 611b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 612b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 613b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 614958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Berniervoid KeyedStoreIC::GenerateMegamorphic(MacroAssembler* masm, 615014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch LanguageMode language_mode) { 616b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ---------- S t a t e -------------- 617b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- r0 : value 618b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- r1 : key 619b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- r2 : receiver 620b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // -- lr : return address 621b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // ----------------------------------- 622b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label slow, fast_object, fast_object_grow; 623b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label fast_double, fast_double_grow; 624958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Label array, extra, check_if_double_array, maybe_name_key, miss; 625b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 626b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Register usage. 627b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = StoreDescriptor::ValueRegister(); 628b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register key = StoreDescriptor::NameRegister(); 629b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = StoreDescriptor::ReceiverRegister(); 630b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(receiver.is(r1)); 631b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(key.is(r2)); 632b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value.is(r0)); 633b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver_map = r3; 634b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements_map = r6; 635b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register elements = r9; // Elements array of the receiver. 636b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r4 and r5 are used as general scratch registers. 637b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 638b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the key is a smi. 639958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotSmi(key, &maybe_name_key); 640b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the object isn't a smi. 641b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ JumpIfSmi(receiver, &slow); 642b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the map of the object. 643b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(receiver_map, FieldMemOperand(receiver, HeapObject::kMapOffset)); 644b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check that the receiver does not require access checks and is not observed. 645b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The generic stub does not perform map checks or handle observed objects. 646b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(ip, FieldMemOperand(receiver_map, Map::kBitFieldOffset)); 647b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ tst(ip, Operand(1 << Map::kIsAccessCheckNeeded | 1 << Map::kIsObserved)); 648b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &slow); 649b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check if the object is a JS array or not. 650b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldrb(r4, FieldMemOperand(receiver_map, Map::kInstanceTypeOffset)); 651b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(r4, Operand(JS_ARRAY_TYPE)); 652b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(eq, &array); 653014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // Check that the object is some kind of JS object EXCEPT JS Value type. In 654014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // the case that the object is a value-wrapper object, we enter the runtime 655014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // system to make sure that indexing into string objects works as intended. 656014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch STATIC_ASSERT(JS_VALUE_TYPE < JS_OBJECT_TYPE); 657014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ cmp(r4, Operand(JS_OBJECT_TYPE)); 658014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ b(lo, &slow); 659b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 660b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Object case: Check key against length in the elements array. 661b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 662b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check array bounds. Both the key and the length of FixedArray are smis. 663b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); 664b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(key, Operand(ip)); 665b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(lo, &fast_object); 666b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 667b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Slow case, handle jump to runtime. 668b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&slow); 669b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Entry registers are intact. 670b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r0: value. 671b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r1: key. 672b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // r2: receiver. 673014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch PropertyICCompiler::GenerateRuntimeSetProperty(masm, language_mode); 674958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Never returns to here. 675958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 676958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&maybe_name_key); 677958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldr(r4, FieldMemOperand(key, HeapObject::kMapOffset)); 678958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ ldrb(r4, FieldMemOperand(r4, Map::kInstanceTypeOffset)); 679958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ JumpIfNotUniqueNameInstanceType(r4, &slow); 680014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 681014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // We use register r8, because otherwise probing the megamorphic stub cache 682014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // would require pushing temporaries on the stack. 683014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // TODO(mvstanton): quit using register r8 when 684014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // FLAG_enable_embedded_constant_pool is turned on. 685014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!FLAG_enable_embedded_constant_pool); 686014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register temporary2 = r8; 687014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // The handlers in the stub cache expect a vector and slot. Since we won't 688014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch // change the IC from any downstream misses, a dummy vector can be used. 689014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register vector = VectorStoreICDescriptor::VectorRegister(); 690014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register slot = VectorStoreICDescriptor::SlotRegister(); 691014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 692014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(!AreAliased(vector, slot, r5, temporary2, r6, r9)); 693014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Handle<TypeFeedbackVector> dummy_vector = 694014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch TypeFeedbackVector::DummyVector(masm->isolate()); 695014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch int slot_index = dummy_vector->GetIndex( 696014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch FeedbackVectorSlot(TypeFeedbackVector::kDummyKeyedStoreICSlot)); 697014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ LoadRoot(vector, Heap::kDummyVectorRootIndex); 698014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ mov(slot, Operand(Smi::FromInt(slot_index))); 699014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch 700958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 701958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier Code::ComputeHandlerFlags(Code::STORE_IC)); 702958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier masm->isolate()->stub_cache()->GenerateProbe( 703014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch masm, Code::STORE_IC, flags, receiver, key, r5, temporary2, r6, r9); 704958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier // Cache miss. 705958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ b(&miss); 706b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 707b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Extra capacity case: Check if there is extra capacity to 708b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // perform the store and update the length. Used for adding one 709b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // element to the array by writing to array[array.length]. 710b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&extra); 711b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Condition code from comparing key and array length is still available. 712b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &slow); // Only support writing to writing to array[array.length]. 713b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check for room in the elements backing store. 714b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Both the key and the length of FixedArray are smis. 715b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(ip, FieldMemOperand(elements, FixedArray::kLengthOffset)); 716b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(key, Operand(ip)); 717b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(hs, &slow); 718b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements_map, FieldMemOperand(elements, HeapObject::kMapOffset)); 719b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(elements_map, Operand(masm->isolate()->factory()->fixed_array_map())); 720b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &check_if_double_array); 721b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&fast_object_grow); 722b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 723b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&check_if_double_array); 724b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(elements_map, 725b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Operand(masm->isolate()->factory()->fixed_double_array_map())); 726b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(ne, &slow); 727b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ jmp(&fast_double_grow); 728b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 729b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Array case: Get the length and the elements array from the JS 730b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // array. Check that the array is in fast mode (and writable); if it 731b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // is the length is always a smi. 732b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&array); 733b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(elements, FieldMemOperand(receiver, JSObject::kElementsOffset)); 734b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 735b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Check the key against the length in the array. 736b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(ip, FieldMemOperand(receiver, JSArray::kLengthOffset)); 737b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ cmp(key, Operand(ip)); 738b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ b(hs, &extra); 739b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 740958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier KeyedStoreGenerateMegamorphicHelper( 741b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch masm, &fast_object, &fast_double, &slow, kCheckMap, kDontIncrementLength, 742b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch value, key, receiver, receiver_map, elements_map, elements); 743958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier KeyedStoreGenerateMegamorphicHelper(masm, &fast_object_grow, 744958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier &fast_double_grow, &slow, kDontCheckMap, 745958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier kIncrementLength, value, key, receiver, 746958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier receiver_map, elements_map, elements); 747958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier 748958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier __ bind(&miss); 749958fae7ec3f466955f8e5b50fa5b8d38b9e91675Emily Bernier GenerateMiss(masm); 750b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 751b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 752b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 753b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StoreIC::GenerateMegamorphic(MacroAssembler* masm) { 754b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = StoreDescriptor::ReceiverRegister(); 755b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name = StoreDescriptor::NameRegister(); 756b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(receiver.is(r1)); 757b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name.is(r2)); 758b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(StoreDescriptor::ValueRegister().is(r0)); 759b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 760b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Get the receiver from the stack and probe the stub cache. 761b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::Flags flags = Code::RemoveTypeAndHolderFromFlags( 762b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Code::ComputeHandlerFlags(Code::STORE_IC)); 763b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 764014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch masm->isolate()->stub_cache()->GenerateProbe(masm, Code::STORE_IC, flags, 765014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch receiver, name, r3, r4, r5, r6); 766b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 767b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Cache miss: Jump to runtime. 768b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMiss(masm); 769b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 770b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 771b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 772b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StoreIC::GenerateMiss(MacroAssembler* masm) { 773014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch StoreIC_PushArgs(masm); 774b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 775b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Perform tail call to the entry. 776014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ TailCallRuntime(Runtime::kStoreIC_Miss); 777b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 778b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 779b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 780b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochvoid StoreIC::GenerateNormal(MacroAssembler* masm) { 781b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Label miss; 782b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register receiver = StoreDescriptor::ReceiverRegister(); 783b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register name = StoreDescriptor::NameRegister(); 784b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register value = StoreDescriptor::ValueRegister(); 785014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch Register dictionary = r5; 786b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(receiver.is(r1)); 787b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(name.is(r2)); 788b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(value.is(r0)); 789014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(VectorStoreICDescriptor::VectorRegister().is(r3)); 790014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch DCHECK(VectorStoreICDescriptor::SlotRegister().is(r4)); 791b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 792b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ ldr(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); 793b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 794014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch GenerateDictionaryStore(masm, &miss, dictionary, name, value, r6, r9); 795b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Counters* counters = masm->isolate()->counters(); 796014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ IncrementCounter(counters->store_normal_hit(), 1, r6, r9); 797b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ Ret(); 798b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 799b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch __ bind(&miss); 800014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch __ IncrementCounter(counters->store_normal_miss(), 1, r6, r9); 801b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch GenerateMiss(masm); 802b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 803b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 804b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 805b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#undef __ 806b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 807b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 808b8a8cc1952d61a2f3a2568848933943a543b5d3eBen MurdochCondition CompareIC::ComputeCondition(Token::Value op) { 809b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch switch (op) { 810b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::EQ_STRICT: 811b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::EQ: 812b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return eq; 813b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::LT: 814b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return lt; 815b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::GT: 816b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return gt; 817b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::LTE: 818b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return le; 819b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch case Token::GTE: 820b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return ge; 821b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch default: 822b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch UNREACHABLE(); 823b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return kNoCondition; 824b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 825b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 826b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 827b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 828b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdochbool CompareIC::HasInlinedSmiCode(Address address) { 829b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The address of the instruction following the call. 830b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address cmp_instruction_address = 831b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::return_address_from_call_start(address); 832b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 833b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the instruction following the call is not a cmp rx, #yyy, nothing 834b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // was inlined. 835b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr instr = Assembler::instr_at(cmp_instruction_address); 836b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return Assembler::IsCmpImmediate(instr); 837b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 838b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 839b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 840014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdochvoid PatchInlinedSmiCode(Isolate* isolate, Address address, 841014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch InlinedSmiCheck check) { 842b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address cmp_instruction_address = 843b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::return_address_from_call_start(address); 844b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 845b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the instruction following the call is not a cmp rx, #yyy, nothing 846b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // was inlined. 847b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr instr = Assembler::instr_at(cmp_instruction_address); 848b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (!Assembler::IsCmpImmediate(instr)) { 849b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 850b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 851b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 852b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // The delta to the start of the map check instruction and the 853b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // condition code uses at the patched jump. 854b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch int delta = Assembler::GetCmpImmediateRawImmediate(instr); 855b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch delta += Assembler::GetCmpImmediateRegister(instr).code() * kOff12Mask; 856b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // If the delta is 0 the instruction is cmp r0, #0 which also signals that 857b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // nothing was inlined. 858b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (delta == 0) { 859b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch return; 860b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 861b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 862b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (FLAG_trace_ic) { 863b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch PrintF("[ patching ic at %p, cmp=%p, delta=%d\n", address, 864b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp_instruction_address, delta); 865b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 866b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 867b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Address patch_address = 868b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch cmp_instruction_address - delta * Instruction::kInstrSize; 869b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr instr_at_patch = Assembler::instr_at(patch_address); 870b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Instr branch_instr = 871b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::instr_at(patch_address + Instruction::kInstrSize); 872b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // This is patching a conditional "jump if not smi/jump if smi" site. 873b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // Enabling by changing from 874b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // cmp rx, rx 875b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // b eq/ne, <target> 876b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // to 877b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // tst rx, #kSmiTagMask 878b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // b ne/eq, <target> 879b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch // and vice-versa to be disabled again. 880014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch CodePatcher patcher(isolate, patch_address, 2); 881b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Register reg = Assembler::GetRn(instr_at_patch); 882b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (check == ENABLE_INLINED_SMI_CHECK) { 883b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsCmpRegister(instr_at_patch)); 884b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK_EQ(Assembler::GetRn(instr_at_patch).code(), 885b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch Assembler::GetRm(instr_at_patch).code()); 886b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->tst(reg, Operand(kSmiTagMask)); 887b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 888b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(check == DISABLE_INLINED_SMI_CHECK); 889b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsTstImmediate(instr_at_patch)); 890b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.masm()->cmp(reg, reg); 891b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 892b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::IsBranch(branch_instr)); 893b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch if (Assembler::GetCondition(branch_instr) == eq) { 894b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.EmitCondition(ne); 895b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } else { 896b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch DCHECK(Assembler::GetCondition(branch_instr) == ne); 897b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch patcher.EmitCondition(eq); 898b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch } 899b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch} 900014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace internal 901014dc512cdd3e367bee49a713fdc5ed92584a3e5Ben Murdoch} // namespace v8 902b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch 903b8a8cc1952d61a2f3a2568848933943a543b5d3eBen Murdoch#endif // V8_TARGET_ARCH_ARM 904