| 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_MIPS) | 6 #if defined(TARGET_ARCH_MIPS) |
| 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 1427 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1438 __ addiu(SP, SP, Immediate(2 * kWordSize)); | 1438 __ addiu(SP, SP, Immediate(2 * kWordSize)); |
| 1439 __ LeaveStubFrame(); | 1439 __ LeaveStubFrame(); |
| 1440 __ Bind(¬_stepping); | 1440 __ Bind(¬_stepping); |
| 1441 } | 1441 } |
| 1442 | 1442 |
| 1443 // Load argument descriptor into S4. | 1443 // Load argument descriptor into S4. |
| 1444 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | 1444 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
| 1445 // Preserve return address, since RA is needed for subroutine call. | 1445 // Preserve return address, since RA is needed for subroutine call. |
| 1446 __ mov(T2, RA); | 1446 __ mov(T2, RA); |
| 1447 // Loop that checks if there is an IC data match. | 1447 // Loop that checks if there is an IC data match. |
| 1448 Label loop, update, test, found, get_class_id_as_smi; | 1448 Label loop, update, test, found; |
| 1449 // S5: IC data object (preserved). | 1449 // S5: IC data object (preserved). |
| 1450 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1450 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
| 1451 // T0: ic_data_array with check entries: classes and target functions. | 1451 // T0: ic_data_array with check entries: classes and target functions. |
| 1452 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1452 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
| 1453 // T0: points directly to the first ic data array element. | 1453 // T0: points directly to the first ic data array element. |
| 1454 | 1454 |
| 1455 // Get the receiver's class ID (first read number of arguments from | 1455 // Get the receiver's class ID (first read number of arguments from |
| 1456 // arguments descriptor array and then access the receiver from the stack). | 1456 // arguments descriptor array and then access the receiver from the stack). |
| 1457 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | 1457 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); |
| 1458 __ LoadImmediate(TMP, Smi::RawValue(1)); | 1458 __ LoadImmediate(TMP, Smi::RawValue(1)); |
| 1459 __ subu(T1, T1, TMP); | 1459 __ subu(T1, T1, TMP); |
| 1460 __ sll(T3, T1, 1); // T1 (argument_count - 1) is smi. | 1460 __ sll(T3, T1, 1); // T1 (argument_count - 1) is smi. |
| 1461 __ addu(T3, T3, SP); | 1461 __ addu(T3, T3, SP); |
| 1462 __ bal(&get_class_id_as_smi); | 1462 __ lw(T3, Address(T3)); |
| 1463 __ delay_slot()->lw(T3, Address(T3)); | 1463 __ LoadTaggedClassIdMayBeSmi(T3, T3); |
| 1464 |
| 1464 // T1: argument_count - 1 (smi). | 1465 // T1: argument_count - 1 (smi). |
| 1465 // T3: receiver's class ID (smi). | 1466 // T3: receiver's class ID (smi). |
| 1466 __ b(&test); | 1467 __ b(&test); |
| 1467 __ delay_slot()->lw(T4, Address(T0)); // First class id (smi) to check. | 1468 __ delay_slot()->lw(T4, Address(T0)); // First class id (smi) to check. |
| 1468 | 1469 |
| 1469 __ Bind(&loop); | 1470 __ Bind(&loop); |
| 1470 for (int i = 0; i < num_args; i++) { | 1471 for (int i = 0; i < num_args; i++) { |
| 1471 if (i > 0) { | 1472 if (i > 0) { |
| 1472 // If not the first, load the next argument's class ID. | 1473 // If not the first, load the next argument's class ID. |
| 1473 __ LoadImmediate(T3, Smi::RawValue(-i)); | 1474 __ LoadImmediate(T3, Smi::RawValue(-i)); |
| 1474 __ addu(T3, T1, T3); | 1475 __ addu(T3, T1, T3); |
| 1475 __ sll(T3, T3, 1); | 1476 __ sll(T3, T3, 1); |
| 1476 __ addu(T3, SP, T3); | 1477 __ addu(T3, SP, T3); |
| 1477 __ bal(&get_class_id_as_smi); | 1478 __ lw(T3, Address(T3)); |
| 1478 __ delay_slot()->lw(T3, Address(T3)); | 1479 __ LoadTaggedClassIdMayBeSmi(T3, T3); |
| 1479 // T3: next argument class ID (smi). | 1480 // T3: next argument class ID (smi). |
| 1480 __ lw(T4, Address(T0, i * kWordSize)); | 1481 __ lw(T4, Address(T0, i * kWordSize)); |
| 1481 // T4: next class ID to check (smi). | 1482 // T4: next class ID to check (smi). |
| 1482 } | 1483 } |
| 1483 if (i < (num_args - 1)) { | 1484 if (i < (num_args - 1)) { |
| 1484 __ bne(T3, T4, &update); // Continue. | 1485 __ bne(T3, T4, &update); // Continue. |
| 1485 } else { | 1486 } else { |
| 1486 // Last check, all checks before matched. | 1487 // Last check, all checks before matched. |
| 1487 Label skip; | 1488 Label skip; |
| 1488 __ bne(T3, T4, &skip); | 1489 __ bne(T3, T4, &skip); |
| 1489 __ b(&found); // Break. | 1490 __ b(&found); // Break. |
| 1490 __ delay_slot()->mov(RA, T2); // Restore return address if found. | 1491 __ delay_slot()->mov(RA, T2); // Restore return address if found. |
| 1491 __ Bind(&skip); | 1492 __ Bind(&skip); |
| 1492 } | 1493 } |
| 1493 } | 1494 } |
| 1494 __ Bind(&update); | 1495 __ Bind(&update); |
| 1495 // Reload receiver class ID. It has not been destroyed when num_args == 1. | 1496 // Reload receiver class ID. It has not been destroyed when num_args == 1. |
| 1496 if (num_args > 1) { | 1497 if (num_args > 1) { |
| 1497 __ sll(T3, T1, 1); | 1498 __ sll(T3, T1, 1); |
| 1498 __ addu(T3, T3, SP); | 1499 __ addu(T3, T3, SP); |
| 1499 __ bal(&get_class_id_as_smi); | 1500 __ lw(T3, Address(T3)); |
| 1500 __ delay_slot()->lw(T3, Address(T3)); | 1501 __ LoadTaggedClassIdMayBeSmi(T3, T3); |
| 1501 } | 1502 } |
| 1502 | 1503 |
| 1503 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1504 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1504 __ AddImmediate(T0, entry_size); // Next entry. | 1505 __ AddImmediate(T0, entry_size); // Next entry. |
| 1505 __ lw(T4, Address(T0)); // Next class ID. | 1506 __ lw(T4, Address(T0)); // Next class ID. |
| 1506 | 1507 |
| 1507 __ Bind(&test); | 1508 __ Bind(&test); |
| 1508 __ BranchNotEqual(T4, Smi::RawValue(kIllegalCid), &loop); // Done? | 1509 __ BranchNotEqual(T4, Smi::RawValue(kIllegalCid), &loop); // Done? |
| 1509 | 1510 |
| 1510 // IC miss. | 1511 // IC miss. |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1565 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); | 1566 __ LoadImmediate(T1, Smi::RawValue(Smi::kMaxValue)); |
| 1566 __ sw(T1, Address(T0, count_offset)); | 1567 __ sw(T1, Address(T0, count_offset)); |
| 1567 | 1568 |
| 1568 __ Bind(&call_target_function); | 1569 __ Bind(&call_target_function); |
| 1569 // T0 <- T3: Target function. | 1570 // T0 <- T3: Target function. |
| 1570 __ mov(T0, T3); | 1571 __ mov(T0, T3); |
| 1571 Label is_compiled; | 1572 Label is_compiled; |
| 1572 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); | 1573 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); |
| 1573 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); | 1574 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); |
| 1574 __ jr(T4); | 1575 __ jr(T4); |
| 1575 | |
| 1576 // Instance in T3, return its class-id in T3 as Smi. | |
| 1577 __ Bind(&get_class_id_as_smi); | |
| 1578 Label not_smi; | |
| 1579 // Test if Smi -> load Smi class for comparison. | |
| 1580 __ andi(CMPRES1, T3, Immediate(kSmiTagMask)); | |
| 1581 __ bne(CMPRES1, ZR, ¬_smi); | |
| 1582 __ jr(RA); | |
| 1583 __ delay_slot()->addiu(T3, ZR, Immediate(Smi::RawValue(kSmiCid))); | |
| 1584 | |
| 1585 __ Bind(¬_smi); | |
| 1586 __ LoadClassId(T3, T3); | |
| 1587 __ jr(RA); | |
| 1588 __ delay_slot()->SmiTag(T3); | |
| 1589 } | 1576 } |
| 1590 | 1577 |
| 1591 | 1578 |
| 1592 // Use inline cache data array to invoke the target or continue in inline | 1579 // Use inline cache data array to invoke the target or continue in inline |
| 1593 // cache miss handler. Stub for 1-argument check (receiver class). | 1580 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1594 // RA: Return address. | 1581 // RA: Return address. |
| 1595 // S5: Inline cache data object. | 1582 // S5: Inline cache data object. |
| 1596 // Inline cache data object structure: | 1583 // Inline cache data object structure: |
| 1597 // 0: function-name | 1584 // 0: function-name |
| 1598 // 1: N, number of arguments checked. | 1585 // 1: N, number of arguments checked. |
| (...skipping 493 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2092 const Register right = T0; | 2079 const Register right = T0; |
| 2093 __ lw(left, Address(SP, 1 * kWordSize)); | 2080 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2094 __ lw(right, Address(SP, 0 * kWordSize)); | 2081 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2095 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2082 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2096 __ Ret(); | 2083 __ Ret(); |
| 2097 } | 2084 } |
| 2098 | 2085 |
| 2099 } // namespace dart | 2086 } // namespace dart |
| 2100 | 2087 |
| 2101 #endif // defined TARGET_ARCH_MIPS | 2088 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |