| 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" |
| (...skipping 1261 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1272 | 1272 |
| 1273 // Note: R5 must be preserved. | 1273 // Note: R5 must be preserved. |
| 1274 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1274 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
| 1275 // must have been primed with a Smi/Smi check that will be used for counting | 1275 // must have been primed with a Smi/Smi check that will be used for counting |
| 1276 // the invocations. | 1276 // the invocations. |
| 1277 static void EmitFastSmiOp(Assembler* assembler, | 1277 static void EmitFastSmiOp(Assembler* assembler, |
| 1278 Token::Kind kind, | 1278 Token::Kind kind, |
| 1279 intptr_t num_args, | 1279 intptr_t num_args, |
| 1280 Label* not_smi_or_overflow, | 1280 Label* not_smi_or_overflow, |
| 1281 bool should_update_result_range) { | 1281 bool should_update_result_range) { |
| 1282 __ Comment("Fast Smi op"); |
| 1282 if (FLAG_throw_on_javascript_int_overflow) { | 1283 if (FLAG_throw_on_javascript_int_overflow) { |
| 1283 // The overflow check is more complex than implemented below. | 1284 // The overflow check is more complex than implemented below. |
| 1284 return; | 1285 return; |
| 1285 } | 1286 } |
| 1286 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Right. | 1287 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Right. |
| 1287 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Left. | 1288 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Left. |
| 1288 __ orr(TMP, R0, Operand(R1)); | 1289 __ orr(TMP, R0, Operand(R1)); |
| 1289 __ tsti(TMP, Immediate(kSmiTagMask)); | 1290 __ tsti(TMP, Immediate(kSmiTagMask)); |
| 1290 __ b(not_smi_or_overflow, NE); | 1291 __ b(not_smi_or_overflow, NE); |
| 1291 switch (kind) { | 1292 switch (kind) { |
| (...skipping 79 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1371 kNoPP, kUnsignedWord); | 1372 kNoPP, kUnsignedWord); |
| 1372 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1373 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1373 __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask())); | 1374 __ andi(R6, R6, Immediate(ICData::NumArgsTestedMask())); |
| 1374 __ CompareImmediate(R6, num_args, kNoPP); | 1375 __ CompareImmediate(R6, num_args, kNoPP); |
| 1375 __ b(&ok, EQ); | 1376 __ b(&ok, EQ); |
| 1376 __ Stop("Incorrect stub for IC data"); | 1377 __ Stop("Incorrect stub for IC data"); |
| 1377 __ Bind(&ok); | 1378 __ Bind(&ok); |
| 1378 } | 1379 } |
| 1379 #endif // DEBUG | 1380 #endif // DEBUG |
| 1380 | 1381 |
| 1381 // Check single stepping. | 1382 __ Comment("Check single stepping"); |
| 1382 Label stepping, done_stepping; | 1383 Label stepping, done_stepping; |
| 1383 __ LoadIsolate(R6, kNoPP); | 1384 __ LoadIsolate(R6, kNoPP); |
| 1384 __ LoadFromOffset( | 1385 __ LoadFromOffset( |
| 1385 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); | 1386 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); |
| 1386 __ CompareRegisters(R6, ZR); | 1387 __ CompareRegisters(R6, ZR); |
| 1387 __ b(&stepping, NE); | 1388 __ b(&stepping, NE); |
| 1388 __ Bind(&done_stepping); | 1389 __ Bind(&done_stepping); |
| 1389 | 1390 |
| 1391 __ Comment("Range feedback collection"); |
| 1390 Label not_smi_or_overflow; | 1392 Label not_smi_or_overflow; |
| 1391 if (range_collection_mode == kCollectRanges) { | 1393 if (range_collection_mode == kCollectRanges) { |
| 1392 ASSERT((num_args == 1) || (num_args == 2)); | 1394 ASSERT((num_args == 1) || (num_args == 2)); |
| 1393 if (num_args == 2) { | 1395 if (num_args == 2) { |
| 1394 __ ldr(R0, Address(SP, 1 * kWordSize)); | 1396 __ ldr(R0, Address(SP, 1 * kWordSize)); |
| 1395 __ UpdateRangeFeedback(R0, 0, R5, R1, R4, ¬_smi_or_overflow); | 1397 __ UpdateRangeFeedback(R0, 0, R5, R1, R4, ¬_smi_or_overflow); |
| 1396 } | 1398 } |
| 1397 | 1399 |
| 1398 __ ldr(R0, Address(SP, 0 * kWordSize)); | 1400 __ ldr(R0, Address(SP, 0 * kWordSize)); |
| 1399 __ UpdateRangeFeedback(R0, num_args - 1, R5, R1, R4, ¬_smi_or_overflow); | 1401 __ UpdateRangeFeedback(R0, num_args - 1, R5, R1, R4, ¬_smi_or_overflow); |
| 1400 } | 1402 } |
| 1401 if (kind != Token::kILLEGAL) { | 1403 if (kind != Token::kILLEGAL) { |
| 1402 EmitFastSmiOp(assembler, | 1404 EmitFastSmiOp(assembler, |
| 1403 kind, | 1405 kind, |
| 1404 num_args, | 1406 num_args, |
| 1405 ¬_smi_or_overflow, | 1407 ¬_smi_or_overflow, |
| 1406 (range_collection_mode == kCollectRanges)); | 1408 (range_collection_mode == kCollectRanges)); |
| 1407 } | 1409 } |
| 1408 __ Bind(¬_smi_or_overflow); | 1410 __ Bind(¬_smi_or_overflow); |
| 1409 | 1411 |
| 1412 __ Comment("Extract ICData initial values and receiver cid"); |
| 1410 // Load arguments descriptor into R4. | 1413 // Load arguments descriptor into R4. |
| 1411 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset(), kNoPP); | 1414 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset(), kNoPP); |
| 1412 // Loop that checks if there is an IC data match. | 1415 // Loop that checks if there is an IC data match. |
| 1413 Label loop, update, test, found; | 1416 Label loop, update, test, found; |
| 1414 // R5: IC data object (preserved). | 1417 // R5: IC data object (preserved). |
| 1415 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP); | 1418 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP); |
| 1416 // R6: ic_data_array with check entries: classes and target functions. | 1419 // R6: ic_data_array with check entries: classes and target functions. |
| 1417 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); | 1420 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); |
| 1418 // R6: points directly to the first ic data array element. | 1421 // R6: points directly to the first ic data array element. |
| 1419 | 1422 |
| 1420 // Get the receiver's class ID (first read number of arguments from | 1423 // Get the receiver's class ID (first read number of arguments from |
| 1421 // arguments descriptor array and then access the receiver from the stack). | 1424 // arguments descriptor array and then access the receiver from the stack). |
| 1422 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), kNoPP); | 1425 __ LoadFieldFromOffset(R7, R4, ArgumentsDescriptor::count_offset(), kNoPP); |
| 1423 __ SmiUntag(R7); // Untag so we can use the LSL 3 addressing mode. | 1426 __ SmiUntag(R7); // Untag so we can use the LSL 3 addressing mode. |
| 1424 __ sub(R7, R7, Operand(1)); | 1427 __ sub(R7, R7, Operand(1)); |
| 1425 | 1428 |
| 1426 // R0 <- [SP + (R7 << 3)] | 1429 // R0 <- [SP + (R7 << 3)] |
| 1427 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled)); | 1430 __ ldr(R0, Address(SP, R7, UXTX, Address::Scaled)); |
| 1428 __ LoadTaggedClassIdMayBeSmi(R0, R0); | 1431 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
| 1429 | 1432 |
| 1430 // R7: argument_count - 1 (untagged). | 1433 // R7: argument_count - 1 (untagged). |
| 1431 // R0: receiver's class ID (smi). | 1434 // R0: receiver's class ID (smi). |
| 1432 __ ldr(R1, Address(R6)); // First class id (smi) to check. | 1435 __ ldr(R1, Address(R6)); // First class id (smi) to check. |
| 1433 __ b(&test); | 1436 __ b(&test); |
| 1434 | 1437 |
| 1438 __ Comment("ICData loop"); |
| 1435 __ Bind(&loop); | 1439 __ Bind(&loop); |
| 1436 for (int i = 0; i < num_args; i++) { | 1440 for (int i = 0; i < num_args; i++) { |
| 1437 if (i > 0) { | 1441 if (i > 0) { |
| 1438 // If not the first, load the next argument's class ID. | 1442 // If not the first, load the next argument's class ID. |
| 1439 __ AddImmediate(R0, R7, -i, kNoPP); | 1443 __ AddImmediate(R0, R7, -i, kNoPP); |
| 1440 // R0 <- [SP + (R0 << 3)] | 1444 // R0 <- [SP + (R0 << 3)] |
| 1441 __ ldr(R0, Address(SP, R0, UXTX, Address::Scaled)); | 1445 __ ldr(R0, Address(SP, R0, UXTX, Address::Scaled)); |
| 1442 __ LoadTaggedClassIdMayBeSmi(R0, R0); | 1446 __ LoadTaggedClassIdMayBeSmi(R0, R0); |
| 1443 // R0: next argument class ID (smi). | 1447 // R0: next argument class ID (smi). |
| 1444 __ LoadFromOffset(R1, R6, i * kWordSize, kNoPP); | 1448 __ LoadFromOffset(R1, R6, i * kWordSize, kNoPP); |
| (...skipping 15 matching lines...) Expand all Loading... |
| 1460 } | 1464 } |
| 1461 | 1465 |
| 1462 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1466 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1463 __ AddImmediate(R6, R6, entry_size, kNoPP); // Next entry. | 1467 __ AddImmediate(R6, R6, entry_size, kNoPP); // Next entry. |
| 1464 __ ldr(R1, Address(R6)); // Next class ID. | 1468 __ ldr(R1, Address(R6)); // Next class ID. |
| 1465 | 1469 |
| 1466 __ Bind(&test); | 1470 __ Bind(&test); |
| 1467 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid), kNoPP); // Done? | 1471 __ CompareImmediate(R1, Smi::RawValue(kIllegalCid), kNoPP); // Done? |
| 1468 __ b(&loop, NE); | 1472 __ b(&loop, NE); |
| 1469 | 1473 |
| 1470 // IC miss. | 1474 __ Comment("IC miss"); |
| 1471 // Compute address of arguments. | 1475 // Compute address of arguments. |
| 1472 // R7: argument_count - 1 (untagged). | 1476 // R7: argument_count - 1 (untagged). |
| 1473 // R7 <- SP + (R7 << 3) | 1477 // R7 <- SP + (R7 << 3) |
| 1474 __ add(R7, SP, Operand(R7, UXTX, 3)); // R7 is Untagged. | 1478 __ add(R7, SP, Operand(R7, UXTX, 3)); // R7 is Untagged. |
| 1475 // R7: address of receiver. | 1479 // R7: address of receiver. |
| 1476 // Create a stub frame as we are pushing some objects on the stack before | 1480 // Create a stub frame as we are pushing some objects on the stack before |
| 1477 // calling into the runtime. | 1481 // calling into the runtime. |
| 1478 __ EnterStubFrame(); | 1482 __ EnterStubFrame(); |
| 1479 // Preserve IC data object and arguments descriptor array and | 1483 // Preserve IC data object and arguments descriptor array and |
| 1480 // setup space on stack for result (target code object). | 1484 // setup space on stack for result (target code object). |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1495 // Pop returned function object into R0. | 1499 // Pop returned function object into R0. |
| 1496 // Restore arguments descriptor array and IC data array. | 1500 // Restore arguments descriptor array and IC data array. |
| 1497 __ Pop(R0); // Pop returned function object into R0. | 1501 __ Pop(R0); // Pop returned function object into R0. |
| 1498 __ Pop(R5); // Restore IC Data. | 1502 __ Pop(R5); // Restore IC Data. |
| 1499 __ Pop(R4); // Restore arguments descriptor array. | 1503 __ Pop(R4); // Restore arguments descriptor array. |
| 1500 __ LeaveStubFrame(); | 1504 __ LeaveStubFrame(); |
| 1501 Label call_target_function; | 1505 Label call_target_function; |
| 1502 __ b(&call_target_function); | 1506 __ b(&call_target_function); |
| 1503 | 1507 |
| 1504 __ Bind(&found); | 1508 __ Bind(&found); |
| 1509 __ Comment("Update caller's counter"); |
| 1505 // R6: pointer to an IC data check group. | 1510 // R6: pointer to an IC data check group. |
| 1506 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1511 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1507 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1512 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1508 __ LoadFromOffset(R0, R6, target_offset, kNoPP); | 1513 __ LoadFromOffset(R0, R6, target_offset, kNoPP); |
| 1509 | 1514 |
| 1510 // Update counter. | 1515 // Update counter. |
| 1511 __ LoadFromOffset(R1, R6, count_offset, kNoPP); | 1516 __ LoadFromOffset(R1, R6, count_offset, kNoPP); |
| 1512 __ adds(R1, R1, Operand(Smi::RawValue(1))); | 1517 __ adds(R1, R1, Operand(Smi::RawValue(1))); |
| 1513 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP); | 1518 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP); |
| 1514 __ csel(R1, R2, R1, VS); // Overflow. | 1519 __ csel(R1, R2, R1, VS); // Overflow. |
| 1515 __ StoreToOffset(R1, R6, count_offset, kNoPP); | 1520 __ StoreToOffset(R1, R6, count_offset, kNoPP); |
| 1516 | 1521 |
| 1522 __ Comment("Call target"); |
| 1517 __ Bind(&call_target_function); | 1523 __ Bind(&call_target_function); |
| 1518 // R0: target function. | 1524 // R0: target function. |
| 1519 __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP); | 1525 __ LoadFieldFromOffset(R2, R0, Function::instructions_offset(), kNoPP); |
| 1520 __ AddImmediate( | 1526 __ AddImmediate( |
| 1521 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); | 1527 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); |
| 1522 if (range_collection_mode == kCollectRanges) { | 1528 if (range_collection_mode == kCollectRanges) { |
| 1523 __ ldr(R1, Address(SP, 0 * kWordSize)); | 1529 __ ldr(R1, Address(SP, 0 * kWordSize)); |
| 1524 if (num_args == 2) { | 1530 if (num_args == 2) { |
| 1525 __ ldr(R3, Address(SP, 1 * kWordSize)); | 1531 __ ldr(R3, Address(SP, 1 * kWordSize)); |
| 1526 } | 1532 } |
| (...skipping 563 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2090 const Register right = R0; | 2096 const Register right = R0; |
| 2091 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); | 2097 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); |
| 2092 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); | 2098 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); |
| 2093 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); | 2099 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); |
| 2094 __ ret(); | 2100 __ ret(); |
| 2095 } | 2101 } |
| 2096 | 2102 |
| 2097 } // namespace dart | 2103 } // namespace dart |
| 2098 | 2104 |
| 2099 #endif // defined TARGET_ARCH_ARM64 | 2105 #endif // defined TARGET_ARCH_ARM64 |
| OLD | NEW |