| 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/code_generator.h" | 9 #include "vm/code_generator.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| 11 #include "vm/dart_entry.h" | 11 #include "vm/dart_entry.h" |
| 12 #include "vm/flow_graph_compiler.h" | 12 #include "vm/flow_graph_compiler.h" |
| 13 #include "vm/heap.h" | 13 #include "vm/heap.h" |
| 14 #include "vm/instructions.h" | 14 #include "vm/instructions.h" |
| 15 #include "vm/object_store.h" | 15 #include "vm/object_store.h" |
| 16 #include "vm/stack_frame.h" | 16 #include "vm/stack_frame.h" |
| 17 #include "vm/stub_code.h" | 17 #include "vm/stub_code.h" |
| 18 #include "vm/tags.h" | 18 #include "vm/tags.h" |
| 19 | 19 |
| 20 #define __ assembler-> | 20 #define __ assembler-> |
| 21 | 21 |
| 22 namespace dart { | 22 namespace dart { |
| 23 | 23 |
| 24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); | 24 DEFINE_FLAG(bool, inline_alloc, true, "Inline allocation of objects."); |
| 25 DEFINE_FLAG(bool, use_slow_path, false, | 25 DEFINE_FLAG(bool, use_slow_path, false, |
| 26 "Set to true for debugging & verifying the slow paths."); | 26 "Set to true for debugging & verifying the slow paths."); |
| 27 DECLARE_FLAG(bool, trace_optimized_ic_calls); | 27 DECLARE_FLAG(bool, trace_optimized_ic_calls); |
| 28 DECLARE_FLAG(int, optimization_counter_threshold); |
| 28 | 29 |
| 29 // Input parameters: | 30 // Input parameters: |
| 30 // LR : return address. | 31 // LR : return address. |
| 31 // SP : address of last argument in argument array. | 32 // SP : address of last argument in argument array. |
| 32 // SP + 8*R4 - 8 : address of first argument in argument array. | 33 // SP + 8*R4 - 8 : address of first argument in argument array. |
| 33 // SP + 8*R4 : address of return value. | 34 // SP + 8*R4 : address of return value. |
| 34 // R5 : address of the runtime function to call. | 35 // R5 : address of the runtime function to call. |
| 35 // R4 : number of arguments to the call. | 36 // R4 : number of arguments to the call. |
| 36 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { | 37 void StubCode::GenerateCallToRuntimeStub(Assembler* assembler) { |
| 37 const intptr_t isolate_offset = NativeArguments::isolate_offset(); | 38 const intptr_t isolate_offset = NativeArguments::isolate_offset(); |
| (...skipping 1220 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1258 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord); | 1259 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord); |
| 1259 __ add(R7, R7, Operand(1)); | 1260 __ add(R7, R7, Operand(1)); |
| 1260 __ StoreFieldToOffset( | 1261 __ StoreFieldToOffset( |
| 1261 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord); | 1262 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord); |
| 1262 } | 1263 } |
| 1263 | 1264 |
| 1264 | 1265 |
| 1265 // Loads function into 'temp_reg'. | 1266 // Loads function into 'temp_reg'. |
| 1266 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, | 1267 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, |
| 1267 Register temp_reg) { | 1268 Register temp_reg) { |
| 1268 Register ic_reg = R5; | 1269 if (FLAG_optimization_counter_threshold != -1) { |
| 1269 Register func_reg = temp_reg; | 1270 Register ic_reg = R5; |
| 1270 ASSERT(temp_reg == R6); | 1271 Register func_reg = temp_reg; |
| 1271 __ Comment("Increment function counter"); | 1272 ASSERT(temp_reg == R6); |
| 1272 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset(), kNoPP); | 1273 __ Comment("Increment function counter"); |
| 1273 __ LoadFieldFromOffset( | 1274 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset(), kNoPP); |
| 1274 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord); | 1275 __ LoadFieldFromOffset( |
| 1275 __ AddImmediate(R7, R7, 1, kNoPP); | 1276 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord); |
| 1276 __ StoreFieldToOffset( | 1277 __ AddImmediate(R7, R7, 1, kNoPP); |
| 1277 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord); | 1278 __ StoreFieldToOffset( |
| 1279 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord); |
| 1280 } |
| 1278 } | 1281 } |
| 1279 | 1282 |
| 1280 | 1283 |
| 1281 // Note: R5 must be preserved. | 1284 // Note: R5 must be preserved. |
| 1282 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1285 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
| 1283 // must have been primed with a Smi/Smi check that will be used for counting | 1286 // must have been primed with a Smi/Smi check that will be used for counting |
| 1284 // the invocations. | 1287 // the invocations. |
| 1285 static void EmitFastSmiOp(Assembler* assembler, | 1288 static void EmitFastSmiOp(Assembler* assembler, |
| 1286 Token::Kind kind, | 1289 Token::Kind kind, |
| 1287 intptr_t num_args, | 1290 intptr_t num_args, |
| (...skipping 48 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1336 __ ldr(R1, Address(R6, 0)); | 1339 __ ldr(R1, Address(R6, 0)); |
| 1337 __ CompareImmediate(R1, imm_smi_cid, kNoPP); | 1340 __ CompareImmediate(R1, imm_smi_cid, kNoPP); |
| 1338 __ b(&error, NE); | 1341 __ b(&error, NE); |
| 1339 __ ldr(R1, Address(R6, kWordSize)); | 1342 __ ldr(R1, Address(R6, kWordSize)); |
| 1340 __ CompareImmediate(R1, imm_smi_cid, kNoPP); | 1343 __ CompareImmediate(R1, imm_smi_cid, kNoPP); |
| 1341 __ b(&ok, EQ); | 1344 __ b(&ok, EQ); |
| 1342 __ Bind(&error); | 1345 __ Bind(&error); |
| 1343 __ Stop("Incorrect IC data"); | 1346 __ Stop("Incorrect IC data"); |
| 1344 __ Bind(&ok); | 1347 __ Bind(&ok); |
| 1345 #endif | 1348 #endif |
| 1346 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1349 if (FLAG_optimization_counter_threshold != -1) { |
| 1347 // Update counter. | 1350 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1348 __ LoadFromOffset(R1, R6, count_offset, kNoPP); | 1351 // Update counter. |
| 1349 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1352 __ LoadFromOffset(R1, R6, count_offset, kNoPP); |
| 1350 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP); | 1353 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
| 1351 __ csel(R1, R2, R1, VS); // Overflow. | 1354 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP); |
| 1352 __ StoreToOffset(R1, R6, count_offset, kNoPP); | 1355 __ csel(R1, R2, R1, VS); // Overflow. |
| 1356 __ StoreToOffset(R1, R6, count_offset, kNoPP); |
| 1357 } |
| 1353 | 1358 |
| 1354 __ ret(); | 1359 __ ret(); |
| 1355 } | 1360 } |
| 1356 | 1361 |
| 1357 | 1362 |
| 1358 // Generate inline cache check for 'num_args'. | 1363 // Generate inline cache check for 'num_args'. |
| 1359 // LR: return address. | 1364 // LR: return address. |
| 1360 // R5: inline cache data object. | 1365 // R5: inline cache data object. |
| 1361 // Control flow: | 1366 // Control flow: |
| 1362 // - If receiver is null -> jump to IC miss. | 1367 // - If receiver is null -> jump to IC miss. |
| (...skipping 150 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1513 Label call_target_function; | 1518 Label call_target_function; |
| 1514 __ b(&call_target_function); | 1519 __ b(&call_target_function); |
| 1515 | 1520 |
| 1516 __ Bind(&found); | 1521 __ Bind(&found); |
| 1517 __ Comment("Update caller's counter"); | 1522 __ Comment("Update caller's counter"); |
| 1518 // R6: pointer to an IC data check group. | 1523 // R6: pointer to an IC data check group. |
| 1519 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1524 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1520 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1525 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1521 __ LoadFromOffset(R0, R6, target_offset, kNoPP); | 1526 __ LoadFromOffset(R0, R6, target_offset, kNoPP); |
| 1522 | 1527 |
| 1523 // Update counter. | 1528 if (FLAG_optimization_counter_threshold != -1) { |
| 1524 __ LoadFromOffset(R1, R6, count_offset, kNoPP); | 1529 // Update counter. |
| 1525 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1530 __ LoadFromOffset(R1, R6, count_offset, kNoPP); |
| 1526 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP); | 1531 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
| 1527 __ csel(R1, R2, R1, VS); // Overflow. | 1532 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP); |
| 1528 __ StoreToOffset(R1, R6, count_offset, kNoPP); | 1533 __ csel(R1, R2, R1, VS); // Overflow. |
| 1534 __ StoreToOffset(R1, R6, count_offset, kNoPP); |
| 1535 } |
| 1529 | 1536 |
| 1530 __ Comment("Call target"); | 1537 __ Comment("Call target"); |
| 1531 __ Bind(&call_target_function); | 1538 __ Bind(&call_target_function); |
| 1532 // R0: target function. | 1539 // R0: target function. |
| 1533 __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP); | 1540 __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP); |
| 1534 __ AddImmediate( | 1541 __ AddImmediate( |
| 1535 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); | 1542 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); |
| 1536 if (range_collection_mode == kCollectRanges) { | 1543 if (range_collection_mode == kCollectRanges) { |
| 1537 __ ldr(R1, Address(SP, 0 * kWordSize)); | 1544 __ ldr(R1, Address(SP, 0 * kWordSize)); |
| 1538 if (num_args == 2) { | 1545 if (num_args == 2) { |
| (...skipping 159 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1698 __ Bind(&done_stepping); | 1705 __ Bind(&done_stepping); |
| 1699 | 1706 |
| 1700 // R5: IC data object (preserved). | 1707 // R5: IC data object (preserved). |
| 1701 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP); | 1708 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP); |
| 1702 // R6: ic_data_array with entries: target functions and count. | 1709 // R6: ic_data_array with entries: target functions and count. |
| 1703 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); | 1710 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); |
| 1704 // R6: points directly to the first ic data array element. | 1711 // R6: points directly to the first ic data array element. |
| 1705 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; | 1712 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; |
| 1706 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; | 1713 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; |
| 1707 | 1714 |
| 1708 // Increment count for this call. | 1715 if (FLAG_optimization_counter_threshold != -1) { |
| 1709 __ LoadFromOffset(R1, R6, count_offset, kNoPP); | 1716 // Increment count for this call. |
| 1710 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1717 __ LoadFromOffset(R1, R6, count_offset, kNoPP); |
| 1711 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP); | 1718 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
| 1712 __ csel(R1, R2, R1, VS); // Overflow. | 1719 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP); |
| 1713 __ StoreToOffset(R1, R6, count_offset, kNoPP); | 1720 __ csel(R1, R2, R1, VS); // Overflow. |
| 1721 __ StoreToOffset(R1, R6, count_offset, kNoPP); |
| 1722 } |
| 1714 | 1723 |
| 1715 // Load arguments descriptor into R4. | 1724 // Load arguments descriptor into R4. |
| 1716 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset(), kNoPP); | 1725 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset(), kNoPP); |
| 1717 | 1726 |
| 1718 // Get function and call it, if possible. | 1727 // Get function and call it, if possible. |
| 1719 __ LoadFromOffset(R0, R6, target_offset, kNoPP); | 1728 __ LoadFromOffset(R0, R6, target_offset, kNoPP); |
| 1720 __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP); | 1729 __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP); |
| 1721 | 1730 |
| 1722 // R0: function. | 1731 // R0: function. |
| 1723 // R2: target instructons. | 1732 // R2: target instructons. |
| (...skipping 380 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2104 const Register right = R0; | 2113 const Register right = R0; |
| 2105 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); | 2114 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); |
| 2106 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); | 2115 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); |
| 2107 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2116 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2108 __ ret(); | 2117 __ ret(); |
| 2109 } | 2118 } |
| 2110 | 2119 |
| 2111 } // namespace dart | 2120 } // namespace dart |
| 2112 | 2121 |
| 2113 #endif // defined TARGET_ARCH_ARM64 | 2122 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |