| OLD | NEW |
| 1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #if V8_TARGET_ARCH_ARM64 | 5 #if V8_TARGET_ARCH_ARM64 |
| 6 | 6 |
| 7 #include "src/codegen.h" | 7 #include "src/codegen.h" |
| 8 #include "src/ic/ic.h" | 8 #include "src/ic/ic.h" |
| 9 #include "src/ic/ic-compiler.h" | 9 #include "src/ic/ic-compiler.h" |
| 10 #include "src/ic/stub-cache.h" | 10 #include "src/ic/stub-cache.h" |
| 11 | 11 |
| 12 namespace v8 { | 12 namespace v8 { |
| 13 namespace internal { | 13 namespace internal { |
| 14 | 14 |
| 15 | 15 |
| 16 #define __ ACCESS_MASM(masm) | 16 #define __ ACCESS_MASM(masm) |
| 17 | 17 |
| 18 // Helper function used from LoadIC GenerateNormal. | |
| 19 // | |
| 20 // elements: Property dictionary. It is not clobbered if a jump to the miss | |
| 21 // label is done. | |
| 22 // name: Property name. It is not clobbered if a jump to the miss label is | |
| 23 // done | |
| 24 // result: Register for the result. It is only updated if a jump to the miss | |
| 25 // label is not done. | |
| 26 // The scratch registers need to be different from elements, name and result. | |
| 27 // The generated code assumes that the receiver has slow properties, | |
| 28 // is not a global object and does not have interceptors. | |
| 29 static void GenerateDictionaryLoad(MacroAssembler* masm, Label* miss, | |
| 30 Register elements, Register name, | |
| 31 Register result, Register scratch1, | |
| 32 Register scratch2) { | |
| 33 DCHECK(!AreAliased(elements, name, scratch1, scratch2)); | |
| 34 DCHECK(!AreAliased(result, scratch1, scratch2)); | |
| 35 | |
| 36 Label done; | |
| 37 | |
| 38 // Probe the dictionary. | |
| 39 NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss, &done, elements, | |
| 40 name, scratch1, scratch2); | |
| 41 | |
| 42 // If probing finds an entry check that the value is a normal property. | |
| 43 __ Bind(&done); | |
| 44 | |
| 45 static const int kElementsStartOffset = | |
| 46 NameDictionary::kHeaderSize + | |
| 47 NameDictionary::kElementsStartIndex * kPointerSize; | |
| 48 static const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | |
| 49 __ Ldr(scratch1, FieldMemOperand(scratch2, kDetailsOffset)); | |
| 50 __ Tst(scratch1, Smi::FromInt(PropertyDetails::TypeField::kMask)); | |
| 51 __ B(ne, miss); | |
| 52 | |
| 53 // Get the value at the masked, scaled index and return. | |
| 54 __ Ldr(result, | |
| 55 FieldMemOperand(scratch2, kElementsStartOffset + 1 * kPointerSize)); | |
| 56 } | |
| 57 | |
| 58 | |
| 59 // Helper function used from StoreIC::GenerateNormal. | |
| 60 // | |
| 61 // elements: Property dictionary. It is not clobbered if a jump to the miss | |
| 62 // label is done. | |
| 63 // name: Property name. It is not clobbered if a jump to the miss label is | |
| 64 // done | |
| 65 // value: The value to store (never clobbered). | |
| 66 // | |
| 67 // The generated code assumes that the receiver has slow properties, | |
| 68 // is not a global object and does not have interceptors. | |
| 69 static void GenerateDictionaryStore(MacroAssembler* masm, Label* miss, | |
| 70 Register elements, Register name, | |
| 71 Register value, Register scratch1, | |
| 72 Register scratch2) { | |
| 73 DCHECK(!AreAliased(elements, name, value, scratch1, scratch2)); | |
| 74 | |
| 75 Label done; | |
| 76 | |
| 77 // Probe the dictionary. | |
| 78 NameDictionaryLookupStub::GeneratePositiveLookup(masm, miss, &done, elements, | |
| 79 name, scratch1, scratch2); | |
| 80 | |
| 81 // If probing finds an entry in the dictionary check that the value | |
| 82 // is a normal property that is not read only. | |
| 83 __ Bind(&done); | |
| 84 | |
| 85 static const int kElementsStartOffset = | |
| 86 NameDictionary::kHeaderSize + | |
| 87 NameDictionary::kElementsStartIndex * kPointerSize; | |
| 88 static const int kDetailsOffset = kElementsStartOffset + 2 * kPointerSize; | |
| 89 static const int kTypeAndReadOnlyMask = | |
| 90 PropertyDetails::TypeField::kMask | | |
| 91 PropertyDetails::AttributesField::encode(READ_ONLY); | |
| 92 __ Ldrsw(scratch1, UntagSmiFieldMemOperand(scratch2, kDetailsOffset)); | |
| 93 __ Tst(scratch1, kTypeAndReadOnlyMask); | |
| 94 __ B(ne, miss); | |
| 95 | |
| 96 // Store the value at the masked, scaled index and return. | |
| 97 static const int kValueOffset = kElementsStartOffset + kPointerSize; | |
| 98 __ Add(scratch2, scratch2, kValueOffset - kHeapObjectTag); | |
| 99 __ Str(value, MemOperand(scratch2)); | |
| 100 | |
| 101 // Update the write barrier. Make sure not to clobber the value. | |
| 102 __ Mov(scratch1, value); | |
| 103 __ RecordWrite(elements, scratch2, scratch1, kLRHasNotBeenSaved, | |
| 104 kDontSaveFPRegs); | |
| 105 } | |
| 106 | |
| 107 void LoadIC::GenerateNormal(MacroAssembler* masm) { | |
| 108 Register dictionary = x0; | |
| 109 DCHECK(!dictionary.is(LoadDescriptor::ReceiverRegister())); | |
| 110 DCHECK(!dictionary.is(LoadDescriptor::NameRegister())); | |
| 111 Label slow; | |
| 112 | |
| 113 __ Ldr(dictionary, FieldMemOperand(LoadDescriptor::ReceiverRegister(), | |
| 114 JSObject::kPropertiesOffset)); | |
| 115 GenerateDictionaryLoad(masm, &slow, dictionary, | |
| 116 LoadDescriptor::NameRegister(), x0, x3, x4); | |
| 117 __ Ret(); | |
| 118 | |
| 119 // Dictionary load failed, go slow (but don't miss). | |
| 120 __ Bind(&slow); | |
| 121 GenerateRuntimeGetProperty(masm); | |
| 122 } | |
| 123 | |
| 124 void LoadIC::GenerateRuntimeGetProperty(MacroAssembler* masm) { | |
| 125 // The return address is in lr. | |
| 126 __ Push(LoadDescriptor::ReceiverRegister(), LoadDescriptor::NameRegister()); | |
| 127 | |
| 128 // Do tail-call to runtime routine. | |
| 129 __ TailCallRuntime(Runtime::kGetProperty); | |
| 130 } | |
| 131 | |
| 132 static void StoreIC_PushArgs(MacroAssembler* masm) { | 18 static void StoreIC_PushArgs(MacroAssembler* masm) { |
| 133 __ Push(StoreWithVectorDescriptor::ValueRegister(), | 19 __ Push(StoreWithVectorDescriptor::ValueRegister(), |
| 134 StoreWithVectorDescriptor::SlotRegister(), | 20 StoreWithVectorDescriptor::SlotRegister(), |
| 135 StoreWithVectorDescriptor::VectorRegister(), | 21 StoreWithVectorDescriptor::VectorRegister(), |
| 136 StoreWithVectorDescriptor::ReceiverRegister(), | 22 StoreWithVectorDescriptor::ReceiverRegister(), |
| 137 StoreWithVectorDescriptor::NameRegister()); | 23 StoreWithVectorDescriptor::NameRegister()); |
| 138 } | 24 } |
| 139 | 25 |
| 140 | 26 |
| 141 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { | 27 void KeyedStoreIC::GenerateMiss(MacroAssembler* masm) { |
| 142 ASM_LOCATION("KeyedStoreIC::GenerateMiss"); | 28 ASM_LOCATION("KeyedStoreIC::GenerateMiss"); |
| 143 StoreIC_PushArgs(masm); | 29 StoreIC_PushArgs(masm); |
| 144 __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); | 30 __ TailCallRuntime(Runtime::kKeyedStoreIC_Miss); |
| 145 } | 31 } |
| 146 | 32 |
| 147 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { | 33 void KeyedStoreIC::GenerateSlow(MacroAssembler* masm) { |
| 148 ASM_LOCATION("KeyedStoreIC::GenerateSlow"); | 34 ASM_LOCATION("KeyedStoreIC::GenerateSlow"); |
| 149 StoreIC_PushArgs(masm); | 35 StoreIC_PushArgs(masm); |
| 150 | 36 |
| 151 // The slow case calls into the runtime to complete the store without causing | 37 // The slow case calls into the runtime to complete the store without causing |
| 152 // an IC miss that would otherwise cause a transition to the generic stub. | 38 // an IC miss that would otherwise cause a transition to the generic stub. |
| 153 __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); | 39 __ TailCallRuntime(Runtime::kKeyedStoreIC_Slow); |
| 154 } | 40 } |
| 155 | 41 |
| 156 void StoreIC::GenerateMiss(MacroAssembler* masm) { | |
| 157 StoreIC_PushArgs(masm); | |
| 158 | |
| 159 // Tail call to the entry. | |
| 160 __ TailCallRuntime(Runtime::kStoreIC_Miss); | |
| 161 } | |
| 162 | |
| 163 | |
| 164 void StoreIC::GenerateNormal(MacroAssembler* masm) { | |
| 165 Label miss; | |
| 166 Register value = StoreDescriptor::ValueRegister(); | |
| 167 Register receiver = StoreDescriptor::ReceiverRegister(); | |
| 168 Register name = StoreDescriptor::NameRegister(); | |
| 169 Register dictionary = x5; | |
| 170 DCHECK(!AreAliased(value, receiver, name, | |
| 171 StoreWithVectorDescriptor::SlotRegister(), | |
| 172 StoreWithVectorDescriptor::VectorRegister(), x5, x6, x7)); | |
| 173 | |
| 174 __ Ldr(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
| 175 | |
| 176 GenerateDictionaryStore(masm, &miss, dictionary, name, value, x6, x7); | |
| 177 Counters* counters = masm->isolate()->counters(); | |
| 178 __ IncrementCounter(counters->ic_store_normal_hit(), 1, x6, x7); | |
| 179 __ Ret(); | |
| 180 | |
| 181 // Cache miss: Jump to runtime. | |
| 182 __ Bind(&miss); | |
| 183 __ IncrementCounter(counters->ic_store_normal_miss(), 1, x6, x7); | |
| 184 GenerateMiss(masm); | |
| 185 } | |
| 186 | |
| 187 | |
| 188 Condition CompareIC::ComputeCondition(Token::Value op) { | 42 Condition CompareIC::ComputeCondition(Token::Value op) { |
| 189 switch (op) { | 43 switch (op) { |
| 190 case Token::EQ_STRICT: | 44 case Token::EQ_STRICT: |
| 191 case Token::EQ: | 45 case Token::EQ: |
| 192 return eq; | 46 return eq; |
| 193 case Token::LT: | 47 case Token::LT: |
| 194 return lt; | 48 return lt; |
| 195 case Token::GT: | 49 case Token::GT: |
| 196 return gt; | 50 return gt; |
| 197 case Token::LTE: | 51 case Token::LTE: |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 269 } else { | 123 } else { |
| 270 DCHECK(to_patch->Mask(TestBranchMask) == TBNZ); | 124 DCHECK(to_patch->Mask(TestBranchMask) == TBNZ); |
| 271 // This is JumpIfSmi(smi_reg, branch_imm). | 125 // This is JumpIfSmi(smi_reg, branch_imm). |
| 272 patcher.tbz(smi_reg, 0, branch_imm); | 126 patcher.tbz(smi_reg, 0, branch_imm); |
| 273 } | 127 } |
| 274 } | 128 } |
| 275 } // namespace internal | 129 } // namespace internal |
| 276 } // namespace v8 | 130 } // namespace v8 |
| 277 | 131 |
| 278 #endif // V8_TARGET_ARCH_ARM64 | 132 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |