| OLD | NEW |
| 1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2013, 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_ARM) | 6 #if defined(TARGET_ARCH_ARM) |
| 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/cpu.h" | 10 #include "vm/cpu.h" |
| (...skipping 1265 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1276 __ Pop(R5); | 1276 __ Pop(R5); |
| 1277 __ LeaveStubFrame(); | 1277 __ LeaveStubFrame(); |
| 1278 __ Bind(¬_stepping); | 1278 __ Bind(¬_stepping); |
| 1279 } | 1279 } |
| 1280 | 1280 |
| 1281 // Load arguments descriptor into R4. | 1281 // Load arguments descriptor into R4. |
| 1282 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); | 1282 __ ldr(R4, FieldAddress(R5, ICData::arguments_descriptor_offset())); |
| 1283 // Preserve return address, since LR is needed for subroutine call. | 1283 // Preserve return address, since LR is needed for subroutine call. |
| 1284 __ mov(R8, Operand(LR)); | 1284 __ mov(R8, Operand(LR)); |
| 1285 // Loop that checks if there is an IC data match. | 1285 // Loop that checks if there is an IC data match. |
| 1286 Label loop, update, test, found, get_class_id_as_smi; | 1286 Label loop, update, test, found; |
| 1287 // R5: IC data object (preserved). | 1287 // R5: IC data object (preserved). |
| 1288 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); | 1288 __ ldr(R6, FieldAddress(R5, ICData::ic_data_offset())); |
| 1289 // R6: ic_data_array with check entries: classes and target functions. | 1289 // R6: ic_data_array with check entries: classes and target functions. |
| 1290 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); | 1290 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag); |
| 1291 // R6: points directly to the first ic data array element. | 1291 // R6: points directly to the first ic data array element. |
| 1292 | 1292 |
| 1293 // Get the receiver's class ID (first read number of arguments from | 1293 // Get the receiver's class ID (first read number of arguments from |
| 1294 // arguments descriptor array and then access the receiver from the stack). | 1294 // arguments descriptor array and then access the receiver from the stack). |
| 1295 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); | 1295 __ ldr(R7, FieldAddress(R4, ArgumentsDescriptor::count_offset())); |
| 1296 __ sub(R7, R7, Operand(Smi::RawValue(1))); | 1296 __ sub(R7, R7, Operand(Smi::RawValue(1))); |
| 1297 __ ldr(R0, Address(SP, R7, LSL, 1)); // R7 (argument_count - 1) is smi. | 1297 __ ldr(R0, Address(SP, R7, LSL, 1)); // R7 (argument_count - 1) is smi. |
| 1298 __ bl(&get_class_id_as_smi); | 1298 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
| 1299 // R7: argument_count - 1 (smi). | 1299 // R7: argument_count - 1 (smi). |
| 1300 // R0: receiver's class ID (smi). | 1300 // R0: receiver's class ID (smi). |
| 1301 __ ldr(R1, Address(R6, 0)); // First class id (smi) to check. | 1301 __ ldr(R1, Address(R6, 0)); // First class id (smi) to check. |
| 1302 __ b(&test); | 1302 __ b(&test); |
| 1303 | 1303 |
| 1304 __ Bind(&loop); | 1304 __ Bind(&loop); |
| 1305 for (int i = 0; i < num_args; i++) { | 1305 for (int i = 0; i < num_args; i++) { |
| 1306 if (i > 0) { | 1306 if (i > 0) { |
| 1307 // If not the first, load the next argument's class ID. | 1307 // If not the first, load the next argument's class ID. |
| 1308 __ AddImmediate(R0, R7, Smi::RawValue(-i)); | 1308 __ AddImmediate(R0, R7, Smi::RawValue(-i)); |
| 1309 __ ldr(R0, Address(SP, R0, LSL, 1)); | 1309 __ ldr(R0, Address(SP, R0, LSL, 1)); |
| 1310 __ bl(&get_class_id_as_smi); | 1310 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
| 1311 // R0: next argument class ID (smi). | 1311 // R0: next argument class ID (smi). |
| 1312 __ LoadFromOffset(kWord, R1, R6, i * kWordSize); | 1312 __ LoadFromOffset(kWord, R1, R6, i * kWordSize); |
| 1313 // R1: next class ID to check (smi). | 1313 // R1: next class ID to check (smi). |
| 1314 } | 1314 } |
| 1315 __ cmp(R0, Operand(R1)); // Class id match? | 1315 __ cmp(R0, Operand(R1)); // Class id match? |
| 1316 if (i < (num_args - 1)) { | 1316 if (i < (num_args - 1)) { |
| 1317 __ b(&update, NE); // Continue. | 1317 __ b(&update, NE); // Continue. |
| 1318 } else { | 1318 } else { |
| 1319 // Last check, all checks before matched. | 1319 // Last check, all checks before matched. |
| 1320 __ mov(LR, Operand(R8), EQ); // Restore return address if found. | 1320 __ mov(LR, Operand(R8), EQ); // Restore return address if found. |
| 1321 __ b(&found, EQ); // Break. | 1321 __ b(&found, EQ); // Break. |
| 1322 } | 1322 } |
| 1323 } | 1323 } |
| 1324 __ Bind(&update); | 1324 __ Bind(&update); |
| 1325 // Reload receiver class ID. It has not been destroyed when num_args == 1. | 1325 // Reload receiver class ID. It has not been destroyed when num_args == 1. |
| 1326 if (num_args > 1) { | 1326 if (num_args > 1) { |
| 1327 __ ldr(R0, Address(SP, R7, LSL, 1)); | 1327 __ ldr(R0, Address(SP, R7, LSL, 1)); |
| 1328 __ bl(&get_class_id_as_smi); | 1328 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
| 1329 } | 1329 } |
| 1330 | 1330 |
| 1331 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1331 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1332 __ AddImmediate(R6, entry_size); // Next entry. | 1332 __ AddImmediate(R6, entry_size); // Next entry. |
| 1333 __ ldr(R1, Address(R6, 0)); // Next class ID. | 1333 __ ldr(R1, Address(R6, 0)); // Next class ID. |
| 1334 | 1334 |
| 1335 __ Bind(&test); | 1335 __ Bind(&test); |
| 1336 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done? | 1336 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid)); // Done? |
| 1337 __ b(&loop, NE); | 1337 __ b(&loop, NE); |
| 1338 | 1338 |
| (...skipping 39 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1378 __ StoreToOffset(kWord, R1, R6, count_offset); | 1378 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1379 __ b(&call_target_function, VC); // No overflow. | 1379 __ b(&call_target_function, VC); // No overflow. |
| 1380 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); | 1380 __ LoadImmediate(R1, Smi::RawValue(Smi::kMaxValue)); |
| 1381 __ StoreToOffset(kWord, R1, R6, count_offset); | 1381 __ StoreToOffset(kWord, R1, R6, count_offset); |
| 1382 | 1382 |
| 1383 __ Bind(&call_target_function); | 1383 __ Bind(&call_target_function); |
| 1384 // R0: target function. | 1384 // R0: target function. |
| 1385 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); | 1385 __ ldr(R2, FieldAddress(R0, Function::instructions_offset())); |
| 1386 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); | 1386 __ AddImmediate(R2, Instructions::HeaderSize() - kHeapObjectTag); |
| 1387 __ bx(R2); | 1387 __ bx(R2); |
| 1388 | |
| 1389 // Instance in R0, return its class-id in R0 as Smi. | |
| 1390 __ Bind(&get_class_id_as_smi); | |
| 1391 | |
| 1392 // Test if Smi -> load Smi class for comparison. | |
| 1393 __ tst(R0, Operand(kSmiTagMask)); | |
| 1394 __ mov(R0, Operand(Smi::RawValue(kSmiCid)), EQ); | |
| 1395 __ bx(LR, EQ); | |
| 1396 __ LoadClassId(R0, R0); | |
| 1397 __ SmiTag(R0); | |
| 1398 __ bx(LR); | |
| 1399 } | 1388 } |
| 1400 | 1389 |
| 1401 | 1390 |
| 1402 // Use inline cache data array to invoke the target or continue in inline | 1391 // Use inline cache data array to invoke the target or continue in inline |
| 1403 // cache miss handler. Stub for 1-argument check (receiver class). | 1392 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1404 // LR: return address. | 1393 // LR: return address. |
| 1405 // R5: inline cache data object. | 1394 // R5: inline cache data object. |
| 1406 // Inline cache data object structure: | 1395 // Inline cache data object structure: |
| 1407 // 0: function-name | 1396 // 0: function-name |
| 1408 // 1: N, number of arguments checked. | 1397 // 1: N, number of arguments checked. |
| (...skipping 445 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1854 const Register right = R0; | 1843 const Register right = R0; |
| 1855 __ ldr(left, Address(SP, 1 * kWordSize)); | 1844 __ ldr(left, Address(SP, 1 * kWordSize)); |
| 1856 __ ldr(right, Address(SP, 0 * kWordSize)); | 1845 __ ldr(right, Address(SP, 0 * kWordSize)); |
| 1857 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 1846 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 1858 __ Ret(); | 1847 __ Ret(); |
| 1859 } | 1848 } |
| 1860 | 1849 |
| 1861 } // namespace dart | 1850 } // namespace dart |
| 1862 | 1851 |
| 1863 #endif // defined TARGET_ARCH_ARM | 1852 #endif // defined TARGET_ARCH_ARM |
| OLD | NEW |