OLD | NEW |
1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file |
2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #include "vm/globals.h" | 5 #include "vm/globals.h" |
6 #if defined(TARGET_ARCH_ARM64) | 6 #if defined(TARGET_ARCH_ARM64) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 69 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
80 | 80 |
81 // There are no runtime calls to closures, so we do not need to set the tag | 81 // There are no runtime calls to closures, so we do not need to set the tag |
82 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. | 82 // bits kClosureFunctionBit and kInstanceFunctionBit in argc_tag_. |
83 ASSERT(argc_tag_offset == 1 * kWordSize); | 83 ASSERT(argc_tag_offset == 1 * kWordSize); |
84 __ mov(R1, R4); // Set argc in NativeArguments. | 84 __ mov(R1, R4); // Set argc in NativeArguments. |
85 | 85 |
86 ASSERT(argv_offset == 2 * kWordSize); | 86 ASSERT(argv_offset == 2 * kWordSize); |
87 __ add(R2, ZR, Operand(R4, LSL, 3)); | 87 __ add(R2, ZR, Operand(R4, LSL, 3)); |
88 __ add(R2, FP, Operand(R2)); // Compute argv. | 88 __ add(R2, FP, Operand(R2)); // Compute argv. |
89 // Set argv in NativeArguments. | 89 // Set argv in NativeArguments. |
90 __ AddImmediate(R2, R2, kParamEndSlotFromFp * kWordSize); | 90 __ AddImmediate(R2, kParamEndSlotFromFp * kWordSize); |
91 | 91 |
92 ASSERT(retval_offset == 3 * kWordSize); | 92 ASSERT(retval_offset == 3 * kWordSize); |
93 __ AddImmediate(R3, R2, kWordSize); | 93 __ AddImmediate(R3, R2, kWordSize); |
94 | 94 |
95 __ StoreToOffset(R0, SP, thread_offset); | 95 __ StoreToOffset(R0, SP, thread_offset); |
96 __ StoreToOffset(R1, SP, argc_tag_offset); | 96 __ StoreToOffset(R1, SP, argc_tag_offset); |
97 __ StoreToOffset(R2, SP, argv_offset); | 97 __ StoreToOffset(R2, SP, argv_offset); |
98 __ StoreToOffset(R3, SP, retval_offset); | 98 __ StoreToOffset(R3, SP, retval_offset); |
99 __ mov(R0, SP); // Pass the pointer to the NativeArguments. | 99 __ mov(R0, SP); // Pass the pointer to the NativeArguments. |
100 | 100 |
(...skipping 309 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
410 static void PushArgumentsArray(Assembler* assembler) { | 410 static void PushArgumentsArray(Assembler* assembler) { |
411 // Allocate array to store arguments of caller. | 411 // Allocate array to store arguments of caller. |
412 __ LoadObject(R1, Object::null_object()); | 412 __ LoadObject(R1, Object::null_object()); |
413 // R1: null element type for raw Array. | 413 // R1: null element type for raw Array. |
414 // R2: smi-tagged argument count, may be zero. | 414 // R2: smi-tagged argument count, may be zero. |
415 __ BranchLink(*StubCode::AllocateArray_entry()); | 415 __ BranchLink(*StubCode::AllocateArray_entry()); |
416 // R0: newly allocated array. | 416 // R0: newly allocated array. |
417 // R2: smi-tagged argument count, may be zero (was preserved by the stub). | 417 // R2: smi-tagged argument count, may be zero (was preserved by the stub). |
418 __ Push(R0); // Array is in R0 and on top of stack. | 418 __ Push(R0); // Array is in R0 and on top of stack. |
419 __ add(R1, FP, Operand(R2, LSL, 2)); | 419 __ add(R1, FP, Operand(R2, LSL, 2)); |
420 __ AddImmediate(R1, R1, kParamEndSlotFromFp * kWordSize); | 420 __ AddImmediate(R1, kParamEndSlotFromFp * kWordSize); |
421 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag); | 421 __ AddImmediate(R3, R0, Array::data_offset() - kHeapObjectTag); |
422 // R1: address of first argument on stack. | 422 // R1: address of first argument on stack. |
423 // R3: address of first argument in array. | 423 // R3: address of first argument in array. |
424 | 424 |
425 Label loop, loop_exit; | 425 Label loop, loop_exit; |
426 __ CompareRegisters(R2, ZR); | 426 __ CompareRegisters(R2, ZR); |
427 __ b(&loop_exit, LE); | 427 __ b(&loop_exit, LE); |
428 __ Bind(&loop); | 428 __ Bind(&loop); |
429 __ ldr(R7, Address(R1)); | 429 __ ldr(R7, Address(R1)); |
430 __ AddImmediate(R1, R1, -kWordSize); | 430 __ AddImmediate(R1, -kWordSize); |
431 __ AddImmediate(R3, R3, kWordSize); | 431 __ AddImmediate(R3, kWordSize); |
432 __ AddImmediateSetFlags(R2, R2, -Smi::RawValue(1)); | 432 __ AddImmediateSetFlags(R2, R2, -Smi::RawValue(1)); |
433 __ str(R7, Address(R3, -kWordSize)); | 433 __ str(R7, Address(R3, -kWordSize)); |
434 __ b(&loop, GE); | 434 __ b(&loop, GE); |
435 __ Bind(&loop_exit); | 435 __ Bind(&loop_exit); |
436 } | 436 } |
437 | 437 |
438 | 438 |
439 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. | 439 // Used by eager and lazy deoptimization. Preserve result in RAX if necessary. |
440 // This stub translates optimized frame into unoptimized frame. The optimized | 440 // This stub translates optimized frame into unoptimized frame. The optimized |
441 // frame can contain values in registers and on stack, the unoptimized | 441 // frame can contain values in registers and on stack, the unoptimized |
(...skipping 348 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
790 __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag); | 790 __ AddImmediate(R1, R0, Array::data_offset() - kHeapObjectTag); |
791 // R1: iterator which initially points to the start of the variable | 791 // R1: iterator which initially points to the start of the variable |
792 // data area to be initialized. | 792 // data area to be initialized. |
793 __ LoadObject(TMP, Object::null_object()); | 793 __ LoadObject(TMP, Object::null_object()); |
794 Label loop, done; | 794 Label loop, done; |
795 __ Bind(&loop); | 795 __ Bind(&loop); |
796 // TODO(cshapiro): StoreIntoObjectNoBarrier | 796 // TODO(cshapiro): StoreIntoObjectNoBarrier |
797 __ CompareRegisters(R1, R7); | 797 __ CompareRegisters(R1, R7); |
798 __ b(&done, CS); | 798 __ b(&done, CS); |
799 __ str(TMP, Address(R1)); // Store if unsigned lower. | 799 __ str(TMP, Address(R1)); // Store if unsigned lower. |
800 __ AddImmediate(R1, R1, kWordSize); | 800 __ AddImmediate(R1, kWordSize); |
801 __ b(&loop); // Loop until R1 == R7. | 801 __ b(&loop); // Loop until R1 == R7. |
802 __ Bind(&done); | 802 __ Bind(&done); |
803 | 803 |
804 // Done allocating and initializing the array. | 804 // Done allocating and initializing the array. |
805 // R0: new object. | 805 // R0: new object. |
806 // R2: array length as Smi (preserved for the caller.) | 806 // R2: array length as Smi (preserved for the caller.) |
807 __ ret(); | 807 __ ret(); |
808 | 808 |
809 // Unable to allocate the array using the fast inline code, just call | 809 // Unable to allocate the array using the fast inline code, just call |
810 // into the runtime. | 810 // into the runtime. |
(...skipping 76 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
887 | 887 |
888 // Load arguments descriptor array into R4, which is passed to Dart code. | 888 // Load arguments descriptor array into R4, which is passed to Dart code. |
889 __ LoadFromOffset(R4, R1, VMHandles::kOffsetOfRawPtrInHandle); | 889 __ LoadFromOffset(R4, R1, VMHandles::kOffsetOfRawPtrInHandle); |
890 | 890 |
891 // Load number of arguments into S5. | 891 // Load number of arguments into S5. |
892 __ LoadFieldFromOffset(R5, R4, ArgumentsDescriptor::count_offset()); | 892 __ LoadFieldFromOffset(R5, R4, ArgumentsDescriptor::count_offset()); |
893 __ SmiUntag(R5); | 893 __ SmiUntag(R5); |
894 | 894 |
895 // Compute address of 'arguments array' data area into R2. | 895 // Compute address of 'arguments array' data area into R2. |
896 __ LoadFromOffset(R2, R2, VMHandles::kOffsetOfRawPtrInHandle); | 896 __ LoadFromOffset(R2, R2, VMHandles::kOffsetOfRawPtrInHandle); |
897 __ AddImmediate(R2, R2, Array::data_offset() - kHeapObjectTag); | 897 __ AddImmediate(R2, Array::data_offset() - kHeapObjectTag); |
898 | 898 |
899 // Set up arguments for the Dart call. | 899 // Set up arguments for the Dart call. |
900 Label push_arguments; | 900 Label push_arguments; |
901 Label done_push_arguments; | 901 Label done_push_arguments; |
902 __ cmp(R5, Operand(0)); | 902 __ cmp(R5, Operand(0)); |
903 __ b(&done_push_arguments, EQ); // check if there are arguments. | 903 __ b(&done_push_arguments, EQ); // check if there are arguments. |
904 __ LoadImmediate(R1, 0); | 904 __ LoadImmediate(R1, 0); |
905 __ Bind(&push_arguments); | 905 __ Bind(&push_arguments); |
906 __ ldr(R3, Address(R2)); | 906 __ ldr(R3, Address(R2)); |
907 __ Push(R3); | 907 __ Push(R3); |
(...skipping 307 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1215 // R2: new object. | 1215 // R2: new object. |
1216 // R3: next object start. | 1216 // R3: next object start. |
1217 // R4: next word to be initialized. | 1217 // R4: next word to be initialized. |
1218 // R1: new object type arguments (if is_cls_parameterized). | 1218 // R1: new object type arguments (if is_cls_parameterized). |
1219 Label init_loop; | 1219 Label init_loop; |
1220 Label done; | 1220 Label done; |
1221 __ Bind(&init_loop); | 1221 __ Bind(&init_loop); |
1222 __ CompareRegisters(R4, R3); | 1222 __ CompareRegisters(R4, R3); |
1223 __ b(&done, CS); | 1223 __ b(&done, CS); |
1224 __ str(R0, Address(R4)); | 1224 __ str(R0, Address(R4)); |
1225 __ AddImmediate(R4, R4, kWordSize); | 1225 __ AddImmediate(R4, kWordSize); |
1226 __ b(&init_loop); | 1226 __ b(&init_loop); |
1227 __ Bind(&done); | 1227 __ Bind(&done); |
1228 } | 1228 } |
1229 if (is_cls_parameterized) { | 1229 if (is_cls_parameterized) { |
1230 // R1: new object type arguments. | 1230 // R1: new object type arguments. |
1231 // Set the type arguments in the new object. | 1231 // Set the type arguments in the new object. |
1232 __ StoreToOffset(R1, R2, cls.type_arguments_field_offset()); | 1232 __ StoreToOffset(R1, R2, cls.type_arguments_field_offset()); |
1233 } | 1233 } |
1234 // Done allocating and initializing the instance. | 1234 // Done allocating and initializing the instance. |
1235 // R2: new object still missing its heap tag. | 1235 // R2: new object still missing its heap tag. |
(...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1324 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, | 1324 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, |
1325 Register temp_reg) { | 1325 Register temp_reg) { |
1326 if (FLAG_optimization_counter_threshold >= 0) { | 1326 if (FLAG_optimization_counter_threshold >= 0) { |
1327 Register ic_reg = R5; | 1327 Register ic_reg = R5; |
1328 Register func_reg = temp_reg; | 1328 Register func_reg = temp_reg; |
1329 ASSERT(temp_reg == R6); | 1329 ASSERT(temp_reg == R6); |
1330 __ Comment("Increment function counter"); | 1330 __ Comment("Increment function counter"); |
1331 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset()); | 1331 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset()); |
1332 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset(), | 1332 __ LoadFieldFromOffset(R7, func_reg, Function::usage_counter_offset(), |
1333 kWord); | 1333 kWord); |
1334 __ AddImmediate(R7, R7, 1); | 1334 __ AddImmediate(R7, 1); |
1335 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset(), | 1335 __ StoreFieldToOffset(R7, func_reg, Function::usage_counter_offset(), |
1336 kWord); | 1336 kWord); |
1337 } | 1337 } |
1338 } | 1338 } |
1339 | 1339 |
1340 | 1340 |
1341 // Note: R5 must be preserved. | 1341 // Note: R5 must be preserved. |
1342 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1342 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
1343 // must have been primed with a Smi/Smi check that will be used for counting | 1343 // must have been primed with a Smi/Smi check that will be used for counting |
1344 // the invocations. | 1344 // the invocations. |
(...skipping 25 matching lines...) Expand all Loading... |
1370 __ csel(R0, R1, R0, NE); | 1370 __ csel(R0, R1, R0, NE); |
1371 break; | 1371 break; |
1372 } | 1372 } |
1373 default: | 1373 default: |
1374 UNIMPLEMENTED(); | 1374 UNIMPLEMENTED(); |
1375 } | 1375 } |
1376 | 1376 |
1377 // R5: IC data object (preserved). | 1377 // R5: IC data object (preserved). |
1378 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset()); | 1378 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset()); |
1379 // R6: ic_data_array with check entries: classes and target functions. | 1379 // R6: ic_data_array with check entries: classes and target functions. |
1380 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1380 __ AddImmediate(R6, Array::data_offset() - kHeapObjectTag); |
1381 // R6: points directly to the first ic data array element. | 1381 // R6: points directly to the first ic data array element. |
1382 #if defined(DEBUG) | 1382 #if defined(DEBUG) |
1383 // Check that first entry is for Smi/Smi. | 1383 // Check that first entry is for Smi/Smi. |
1384 Label error, ok; | 1384 Label error, ok; |
1385 const intptr_t imm_smi_cid = reinterpret_cast<intptr_t>(Smi::New(kSmiCid)); | 1385 const intptr_t imm_smi_cid = reinterpret_cast<intptr_t>(Smi::New(kSmiCid)); |
1386 __ ldr(R1, Address(R6, 0)); | 1386 __ ldr(R1, Address(R6, 0)); |
1387 __ CompareImmediate(R1, imm_smi_cid); | 1387 __ CompareImmediate(R1, imm_smi_cid); |
1388 __ b(&error, NE); | 1388 __ b(&error, NE); |
1389 __ ldr(R1, Address(R6, kWordSize)); | 1389 __ ldr(R1, Address(R6, kWordSize)); |
1390 __ CompareImmediate(R1, imm_smi_cid); | 1390 __ CompareImmediate(R1, imm_smi_cid); |
(...skipping 64 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1455 __ Bind(¬_smi_or_overflow); | 1455 __ Bind(¬_smi_or_overflow); |
1456 | 1456 |
1457 __ Comment("Extract ICData initial values and receiver cid"); | 1457 __ Comment("Extract ICData initial values and receiver cid"); |
1458 // Load arguments descriptor into R4. | 1458 // Load arguments descriptor into R4. |
1459 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset()); | 1459 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset()); |
1460 // Loop that checks if there is an IC data match. | 1460 // Loop that checks if there is an IC data match. |
1461 Label loop, found, miss; | 1461 Label loop, found, miss; |
1462 // R5: IC data object (preserved). | 1462 // R5: IC data object (preserved). |
1463 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset()); | 1463 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset()); |
1464 // R6: ic_data_array with check entries: classes and target functions. | 1464 // R6: ic_data_array with check entries: classes and target functions. |
1465 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1465 __ AddImmediate(R6, Array::data_offset() - kHeapObjectTag); |
1466 // R6: points directly to the first ic data array element. | 1466 // R6: points directly to the first ic data array element. |
1467 | 1467 |
1468 // Get the receiver's class ID (first read number of arguments from | 1468 // Get the receiver's class ID (first read number of arguments from |
1469 // arguments descriptor array and then access the receiver from the stack). | 1469 // arguments descriptor array and then access the receiver from the stack). |
1470 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); | 1470 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset()); |
1471 __ SmiUntag(R7); // Untag so we can use the LSL 3 addressing mode. | 1471 __ SmiUntag(R7); // Untag so we can use the LSL 3 addressing mode. |
1472 __ sub(R7, R7, Operand(1)); | 1472 __ sub(R7, R7, Operand(1)); |
1473 | 1473 |
1474 // R0 <- [SP + (R7 << 3)] | 1474 // R0 <- [SP + (R7 << 3)] |
1475 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled)); | 1475 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled)); |
(...skipping 20 matching lines...) Expand all Loading... |
1496 __ b(&update, NE); // Continue. | 1496 __ b(&update, NE); // Continue. |
1497 __ LoadFromOffset(R2, R6, kWordSize); | 1497 __ LoadFromOffset(R2, R6, kWordSize); |
1498 __ CompareRegisters(R1, R2); // Class id match? | 1498 __ CompareRegisters(R1, R2); // Class id match? |
1499 } | 1499 } |
1500 __ b(&found, EQ); // Break. | 1500 __ b(&found, EQ); // Break. |
1501 | 1501 |
1502 __ Bind(&update); | 1502 __ Bind(&update); |
1503 | 1503 |
1504 const intptr_t entry_size = | 1504 const intptr_t entry_size = |
1505 ICData::TestEntryLengthFor(num_args) * kWordSize; | 1505 ICData::TestEntryLengthFor(num_args) * kWordSize; |
1506 __ AddImmediate(R6, R6, entry_size); // Next entry. | 1506 __ AddImmediate(R6, entry_size); // Next entry. |
1507 | 1507 |
1508 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); // Done? | 1508 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); // Done? |
1509 if (unroll == 0) { | 1509 if (unroll == 0) { |
1510 __ b(&loop, NE); | 1510 __ b(&loop, NE); |
1511 } else { | 1511 } else { |
1512 __ b(&miss, EQ); | 1512 __ b(&miss, EQ); |
1513 } | 1513 } |
1514 } | 1514 } |
1515 | 1515 |
1516 __ Bind(&miss); | 1516 __ Bind(&miss); |
(...skipping 158 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1675 __ LoadIsolate(R6); | 1675 __ LoadIsolate(R6); |
1676 __ LoadFromOffset(R6, R6, Isolate::single_step_offset(), kUnsignedByte); | 1676 __ LoadFromOffset(R6, R6, Isolate::single_step_offset(), kUnsignedByte); |
1677 __ CompareImmediate(R6, 0); | 1677 __ CompareImmediate(R6, 0); |
1678 __ b(&stepping, NE); | 1678 __ b(&stepping, NE); |
1679 __ Bind(&done_stepping); | 1679 __ Bind(&done_stepping); |
1680 } | 1680 } |
1681 | 1681 |
1682 // R5: IC data object (preserved). | 1682 // R5: IC data object (preserved). |
1683 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset()); | 1683 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset()); |
1684 // R6: ic_data_array with entries: target functions and count. | 1684 // R6: ic_data_array with entries: target functions and count. |
1685 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1685 __ AddImmediate(R6, Array::data_offset() - kHeapObjectTag); |
1686 // R6: points directly to the first ic data array element. | 1686 // R6: points directly to the first ic data array element. |
1687 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1687 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
1688 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1688 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
1689 | 1689 |
1690 if (FLAG_optimization_counter_threshold >= 0) { | 1690 if (FLAG_optimization_counter_threshold >= 0) { |
1691 // Increment count for this call, ignore overflow. | 1691 // Increment count for this call, ignore overflow. |
1692 __ LoadFromOffset(R1, R6, count_offset); | 1692 __ LoadFromOffset(R1, R6, count_offset); |
1693 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1693 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
1694 __ StoreToOffset(R1, R6, count_offset); | 1694 __ StoreToOffset(R1, R6, count_offset); |
1695 } | 1695 } |
(...skipping 123 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1819 __ Bind(&has_no_type_arguments); | 1819 __ Bind(&has_no_type_arguments); |
1820 } | 1820 } |
1821 __ LoadClassId(R6, R0); | 1821 __ LoadClassId(R6, R0); |
1822 // R0: instance. | 1822 // R0: instance. |
1823 // R1: instantiator type arguments (only if n == 4, can be raw_null). | 1823 // R1: instantiator type arguments (only if n == 4, can be raw_null). |
1824 // R2: function type arguments (only if n == 4, can be raw_null). | 1824 // R2: function type arguments (only if n == 4, can be raw_null). |
1825 // R3: SubtypeTestCache. | 1825 // R3: SubtypeTestCache. |
1826 // R6: instance class id. | 1826 // R6: instance class id. |
1827 // R4: instance type arguments (null if none), used only if n > 1. | 1827 // R4: instance type arguments (null if none), used only if n > 1. |
1828 __ LoadFieldFromOffset(R3, R3, SubtypeTestCache::cache_offset()); | 1828 __ LoadFieldFromOffset(R3, R3, SubtypeTestCache::cache_offset()); |
1829 __ AddImmediate(R3, R3, Array::data_offset() - kHeapObjectTag); | 1829 __ AddImmediate(R3, Array::data_offset() - kHeapObjectTag); |
1830 | 1830 |
1831 Label loop, found, not_found, next_iteration; | 1831 Label loop, found, not_found, next_iteration; |
1832 // R3: entry start. | 1832 // R3: entry start. |
1833 // R6: instance class id. | 1833 // R6: instance class id. |
1834 // R4: instance type arguments (still null if closure). | 1834 // R4: instance type arguments (still null if closure). |
1835 __ SmiTag(R6); | 1835 __ SmiTag(R6); |
1836 __ CompareImmediate(R6, Smi::RawValue(kClosureCid)); | 1836 __ CompareImmediate(R6, Smi::RawValue(kClosureCid)); |
1837 __ b(&loop, NE); | 1837 __ b(&loop, NE); |
1838 __ LoadFieldFromOffset(R4, R0, Closure::function_type_arguments_offset()); | 1838 __ LoadFieldFromOffset(R4, R0, Closure::function_type_arguments_offset()); |
1839 __ CompareObject(R4, Object::null_object()); | 1839 __ CompareObject(R4, Object::null_object()); |
(...skipping 22 matching lines...) Expand all Loading... |
1862 R5, R3, kWordSize * SubtypeTestCache::kInstantiatorTypeArguments); | 1862 R5, R3, kWordSize * SubtypeTestCache::kInstantiatorTypeArguments); |
1863 __ CompareRegisters(R5, R1); | 1863 __ CompareRegisters(R5, R1); |
1864 __ b(&next_iteration, NE); | 1864 __ b(&next_iteration, NE); |
1865 __ LoadFromOffset(R5, R3, | 1865 __ LoadFromOffset(R5, R3, |
1866 kWordSize * SubtypeTestCache::kFunctionTypeArguments); | 1866 kWordSize * SubtypeTestCache::kFunctionTypeArguments); |
1867 __ CompareRegisters(R5, R2); | 1867 __ CompareRegisters(R5, R2); |
1868 __ b(&found, EQ); | 1868 __ b(&found, EQ); |
1869 } | 1869 } |
1870 } | 1870 } |
1871 __ Bind(&next_iteration); | 1871 __ Bind(&next_iteration); |
1872 __ AddImmediate(R3, R3, kWordSize * SubtypeTestCache::kTestEntryLength); | 1872 __ AddImmediate(R3, kWordSize * SubtypeTestCache::kTestEntryLength); |
1873 __ b(&loop); | 1873 __ b(&loop); |
1874 // Fall through to not found. | 1874 // Fall through to not found. |
1875 __ Bind(¬_found); | 1875 __ Bind(¬_found); |
1876 __ LoadObject(R1, Object::null_object()); | 1876 __ LoadObject(R1, Object::null_object()); |
1877 __ ret(); | 1877 __ ret(); |
1878 | 1878 |
1879 __ Bind(&found); | 1879 __ Bind(&found); |
1880 __ LoadFromOffset(R1, R3, kWordSize * SubtypeTestCache::kTestResult); | 1880 __ LoadFromOffset(R1, R3, kWordSize * SubtypeTestCache::kTestResult); |
1881 __ ret(); | 1881 __ ret(); |
1882 } | 1882 } |
(...skipping 294 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2177 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 2177 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
2178 __ br(R1); | 2178 __ br(R1); |
2179 | 2179 |
2180 // Probe failed, check if it is a miss. | 2180 // Probe failed, check if it is a miss. |
2181 __ Bind(&probe_failed); | 2181 __ Bind(&probe_failed); |
2182 ASSERT(kIllegalCid == 0); | 2182 ASSERT(kIllegalCid == 0); |
2183 __ tst(R6, Operand(R6)); | 2183 __ tst(R6, Operand(R6)); |
2184 __ b(&load_target, EQ); // branch if miss. | 2184 __ b(&load_target, EQ); // branch if miss. |
2185 | 2185 |
2186 // Try next extry in the table. | 2186 // Try next extry in the table. |
2187 __ AddImmediate(R3, R3, Smi::RawValue(1)); | 2187 __ AddImmediate(R3, Smi::RawValue(1)); |
2188 __ b(&loop); | 2188 __ b(&loop); |
2189 | 2189 |
2190 // Load cid for the Smi case. | 2190 // Load cid for the Smi case. |
2191 __ Bind(&smi_case); | 2191 __ Bind(&smi_case); |
2192 __ LoadImmediate(R0, kSmiCid); | 2192 __ LoadImmediate(R0, kSmiCid); |
2193 __ b(&cid_loaded); | 2193 __ b(&cid_loaded); |
2194 } | 2194 } |
2195 | 2195 |
2196 | 2196 |
2197 // Called from switchable IC calls. | 2197 // Called from switchable IC calls. |
2198 // R0: receiver | 2198 // R0: receiver |
2199 // R5: ICData (preserved) | 2199 // R5: ICData (preserved) |
2200 // Passed to target: | 2200 // Passed to target: |
2201 // CODE_REG: target Code object | 2201 // CODE_REG: target Code object |
2202 // R4: arguments descriptor | 2202 // R4: arguments descriptor |
2203 void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) { | 2203 void StubCode::GenerateICCallThroughFunctionStub(Assembler* assembler) { |
2204 Label loop, found, miss; | 2204 Label loop, found, miss; |
2205 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 2205 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
2206 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset())); | 2206 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset())); |
2207 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); | 2207 __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag); |
2208 // R8: first IC entry | 2208 // R8: first IC entry |
2209 __ LoadTaggedClassIdMayBeSmi(R1, R0); | 2209 __ LoadTaggedClassIdMayBeSmi(R1, R0); |
2210 // R1: receiver cid as Smi | 2210 // R1: receiver cid as Smi |
2211 | 2211 |
2212 __ Bind(&loop); | 2212 __ Bind(&loop); |
2213 __ ldr(R2, Address(R8, 0)); | 2213 __ ldr(R2, Address(R8, 0)); |
2214 __ cmp(R1, Operand(R2)); | 2214 __ cmp(R1, Operand(R2)); |
2215 __ b(&found, EQ); | 2215 __ b(&found, EQ); |
2216 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); | 2216 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); |
2217 __ b(&miss, EQ); | 2217 __ b(&miss, EQ); |
2218 | 2218 |
2219 const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; | 2219 const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; |
2220 __ AddImmediate(R8, R8, entry_length); // Next entry. | 2220 __ AddImmediate(R8, entry_length); // Next entry. |
2221 __ b(&loop); | 2221 __ b(&loop); |
2222 | 2222 |
2223 __ Bind(&found); | 2223 __ Bind(&found); |
2224 const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize; | 2224 const intptr_t target_offset = ICData::TargetIndexFor(1) * kWordSize; |
2225 __ ldr(R0, Address(R8, target_offset)); | 2225 __ ldr(R0, Address(R8, target_offset)); |
2226 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); | 2226 __ ldr(R1, FieldAddress(R0, Function::entry_point_offset())); |
2227 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); | 2227 __ ldr(CODE_REG, FieldAddress(R0, Function::code_offset())); |
2228 __ br(R1); | 2228 __ br(R1); |
2229 | 2229 |
2230 __ Bind(&miss); | 2230 __ Bind(&miss); |
2231 __ LoadIsolate(R2); | 2231 __ LoadIsolate(R2); |
2232 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); | 2232 __ ldr(CODE_REG, Address(R2, Isolate::ic_miss_code_offset())); |
2233 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); | 2233 __ ldr(R1, FieldAddress(CODE_REG, Code::entry_point_offset())); |
2234 __ br(R1); | 2234 __ br(R1); |
2235 } | 2235 } |
2236 | 2236 |
2237 | 2237 |
2238 void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) { | 2238 void StubCode::GenerateICCallThroughCodeStub(Assembler* assembler) { |
2239 Label loop, found, miss; | 2239 Label loop, found, miss; |
2240 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 2240 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
2241 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset())); | 2241 __ ldr(R8, FieldAddress(R5, ICData::ic_data_offset())); |
2242 __ AddImmediate(R8, R8, Array::data_offset() - kHeapObjectTag); | 2242 __ AddImmediate(R8, Array::data_offset() - kHeapObjectTag); |
2243 // R8: first IC entry | 2243 // R8: first IC entry |
2244 __ LoadTaggedClassIdMayBeSmi(R1, R0); | 2244 __ LoadTaggedClassIdMayBeSmi(R1, R0); |
2245 // R1: receiver cid as Smi | 2245 // R1: receiver cid as Smi |
2246 | 2246 |
2247 __ Bind(&loop); | 2247 __ Bind(&loop); |
2248 __ ldr(R2, Address(R8, 0)); | 2248 __ ldr(R2, Address(R8, 0)); |
2249 __ cmp(R1, Operand(R2)); | 2249 __ cmp(R1, Operand(R2)); |
2250 __ b(&found, EQ); | 2250 __ b(&found, EQ); |
2251 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); | 2251 __ CompareImmediate(R2, Smi::RawValue(kIllegalCid)); |
2252 __ b(&miss, EQ); | 2252 __ b(&miss, EQ); |
2253 | 2253 |
2254 const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; | 2254 const intptr_t entry_length = ICData::TestEntryLengthFor(1) * kWordSize; |
2255 __ AddImmediate(R8, R8, entry_length); // Next entry. | 2255 __ AddImmediate(R8, entry_length); // Next entry. |
2256 __ b(&loop); | 2256 __ b(&loop); |
2257 | 2257 |
2258 __ Bind(&found); | 2258 __ Bind(&found); |
2259 const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize; | 2259 const intptr_t code_offset = ICData::CodeIndexFor(1) * kWordSize; |
2260 const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize; | 2260 const intptr_t entry_offset = ICData::EntryPointIndexFor(1) * kWordSize; |
2261 __ ldr(R1, Address(R8, entry_offset)); | 2261 __ ldr(R1, Address(R8, entry_offset)); |
2262 __ ldr(CODE_REG, Address(R8, code_offset)); | 2262 __ ldr(CODE_REG, Address(R8, code_offset)); |
2263 __ br(R1); | 2263 __ br(R1); |
2264 | 2264 |
2265 __ Bind(&miss); | 2265 __ Bind(&miss); |
(...skipping 95 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2361 } | 2361 } |
2362 | 2362 |
2363 | 2363 |
2364 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { | 2364 void StubCode::GenerateAsynchronousGapMarkerStub(Assembler* assembler) { |
2365 __ brk(0); | 2365 __ brk(0); |
2366 } | 2366 } |
2367 | 2367 |
2368 } // namespace dart | 2368 } // namespace dart |
2369 | 2369 |
2370 #endif // defined TARGET_ARCH_ARM64 | 2370 #endif // defined TARGET_ARCH_ARM64 |
OLD | NEW |