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 |