| 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 #include "src/v8.h" | 5 #include "src/v8.h" |
| 6 | 6 |
| 7 #if V8_TARGET_ARCH_ARM64 | 7 #if V8_TARGET_ARCH_ARM64 |
| 8 | 8 |
| 9 #include "src/arm64/assembler-arm64.h" | 9 #include "src/arm64/assembler-arm64.h" |
| 10 #include "src/code-stubs.h" | 10 #include "src/code-stubs.h" |
| (...skipping 16 matching lines...) Expand all Loading... |
| 27 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, | 27 static void GenerateGlobalInstanceTypeCheck(MacroAssembler* masm, |
| 28 Register type, | 28 Register type, |
| 29 Label* global_object) { | 29 Label* global_object) { |
| 30 __ Cmp(type, JS_GLOBAL_OBJECT_TYPE); | 30 __ Cmp(type, JS_GLOBAL_OBJECT_TYPE); |
| 31 __ Ccmp(type, JS_BUILTINS_OBJECT_TYPE, ZFlag, ne); | 31 __ Ccmp(type, JS_BUILTINS_OBJECT_TYPE, ZFlag, ne); |
| 32 __ Ccmp(type, JS_GLOBAL_PROXY_TYPE, ZFlag, ne); | 32 __ Ccmp(type, JS_GLOBAL_PROXY_TYPE, ZFlag, ne); |
| 33 __ B(eq, global_object); | 33 __ B(eq, global_object); |
| 34 } | 34 } |
| 35 | 35 |
| 36 | 36 |
| 37 // Generated code falls through if the receiver is a regular non-global | |
| 38 // JS object with slow properties and no interceptors. | |
| 39 // | |
| 40 // "receiver" holds the receiver on entry and is unchanged. | |
| 41 // "elements" holds the property dictionary on fall through. | |
| 42 static void GenerateNameDictionaryReceiverCheck(MacroAssembler* masm, | |
| 43 Register receiver, | |
| 44 Register elements, | |
| 45 Register scratch0, | |
| 46 Register scratch1, | |
| 47 Label* miss) { | |
| 48 ASSERT(!AreAliased(receiver, elements, scratch0, scratch1)); | |
| 49 | |
| 50 // Check that the receiver isn't a smi. | |
| 51 __ JumpIfSmi(receiver, miss); | |
| 52 | |
| 53 // Check that the receiver is a valid JS object. | |
| 54 // Let t be the object instance type, we want: | |
| 55 // FIRST_SPEC_OBJECT_TYPE <= t <= LAST_SPEC_OBJECT_TYPE. | |
| 56 // Since LAST_SPEC_OBJECT_TYPE is the last possible instance type we only | |
| 57 // check the lower bound. | |
| 58 STATIC_ASSERT(LAST_TYPE == LAST_SPEC_OBJECT_TYPE); | |
| 59 | |
| 60 __ JumpIfObjectType(receiver, scratch0, scratch1, FIRST_SPEC_OBJECT_TYPE, | |
| 61 miss, lt); | |
| 62 | |
| 63 // scratch0 now contains the map of the receiver and scratch1 the object type. | |
| 64 Register map = scratch0; | |
| 65 Register type = scratch1; | |
| 66 | |
| 67 // Check if the receiver is a global JS object. | |
| 68 GenerateGlobalInstanceTypeCheck(masm, type, miss); | |
| 69 | |
| 70 // Check that the object does not require access checks. | |
| 71 __ Ldrb(scratch1, FieldMemOperand(map, Map::kBitFieldOffset)); | |
| 72 __ Tbnz(scratch1, Map::kIsAccessCheckNeeded, miss); | |
| 73 __ Tbnz(scratch1, Map::kHasNamedInterceptor, miss); | |
| 74 | |
| 75 // Check that the properties dictionary is valid. | |
| 76 __ Ldr(elements, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); | |
| 77 __ Ldr(scratch1, FieldMemOperand(elements, HeapObject::kMapOffset)); | |
| 78 __ JumpIfNotRoot(scratch1, Heap::kHashTableMapRootIndex, miss); | |
| 79 } | |
| 80 | |
| 81 | |
| 82 // Helper function used from LoadIC GenerateNormal. | 37 // Helper function used from LoadIC GenerateNormal. |
| 83 // | 38 // |
| 84 // elements: Property dictionary. It is not clobbered if a jump to the miss | 39 // elements: Property dictionary. It is not clobbered if a jump to the miss |
| 85 // label is done. | 40 // label is done. |
| 86 // name: Property name. It is not clobbered if a jump to the miss label is | 41 // name: Property name. It is not clobbered if a jump to the miss label is |
| 87 // done | 42 // done |
| 88 // result: Register for the result. It is only updated if a jump to the miss | 43 // result: Register for the result. It is only updated if a jump to the miss |
| 89 // label is not done. | 44 // label is not done. |
| 90 // The scratch registers need to be different from elements, name and result. | 45 // The scratch registers need to be different from elements, name and result. |
| 91 // The generated code assumes that the receiver has slow properties, | 46 // The generated code assumes that the receiver has slow properties, |
| (...skipping 325 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 417 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); | 372 Code::Flags flags = Code::ComputeHandlerFlags(Code::LOAD_IC); |
| 418 masm->isolate()->stub_cache()->GenerateProbe( | 373 masm->isolate()->stub_cache()->GenerateProbe( |
| 419 masm, flags, receiver, name, x3, x4, x5, x6); | 374 masm, flags, receiver, name, x3, x4, x5, x6); |
| 420 | 375 |
| 421 // Cache miss: Jump to runtime. | 376 // Cache miss: Jump to runtime. |
| 422 GenerateMiss(masm); | 377 GenerateMiss(masm); |
| 423 } | 378 } |
| 424 | 379 |
| 425 | 380 |
| 426 void LoadIC::GenerateNormal(MacroAssembler* masm) { | 381 void LoadIC::GenerateNormal(MacroAssembler* masm) { |
| 427 // ----------- S t a t e ------------- | 382 Register dictionary = x0; |
| 428 // -- x2 : name | 383 ASSERT(!dictionary.is(ReceiverRegister())); |
| 429 // -- lr : return address | 384 ASSERT(!dictionary.is(NameRegister())); |
| 430 // -- x1 : receiver | 385 Label slow; |
| 431 // ----------------------------------- | |
| 432 ASSERT(x1.is(ReceiverRegister())); | |
| 433 ASSERT(x2.is(NameRegister())); | |
| 434 Label miss, slow; | |
| 435 | 386 |
| 436 GenerateNameDictionaryReceiverCheck(masm, x1, x0, x3, x4, &miss); | 387 __ Ldr(dictionary, |
| 437 | 388 FieldMemOperand(ReceiverRegister(), JSObject::kPropertiesOffset)); |
| 438 // x0 now holds the property dictionary. | 389 GenerateDictionaryLoad(masm, &slow, dictionary, NameRegister(), x0, x3, x4); |
| 439 GenerateDictionaryLoad(masm, &slow, x0, x2, x0, x3, x4); | |
| 440 __ Ret(); | 390 __ Ret(); |
| 441 | 391 |
| 442 // Dictionary load failed, go slow (but don't miss). | 392 // Dictionary load failed, go slow (but don't miss). |
| 443 __ Bind(&slow); | 393 __ Bind(&slow); |
| 444 GenerateRuntimeGetProperty(masm); | 394 GenerateRuntimeGetProperty(masm); |
| 445 | |
| 446 // Cache miss: Jump to runtime. | |
| 447 __ Bind(&miss); | |
| 448 GenerateMiss(masm); | |
| 449 } | 395 } |
| 450 | 396 |
| 451 | 397 |
| 452 void LoadIC::GenerateMiss(MacroAssembler* masm) { | 398 void LoadIC::GenerateMiss(MacroAssembler* masm) { |
| 453 // The return address is in lr. | 399 // The return address is in lr. |
| 454 Isolate* isolate = masm->isolate(); | 400 Isolate* isolate = masm->isolate(); |
| 455 ASM_LOCATION("LoadIC::GenerateMiss"); | 401 ASM_LOCATION("LoadIC::GenerateMiss"); |
| 456 | 402 |
| 457 __ IncrementCounter(isolate->counters()->load_miss(), 1, x3, x4); | 403 __ IncrementCounter(isolate->counters()->load_miss(), 1, x3, x4); |
| 458 | 404 |
| (...skipping 721 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1180 | 1126 |
| 1181 | 1127 |
| 1182 void StoreIC::GenerateNormal(MacroAssembler* masm) { | 1128 void StoreIC::GenerateNormal(MacroAssembler* masm) { |
| 1183 Label miss; | 1129 Label miss; |
| 1184 Register value = ValueRegister(); | 1130 Register value = ValueRegister(); |
| 1185 Register receiver = ReceiverRegister(); | 1131 Register receiver = ReceiverRegister(); |
| 1186 Register name = NameRegister(); | 1132 Register name = NameRegister(); |
| 1187 Register dictionary = x3; | 1133 Register dictionary = x3; |
| 1188 ASSERT(!AreAliased(value, receiver, name, x3, x4, x5)); | 1134 ASSERT(!AreAliased(value, receiver, name, x3, x4, x5)); |
| 1189 | 1135 |
| 1190 GenerateNameDictionaryReceiverCheck( | 1136 __ Ldr(dictionary, FieldMemOperand(receiver, JSObject::kPropertiesOffset)); |
| 1191 masm, receiver, dictionary, x4, x5, &miss); | |
| 1192 | 1137 |
| 1193 GenerateDictionaryStore(masm, &miss, dictionary, name, value, x4, x5); | 1138 GenerateDictionaryStore(masm, &miss, dictionary, name, value, x4, x5); |
| 1194 Counters* counters = masm->isolate()->counters(); | 1139 Counters* counters = masm->isolate()->counters(); |
| 1195 __ IncrementCounter(counters->store_normal_hit(), 1, x4, x5); | 1140 __ IncrementCounter(counters->store_normal_hit(), 1, x4, x5); |
| 1196 __ Ret(); | 1141 __ Ret(); |
| 1197 | 1142 |
| 1198 // Cache miss: Jump to runtime. | 1143 // Cache miss: Jump to runtime. |
| 1199 __ Bind(&miss); | 1144 __ Bind(&miss); |
| 1200 __ IncrementCounter(counters->store_normal_miss(), 1, x4, x5); | 1145 __ IncrementCounter(counters->store_normal_miss(), 1, x4, x5); |
| 1201 GenerateMiss(masm); | 1146 GenerateMiss(masm); |
| (...skipping 118 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1320 ASSERT(to_patch->Mask(TestBranchMask) == TBNZ); | 1265 ASSERT(to_patch->Mask(TestBranchMask) == TBNZ); |
| 1321 // This is JumpIfSmi(smi_reg, branch_imm). | 1266 // This is JumpIfSmi(smi_reg, branch_imm). |
| 1322 patcher.tbz(smi_reg, 0, branch_imm); | 1267 patcher.tbz(smi_reg, 0, branch_imm); |
| 1323 } | 1268 } |
| 1324 } | 1269 } |
| 1325 | 1270 |
| 1326 | 1271 |
| 1327 } } // namespace v8::internal | 1272 } } // namespace v8::internal |
| 1328 | 1273 |
| 1329 #endif // V8_TARGET_ARCH_ARM64 | 1274 #endif // V8_TARGET_ARCH_ARM64 |
| OLD | NEW |