| 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 1333 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1344 | 1344 |
| 1345 | 1345 |
| 1346 // Note: S5 must be preserved. | 1346 // Note: S5 must be preserved. |
| 1347 // Attempt a quick Smi operation for known operations ('kind'). The ICData | 1347 // Attempt a quick Smi operation for known operations ('kind'). The ICData |
| 1348 // must have been primed with a Smi/Smi check that will be used for counting | 1348 // must have been primed with a Smi/Smi check that will be used for counting |
| 1349 // the invocations. | 1349 // the invocations. |
| 1350 static void EmitFastSmiOp(Assembler* assembler, | 1350 static void EmitFastSmiOp(Assembler* assembler, |
| 1351 Token::Kind kind, | 1351 Token::Kind kind, |
| 1352 intptr_t num_args, | 1352 intptr_t num_args, |
| 1353 Label* not_smi_or_overflow) { | 1353 Label* not_smi_or_overflow) { |
| 1354 __ Comment("Fast Smi op"); |
| 1354 ASSERT(num_args == 2); | 1355 ASSERT(num_args == 2); |
| 1355 __ lw(T0, Address(SP, 0 * kWordSize)); // Left. | 1356 __ lw(T0, Address(SP, 0 * kWordSize)); // Left. |
| 1356 __ lw(T1, Address(SP, 1 * kWordSize)); // Right. | 1357 __ lw(T1, Address(SP, 1 * kWordSize)); // Right. |
| 1357 __ or_(CMPRES1, T0, T1); | 1358 __ or_(CMPRES1, T0, T1); |
| 1358 __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask)); | 1359 __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask)); |
| 1359 __ bne(CMPRES1, ZR, not_smi_or_overflow); | 1360 __ bne(CMPRES1, ZR, not_smi_or_overflow); |
| 1360 switch (kind) { | 1361 switch (kind) { |
| 1361 case Token::kADD: { | 1362 case Token::kADD: { |
| 1362 __ AdduDetectOverflow(V0, T1, T0, CMPRES1); // Add. | 1363 __ AdduDetectOverflow(V0, T1, T0, CMPRES1); // Add. |
| 1363 __ bltz(CMPRES1, not_smi_or_overflow); // Fall through on overflow. | 1364 __ bltz(CMPRES1, not_smi_or_overflow); // Fall through on overflow. |
| (...skipping 71 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1435 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); | 1436 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); |
| 1436 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1437 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
| 1437 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); | 1438 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); |
| 1438 __ BranchEqual(T0, Immediate(num_args), &ok); | 1439 __ BranchEqual(T0, Immediate(num_args), &ok); |
| 1439 __ Stop("Incorrect stub for IC data"); | 1440 __ Stop("Incorrect stub for IC data"); |
| 1440 __ Bind(&ok); | 1441 __ Bind(&ok); |
| 1441 } | 1442 } |
| 1442 #endif // DEBUG | 1443 #endif // DEBUG |
| 1443 | 1444 |
| 1444 | 1445 |
| 1445 // Check single stepping. | 1446 __ Comment("Check single stepping"); |
| 1446 Label stepping, done_stepping; | 1447 Label stepping, done_stepping; |
| 1447 __ LoadIsolate(T0); | 1448 __ LoadIsolate(T0); |
| 1448 __ lbu(T0, Address(T0, Isolate::single_step_offset())); | 1449 __ lbu(T0, Address(T0, Isolate::single_step_offset())); |
| 1449 __ BranchNotEqual(T0, Immediate(0), &stepping); | 1450 __ BranchNotEqual(T0, Immediate(0), &stepping); |
| 1450 __ Bind(&done_stepping); | 1451 __ Bind(&done_stepping); |
| 1451 | 1452 |
| 1453 __ Comment("Range feedback collection"); |
| 1452 Label not_smi_or_overflow; | 1454 Label not_smi_or_overflow; |
| 1453 if (range_collection_mode == kCollectRanges) { | 1455 if (range_collection_mode == kCollectRanges) { |
| 1454 ASSERT((num_args == 1) || (num_args == 2)); | 1456 ASSERT((num_args == 1) || (num_args == 2)); |
| 1455 if (num_args == 2) { | 1457 if (num_args == 2) { |
| 1456 __ lw(T0, Address(SP, 1 * kWordSize)); | 1458 __ lw(T0, Address(SP, 1 * kWordSize)); |
| 1457 __ UpdateRangeFeedback(T0, 0, S5, T1, ¬_smi_or_overflow); | 1459 __ UpdateRangeFeedback(T0, 0, S5, T1, ¬_smi_or_overflow); |
| 1458 } | 1460 } |
| 1459 | 1461 |
| 1460 __ lw(T0, Address(SP, 0 * kWordSize)); | 1462 __ lw(T0, Address(SP, 0 * kWordSize)); |
| 1461 __ UpdateRangeFeedback(T0, num_args - 1, S5, T1, ¬_smi_or_overflow); | 1463 __ UpdateRangeFeedback(T0, num_args - 1, S5, T1, ¬_smi_or_overflow); |
| 1462 } | 1464 } |
| 1463 if (kind != Token::kILLEGAL) { | 1465 if (kind != Token::kILLEGAL) { |
| 1464 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1466 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
| 1465 } | 1467 } |
| 1466 __ Bind(¬_smi_or_overflow); | 1468 __ Bind(¬_smi_or_overflow); |
| 1467 | 1469 |
| 1470 __ Comment("Extract ICData initial values and receiver cid"); |
| 1468 // Load argument descriptor into S4. | 1471 // Load argument descriptor into S4. |
| 1469 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); | 1472 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); |
| 1470 // Preserve return address, since RA is needed for subroutine call. | 1473 // Preserve return address, since RA is needed for subroutine call. |
| 1471 __ mov(T2, RA); | 1474 __ mov(T2, RA); |
| 1472 // Loop that checks if there is an IC data match. | 1475 // Loop that checks if there is an IC data match. |
| 1473 Label loop, update, test, found; | 1476 Label loop, update, test, found; |
| 1474 // S5: IC data object (preserved). | 1477 // S5: IC data object (preserved). |
| 1475 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); | 1478 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); |
| 1476 // T0: ic_data_array with check entries: classes and target functions. | 1479 // T0: ic_data_array with check entries: classes and target functions. |
| 1477 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); | 1480 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); |
| 1478 // T0: points directly to the first ic data array element. | 1481 // T0: points directly to the first ic data array element. |
| 1479 | 1482 |
| 1480 // Get the receiver's class ID (first read number of arguments from | 1483 // Get the receiver's class ID (first read number of arguments from |
| 1481 // arguments descriptor array and then access the receiver from the stack). | 1484 // arguments descriptor array and then access the receiver from the stack). |
| 1482 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); | 1485 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); |
| 1483 __ LoadImmediate(TMP, Smi::RawValue(1)); | 1486 __ LoadImmediate(TMP, Smi::RawValue(1)); |
| 1484 __ subu(T1, T1, TMP); | 1487 __ subu(T1, T1, TMP); |
| 1485 __ sll(T3, T1, 1); // T1 (argument_count - 1) is smi. | 1488 __ sll(T3, T1, 1); // T1 (argument_count - 1) is smi. |
| 1486 __ addu(T3, T3, SP); | 1489 __ addu(T3, T3, SP); |
| 1487 __ lw(T3, Address(T3)); | 1490 __ lw(T3, Address(T3)); |
| 1488 __ LoadTaggedClassIdMayBeSmi(T3, T3); | 1491 __ LoadTaggedClassIdMayBeSmi(T3, T3); |
| 1489 | 1492 |
| 1490 // T1: argument_count - 1 (smi). | 1493 // T1: argument_count - 1 (smi). |
| 1491 // T3: receiver's class ID (smi). | 1494 // T3: receiver's class ID (smi). |
| 1492 __ b(&test); | 1495 __ b(&test); |
| 1493 __ delay_slot()->lw(T4, Address(T0)); // First class id (smi) to check. | 1496 __ delay_slot()->lw(T4, Address(T0)); // First class id (smi) to check. |
| 1494 | 1497 |
| 1498 __ Comment("ICData loop"); |
| 1495 __ Bind(&loop); | 1499 __ Bind(&loop); |
| 1496 for (int i = 0; i < num_args; i++) { | 1500 for (int i = 0; i < num_args; i++) { |
| 1497 if (i > 0) { | 1501 if (i > 0) { |
| 1498 // If not the first, load the next argument's class ID. | 1502 // If not the first, load the next argument's class ID. |
| 1499 __ LoadImmediate(T3, Smi::RawValue(-i)); | 1503 __ LoadImmediate(T3, Smi::RawValue(-i)); |
| 1500 __ addu(T3, T1, T3); | 1504 __ addu(T3, T1, T3); |
| 1501 __ sll(T3, T3, 1); | 1505 __ sll(T3, T3, 1); |
| 1502 __ addu(T3, SP, T3); | 1506 __ addu(T3, SP, T3); |
| 1503 __ lw(T3, Address(T3)); | 1507 __ lw(T3, Address(T3)); |
| 1504 __ LoadTaggedClassIdMayBeSmi(T3, T3); | 1508 __ LoadTaggedClassIdMayBeSmi(T3, T3); |
| (...skipping 21 matching lines...) Expand all Loading... |
| 1526 __ LoadTaggedClassIdMayBeSmi(T3, T3); | 1530 __ LoadTaggedClassIdMayBeSmi(T3, T3); |
| 1527 } | 1531 } |
| 1528 | 1532 |
| 1529 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; | 1533 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; |
| 1530 __ AddImmediate(T0, entry_size); // Next entry. | 1534 __ AddImmediate(T0, entry_size); // Next entry. |
| 1531 __ lw(T4, Address(T0)); // Next class ID. | 1535 __ lw(T4, Address(T0)); // Next class ID. |
| 1532 | 1536 |
| 1533 __ Bind(&test); | 1537 __ Bind(&test); |
| 1534 __ BranchNotEqual(T4, Immediate(Smi::RawValue(kIllegalCid)), &loop); // Done? | 1538 __ BranchNotEqual(T4, Immediate(Smi::RawValue(kIllegalCid)), &loop); // Done? |
| 1535 | 1539 |
| 1536 // IC miss. | 1540 __ Comment("IC miss"); |
| 1537 // Restore return address. | 1541 // Restore return address. |
| 1538 __ mov(RA, T2); | 1542 __ mov(RA, T2); |
| 1539 | 1543 |
| 1540 // Compute address of arguments (first read number of arguments from | 1544 // Compute address of arguments (first read number of arguments from |
| 1541 // arguments descriptor array and then compute address on the stack). | 1545 // arguments descriptor array and then compute address on the stack). |
| 1542 // T1: argument_count - 1 (smi). | 1546 // T1: argument_count - 1 (smi). |
| 1543 __ sll(T1, T1, 1); // T1 is Smi. | 1547 __ sll(T1, T1, 1); // T1 is Smi. |
| 1544 __ addu(T1, SP, T1); | 1548 __ addu(T1, SP, T1); |
| 1545 // T1: address of receiver. | 1549 // T1: address of receiver. |
| 1546 // Create a stub frame as we are pushing some objects on the stack before | 1550 // Create a stub frame as we are pushing some objects on the stack before |
| (...skipping 23 matching lines...) Expand all Loading... |
| 1570 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize)); | 1574 __ lw(S5, Address(SP, (num_slots - 1) * kWordSize)); |
| 1571 // Remove the call arguments pushed earlier, including the IC data object | 1575 // Remove the call arguments pushed earlier, including the IC data object |
| 1572 // and the arguments descriptor array. | 1576 // and the arguments descriptor array. |
| 1573 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); | 1577 __ addiu(SP, SP, Immediate(num_slots * kWordSize)); |
| 1574 __ LeaveStubFrame(); | 1578 __ LeaveStubFrame(); |
| 1575 | 1579 |
| 1576 Label call_target_function; | 1580 Label call_target_function; |
| 1577 __ b(&call_target_function); | 1581 __ b(&call_target_function); |
| 1578 | 1582 |
| 1579 __ Bind(&found); | 1583 __ Bind(&found); |
| 1584 __ Comment("Update caller's counter"); |
| 1580 // T0: Pointer to an IC data check group. | 1585 // T0: Pointer to an IC data check group. |
| 1581 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; | 1586 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; |
| 1582 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; | 1587 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; |
| 1583 __ lw(T3, Address(T0, target_offset)); | 1588 __ lw(T3, Address(T0, target_offset)); |
| 1584 | 1589 |
| 1585 // Update counter. | 1590 // Update counter. |
| 1586 __ lw(T4, Address(T0, count_offset)); | 1591 __ lw(T4, Address(T0, count_offset)); |
| 1587 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); | 1592 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); |
| 1588 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. | 1593 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow. |
| 1589 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); | 1594 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue)); |
| 1590 __ movz(T4, T7, CMPRES1); | 1595 __ movz(T4, T7, CMPRES1); |
| 1591 __ sw(T4, Address(T0, count_offset)); | 1596 __ sw(T4, Address(T0, count_offset)); |
| 1592 | 1597 |
| 1598 __ Comment("Call target"); |
| 1593 __ Bind(&call_target_function); | 1599 __ Bind(&call_target_function); |
| 1594 // T0 <- T3: Target function. | 1600 // T0 <- T3: Target function. |
| 1595 __ mov(T0, T3); | 1601 __ mov(T0, T3); |
| 1596 Label is_compiled; | 1602 Label is_compiled; |
| 1597 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); | 1603 __ lw(T4, FieldAddress(T0, Function::instructions_offset())); |
| 1598 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); | 1604 __ AddImmediate(T4, Instructions::HeaderSize() - kHeapObjectTag); |
| 1599 if (range_collection_mode == kCollectRanges) { | 1605 if (range_collection_mode == kCollectRanges) { |
| 1600 const intptr_t frame_size = num_args + 2; | 1606 const intptr_t frame_size = num_args + 2; |
| 1601 __ lw(T3, Address(SP, 0 * kWordSize)); | 1607 __ lw(T3, Address(SP, 0 * kWordSize)); |
| 1602 if (num_args == 2) { | 1608 if (num_args == 2) { |
| (...skipping 638 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2241 const Register right = T0; | 2247 const Register right = T0; |
| 2242 __ lw(left, Address(SP, 1 * kWordSize)); | 2248 __ lw(left, Address(SP, 1 * kWordSize)); |
| 2243 __ lw(right, Address(SP, 0 * kWordSize)); | 2249 __ lw(right, Address(SP, 0 * kWordSize)); |
| 2244 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); | 2250 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); |
| 2245 __ Ret(); | 2251 __ Ret(); |
| 2246 } | 2252 } |
| 2247 | 2253 |
| 2248 } // namespace dart | 2254 } // namespace dart |
| 2249 | 2255 |
| 2250 #endif // defined TARGET_ARCH_MIPS | 2256 #endif // defined TARGET_ARCH_MIPS |
| OLD | NEW |