| OLD | NEW |
| 1 // Copyright 2012 the V8 project authors. All rights reserved. | 1 // Copyright 2012 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM | 7 #if V8_TARGET_ARCH_ARM |
| 8 | 8 |
| 9 #include "src/arm/assembler-arm.h" | 9 #include "src/arm/assembler-arm.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 // type: holds the receiver instance type on entry. | 32 // type: holds the receiver instance type on entry. |
| 33 __ cmp(type, Operand(JS_GLOBAL_OBJECT_TYPE)); | 33 __ cmp(type, Operand(JS_GLOBAL_OBJECT_TYPE)); |
| 34 __ b(eq, global_object); | 34 __ b(eq, global_object); |
| 35 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); | 35 __ cmp(type, Operand(JS_BUILTINS_OBJECT_TYPE)); |
| 36 __ b(eq, global_object); | 36 __ b(eq, global_object); |
| 37 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); | 37 __ cmp(type, Operand(JS_GLOBAL_PROXY_TYPE)); |
| 38 __ b(eq, global_object); | 38 __ b(eq, global_object); |
| 39 } | 39 } |
| 40 | 40 |
| 41 | 41 |
| 42 // Generated code falls through if the receiver is a regular non-global | |
| 43 // JS object with slow properties and no interceptors. | |
| 44 static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, | |
| 45 Register receiver, | |
| 46 Register elements, | |
| 47 Register t0, | |
| 48 Register t1, | |
| 49 Label* miss) { | |
| 50 // Register usage: | |
| 51 // receiver: holds the receiver on entry and is unchanged. | |
| 52 // elements: holds the property dictionary on fall through. | |
| 53 // Scratch registers: | |
| 54 // t0: used to holds the receiver map. | |
| 55 // t1: used to holds the receiver instance type, receiver bit mask and | |
| 56 // elements map. | |
| 57 | |
| 58 // Check that the receiver isn't a smi. | |
| 59 __ JumpIfSmi(receiver, miss); | |
| 60 | |
| 61 // Check that the receiver is a valid JS object. | |
| 62 __ CompareObjectType(receiver, t0, t1, FIRST_SPEC_OBJECT_TYPE); | |
| 63 __ b(lt, miss); | |
| 64 | |
| 65 // If this assert fails, we have to check upper bound too. | |
| 66 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); | |
| 67 | |
| 68 GenerateGlobalInstanceTypeCheck(masm, t1, miss); | |
| 69 | |
| 70 // Check that the global object does not require access checks. | |
| 71 __ ldrb(t1, FieldMemOperand(t0, Map::kBitFieldOffset)); | |
| 72 __ tst(t1, Operand((1 << Map::kIsAccessCheckNeeded) | | |
| 73 (1 << Map::kHasNamedInterceptor))); | |
| 74 __ b(ne, miss); | |
| 75 | |
| 76 __ ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
| 77 __ ldr(t1, FieldMemOperand(elements, HeapObject::kMapOffset)); | |
| 78 __ LoadRoot(ip, Heap::kHashTableMapRootIndex); | |
| 79 __ cmp(t1, ip); | |
| 80 __ b(ne, miss); | |
| 81 } | |
| 82 | |
| 83 | |
| 84 // Helper function used from LoadIC GenerateNormal. | 42 // Helper function used from LoadIC GenerateNormal. |
| 85 // | 43 // |
| 86 // elements: Property dictionary. It is not clobbered if a jump to the miss | 44 // elements: Property dictionary. It is not clobbered if a jump to the miss |
| 87 // label is done. | 45 // label is done. |
| 88 // name: Property name. It is not clobbered if a jump to the miss label is | 46 // name: Property name. It is not clobbered if a jump to the miss label is |
| 89 // done | 47 // done |
| 90 // result: Register for the result. It is only updated if a jump to the miss | 48 // result: Register for the result. It is only updated if a jump to the miss |
| 91 // label is not done. Can be the same as elements or name clobbering | 49 // label is not done. Can be the same as elements or name clobbering |
| 92 // one of these in the case of not jumping to the miss label. | 50 // one of these in the case of not jumping to the miss label. |
| 93 // The two scratch registers need to be different from elements, name and | 51 // The two scratch registers need to be different from elements, name and |
| (...skipping 227 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 321 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 279 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
| 322 masm->isolate()->stub_cache()->GenerateProbe( | 280 masm->isolate()->stub_cache()->GenerateProbe( |
| 323 masm, flags, receiver, name, r3, r4, r5, r6); | 281 masm, flags, receiver, name, r3, r4, r5, r6); |
| 324 | 282 |
| 325 // Cache miss: Jump to runtime. | 283 // Cache miss: Jump to runtime. |
| 326 GenerateMiss(masm); | 284 GenerateMiss(masm); |
| 327 } | 285 } |
| 328 | 286 |
| 329 | 287 |
| 330 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 288 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 331 // ----------- S t a t e ------------- | 289 Register dictionary = r0; |
| 332 // -- r2 : name | 290 ASSERT(!dictionary.is(ReceiverRegister())); |
| 333 // -- lr : return address | 291 ASSERT(!dictionary.is(NameRegister())); |
| 334 // -- r1 : receiver | |
| 335 // ----------------------------------- | |
| 336 ASSERT(r1.is(ReceiverRegister())); | |
| 337 ASSERT(r2.is(NameRegister())); | |
| 338 | 292 |
| 339 Label miss, slow; | 293 Label slow; |
| 340 | 294 |
| 341 GenerateNameDictionaryReceiverCheck(masm, r1, r0, r3, r4, &miss); | 295 __ ldr(dictionary, |
| 342 | 296 FieldMemOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); |
| 343 // r0: elements | 297 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), r0, r3, r4); |
| 344 GenerateDictionaryLoad(masm, &slow, r0, r2, r0, r3, r4); | |
| 345 __ Ret(); | 298 __ Ret(); |
| 346 | 299 |
| 347 // Dictionary load failed, go slow (but don't miss). | 300 // Dictionary load failed, go slow (but don't miss). |
| 348 __ bind(&slow); | 301 __ bind(&slow); |
| 349 GenerateRuntimeGetProperty(masm); | 302 GenerateRuntimeGetProperty(masm); |
| 350 | |
| 351 // Cache miss: Jump to runtime. | |
| 352 __ bind(&miss); | |
| 353 GenerateMiss(masm); | |
| 354 } | 303 } |
| 355 | 304 |
| 356 | 305 |
| 357 // A register that isn't one of the parameters to the load ic. | 306 // A register that isn't one of the parameters to the load ic. |
| 358 static const Register LoadIC_TempRegister() { return r3; } | 307 static const Register LoadIC_TempRegister() { return r3; } |
| 359 | 308 |
| 360 | 309 |
| 361 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 310 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 362 // The return address is in lr. | 311 // The return address is in lr. |
| 363 Isolate* isolate = masm->isolate(); | 312 Isolate* isolate = masm->isolate(); |
| (...skipping 777 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1141 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); | 1090 ExternalReference(IC_Utility(kStoreIC_Miss), masm->isolate()); |
| 1142 __ TailCallExternalReference(ref, 3, 1); | 1091 __ TailCallExternalReference(ref, 3, 1); |
| 1143 } | 1092 } |
| 1144 | 1093 |
| 1145 | 1094 |
| 1146 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1095 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 1147 Label miss; | 1096 Label miss; |
| 1148 Register receiver = ReceiverRegister(); | 1097 Register receiver = ReceiverRegister(); |
| 1149 Register name = NameRegister(); | 1098 Register name = NameRegister(); |
| 1150 Register value = ValueRegister(); | 1099 Register value = ValueRegister(); |
| 1100 Register dictionary = r3; |
| 1151 ASSERT(receiver.is(r1)); | 1101 ASSERT(receiver.is(r1)); |
| 1152 ASSERT(name.is(r2)); | 1102 ASSERT(name.is(r2)); |
| 1153 ASSERT(value.is(r0)); | 1103 ASSERT(value.is(r0)); |
| 1154 | 1104 |
| 1155 GenerateNameDictionaryReceiverCheck(masm, receiver, r3, r4, r5, &miss); | 1105 __ ldr(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 1156 | 1106 |
| 1157 GenerateDictionaryStore(masm, &miss, r3, name, value, r4, r5); | 1107 GenerateDictionaryStore(masm, &miss, dictionary, name, value, r4, r5); |
| 1158 Counters* counters = masm->isolate()->counters(); | 1108 Counters* counters = masm->isolate()->counters(); |
| 1159 __ IncrementCounter(counters->store_normal_hit(), | 1109 __ IncrementCounter(counters->store_normal_hit(), |
| 1160 1, r4, r5); | 1110 1, r4, r5); |
| 1161 __ Ret(); | 1111 __ Ret(); |
| 1162 | 1112 |
| 1163 __ bind(&miss); | 1113 __ bind(&miss); |
| 1164 __ IncrementCounter(counters->store_normal_miss(), 1, r4, r5); | 1114 __ IncrementCounter(counters->store_normal_miss(), 1, r4, r5); |
| 1165 GenerateMiss(masm); | 1115 GenerateMiss(masm); |
| 1166 } | 1116 } |
| 1167 | 1117 |
| (...skipping 103 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1271 } else { | 1221 } else { |
| 1272 ASSERT(Assembler::GetCondition(branch_instr) == ne); | 1222 ASSERT(Assembler::GetCondition(branch_instr) == ne); |
| 1273 patcher.EmitCondition(eq); | 1223 patcher.EmitCondition(eq); |
| 1274 } | 1224 } |
| 1275 } | 1225 } |
| 1276 | 1226 |
| 1277 | 1227 |
| 1278 } } // namespace v8::internal | 1228 } } // namespace v8::internal |
| 1279 | 1229 |
| 1280 #endif // V8_TARGET_ARCH_ARM | 1230 #endif // V8_TARGET_ARCH_ARM |
| OLD | NEW |