| 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 |