Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(1092)

Side by Side Diff: runtime/vm/stub_code_mips.cc

Issue 436643002: Faster IC stubs by specializing them for Binary Smi operations (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 6 years, 4 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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 1354 matching lines...) Expand 10 before | Expand all | Expand 10 after
1365 Register ic_reg = S5; 1365 Register ic_reg = S5;
1366 Register func_reg = temp_reg; 1366 Register func_reg = temp_reg;
1367 ASSERT(temp_reg == T0); 1367 ASSERT(temp_reg == T0);
1368 __ lw(func_reg, FieldAddress(ic_reg, ICData::owner_offset())); 1368 __ lw(func_reg, FieldAddress(ic_reg, ICData::owner_offset()));
1369 __ lw(T1, FieldAddress(func_reg, Function::usage_counter_offset())); 1369 __ lw(T1, FieldAddress(func_reg, Function::usage_counter_offset()));
1370 __ addiu(T1, T1, Immediate(1)); 1370 __ addiu(T1, T1, Immediate(1));
1371 __ sw(T1, FieldAddress(func_reg, Function::usage_counter_offset())); 1371 __ sw(T1, FieldAddress(func_reg, Function::usage_counter_offset()));
1372 } 1372 }
1373 1373
1374 1374
1375 // Note: S5 must be preserved.
1376 // Attempt a quick Smi operation for known operations ('kind'). The ICData
1377 // must have been primed with a Smi/Smi check that will be used for counting
1378 // the invocations.
1379 static void EmitFastSmiOp(Assembler* assembler,
1380 Token::Kind kind,
1381 intptr_t num_args,
1382 Label* not_smi_or_overflow) {
1383 ASSERT(num_args == 2);
1384 __ lw(T0, Address(SP, 0 * kWordSize)); // Left.
1385 __ lw(T1, Address(SP, 1 * kWordSize)); // Right.
1386 __ or_(CMPRES1, T0, T1);
1387 __ andi(CMPRES1, CMPRES1, Immediate(kSmiTagMask));
1388 __ bne(CMPRES1, ZR, not_smi_or_overflow);
1389 switch (kind) {
1390 case Token::kADD: {
1391 __ AdduDetectOverflow(V0, T1, T0, CMPRES1); // Add.
1392 __ bltz(CMPRES1, not_smi_or_overflow); // Fall through on overflow.
1393 break;
1394 }
1395 case Token::kSUB: {
1396 __ SubuDetectOverflow(V0, T1, T0, CMPRES1); // Subtract.
1397 __ bltz(CMPRES1, not_smi_or_overflow); // Fall through on overflow.
1398 break;
1399 }
1400 case Token::kEQ: {
1401 Label true_label, done;
1402 __ beq(T1, T0, &true_label);
1403 __ LoadObject(V0, Bool::False());
1404 __ b(&done);
1405 __ Bind(&true_label);
1406 __ LoadObject(V0, Bool::True());
1407 __ Bind(&done);
1408 break;
1409 }
1410 default: UNIMPLEMENTED();
1411 }
1412 // S5: IC data object (preserved).
1413 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset()));
1414 // T0: ic_data_array with check entries: classes and target functions.
1415 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag);
1416 // T0: points directly to the first ic data array element.
1417 #if defined(DEBUG)
1418 // Check that first entry is for Smi/Smi.
1419 Label error, ok;
1420 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid));
1421 __ lw(T4, Address(T0));
1422 __ BranchNotEqual(T4, imm_smi_cid, &error);
1423 __ lw(T4, Address(T0, kWordSize));
1424 __ BranchEqual(T4, imm_smi_cid, &ok);
1425 __ Bind(&error);
1426 __ Stop("Incorrect IC data");
1427 __ Bind(&ok);
1428 #endif
1429 // Update counter.
1430 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1431 __ lw(T4, Address(T0, count_offset));
1432 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6);
1433 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow.
1434 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue));
1435 __ movz(T4, T7, CMPRES1);
1436 __ sw(T4, Address(T0, count_offset));
1437
1438 __ Ret();
1439 }
1440
1441
1375 // Generate inline cache check for 'num_args'. 1442 // Generate inline cache check for 'num_args'.
1376 // RA: return address 1443 // RA: return address
1377 // S5: Inline cache data object. 1444 // S5: Inline cache data object.
1378 // Control flow: 1445 // Control flow:
1379 // - If receiver is null -> jump to IC miss. 1446 // - If receiver is null -> jump to IC miss.
1380 // - If receiver is Smi -> load Smi class. 1447 // - If receiver is Smi -> load Smi class.
1381 // - If receiver is not-Smi -> load receiver's class. 1448 // - If receiver is not-Smi -> load receiver's class.
1382 // - Check if 'num_args' (including receiver) match any IC data group. 1449 // - Check if 'num_args' (including receiver) match any IC data group.
1383 // - Match found -> jump to target. 1450 // - Match found -> jump to target.
1384 // - Match not found -> jump to IC miss. 1451 // - Match not found -> jump to IC miss.
1385 void StubCode::GenerateNArgsCheckInlineCacheStub( 1452 void StubCode::GenerateNArgsCheckInlineCacheStub(
1386 Assembler* assembler, 1453 Assembler* assembler,
1387 intptr_t num_args, 1454 intptr_t num_args,
1388 const RuntimeEntry& handle_ic_miss) { 1455 const RuntimeEntry& handle_ic_miss,
1456 Token::Kind kind) {
1389 __ TraceSimMsg("NArgsCheckInlineCacheStub"); 1457 __ TraceSimMsg("NArgsCheckInlineCacheStub");
1390 ASSERT(num_args > 0); 1458 ASSERT(num_args > 0);
1391 #if defined(DEBUG) 1459 #if defined(DEBUG)
1392 { Label ok; 1460 { Label ok;
1393 // Check that the IC data array has NumArgsTested() == num_args. 1461 // Check that the IC data array has NumArgsTested() == num_args.
1394 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1462 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1395 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); 1463 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset()));
1396 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1464 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1397 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); 1465 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask()));
1398 __ BranchEqual(T0, num_args, &ok); 1466 __ BranchEqual(T0, num_args, &ok);
1399 __ Stop("Incorrect stub for IC data"); 1467 __ Stop("Incorrect stub for IC data");
1400 __ Bind(&ok); 1468 __ Bind(&ok);
1401 } 1469 }
1402 #endif // DEBUG 1470 #endif // DEBUG
1403 1471
1404 1472
1405 Label stepping, done_stepping; 1473 Label stepping, done_stepping;
1406 // Check single stepping. 1474 // Check single stepping.
1407 __ lw(T0, FieldAddress(CTX, Context::isolate_offset())); 1475 __ lw(T0, FieldAddress(CTX, Context::isolate_offset()));
1408 __ lbu(T0, Address(T0, Isolate::single_step_offset())); 1476 __ lbu(T0, Address(T0, Isolate::single_step_offset()));
1409 __ BranchNotEqual(T0, 0, &stepping); 1477 __ BranchNotEqual(T0, 0, &stepping);
1410 __ Bind(&done_stepping); 1478 __ Bind(&done_stepping);
1411 1479
1480 if (kind != Token::kILLEGAL) {
1481 Label not_smi_or_overflow;
1482 EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
1483 __ Bind(&not_smi_or_overflow);
1484 }
1485
1412 // Load argument descriptor into S4. 1486 // Load argument descriptor into S4.
1413 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); 1487 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
1414 // Preserve return address, since RA is needed for subroutine call. 1488 // Preserve return address, since RA is needed for subroutine call.
1415 __ mov(T2, RA); 1489 __ mov(T2, RA);
1416 // Loop that checks if there is an IC data match. 1490 // Loop that checks if there is an IC data match.
1417 Label loop, update, test, found; 1491 Label loop, update, test, found;
1418 // S5: IC data object (preserved). 1492 // S5: IC data object (preserved).
1419 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); 1493 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset()));
1420 // T0: ic_data_array with check entries: classes and target functions. 1494 // T0: ic_data_array with check entries: classes and target functions.
1421 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); 1495 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag);
(...skipping 140 matching lines...) Expand 10 before | Expand all | Expand 10 after
1562 // RA: Return address. 1636 // RA: Return address.
1563 // S5: Inline cache data object. 1637 // S5: Inline cache data object.
1564 // Inline cache data object structure: 1638 // Inline cache data object structure:
1565 // 0: function-name 1639 // 0: function-name
1566 // 1: N, number of arguments checked. 1640 // 1: N, number of arguments checked.
1567 // 2 .. (length - 1): group of checks, each check containing: 1641 // 2 .. (length - 1): group of checks, each check containing:
1568 // - N classes. 1642 // - N classes.
1569 // - 1 target function. 1643 // - 1 target function.
1570 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1644 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1571 GenerateUsageCounterIncrement(assembler, T0); 1645 GenerateUsageCounterIncrement(assembler, T0);
1572 GenerateNArgsCheckInlineCacheStub( 1646 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1573 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); 1647 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1574 } 1648 }
1575 1649
1576 1650
1577 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1651 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1578 GenerateUsageCounterIncrement(assembler, T0); 1652 GenerateUsageCounterIncrement(assembler, T0);
1579 GenerateNArgsCheckInlineCacheStub( 1653 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1580 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); 1654 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1581 } 1655 }
1582 1656
1583 1657
1584 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { 1658 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) {
1585 GenerateUsageCounterIncrement(assembler, T0); 1659 GenerateUsageCounterIncrement(assembler, T0);
1586 GenerateNArgsCheckInlineCacheStub( 1660 GenerateNArgsCheckInlineCacheStub(assembler, 3,
1587 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); 1661 kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL);
1662 }
1663
1664
1665 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
1666 GenerateUsageCounterIncrement(assembler, T0);
1667 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1668 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
1669 }
1670
1671
1672 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
1673 GenerateUsageCounterIncrement(assembler, T0);
1674 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1675 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
1676 }
1677
1678
1679 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
1680 GenerateUsageCounterIncrement(assembler, T0);
1681 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1682 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
1588 } 1683 }
1589 1684
1590 1685
1591 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( 1686 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
1592 Assembler* assembler) { 1687 Assembler* assembler) {
1593 GenerateOptimizedUsageCounterIncrement(assembler); 1688 GenerateOptimizedUsageCounterIncrement(assembler);
1594 GenerateNArgsCheckInlineCacheStub( 1689 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1595 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); 1690 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1596 } 1691 }
1597 1692
1598 1693
1599 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( 1694 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
1600 Assembler* assembler) { 1695 Assembler* assembler) {
1601 GenerateOptimizedUsageCounterIncrement(assembler); 1696 GenerateOptimizedUsageCounterIncrement(assembler);
1602 GenerateNArgsCheckInlineCacheStub( 1697 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1603 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); 1698 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1604 } 1699 }
1605 1700
1606 1701
1607 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub( 1702 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub(
1608 Assembler* assembler) { 1703 Assembler* assembler) {
1609 GenerateOptimizedUsageCounterIncrement(assembler); 1704 GenerateOptimizedUsageCounterIncrement(assembler);
1610 GenerateNArgsCheckInlineCacheStub( 1705 GenerateNArgsCheckInlineCacheStub(assembler, 3,
1611 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); 1706 kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL);
1612 } 1707 }
1613 1708
1614 1709
1615 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) { 1710 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) {
1616 GenerateNArgsCheckInlineCacheStub( 1711 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1617 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); 1712 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1618 } 1713 }
1619 1714
1620 1715
1621 // Intermediary stub between a static call and its target. ICData contains 1716 // Intermediary stub between a static call and its target. ICData contains
1622 // the target function and the call count. 1717 // the target function and the call count.
1623 // S5: ICData 1718 // S5: ICData
1624 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1719 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1625 GenerateUsageCounterIncrement(assembler, T0); 1720 GenerateUsageCounterIncrement(assembler, T0);
1626 __ TraceSimMsg("UnoptimizedStaticCallStub"); 1721 __ TraceSimMsg("UnoptimizedStaticCallStub");
1627 #if defined(DEBUG) 1722 #if defined(DEBUG)
(...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after
1682 __ lw(S5, Address(SP, 1 * kWordSize)); 1777 __ lw(S5, Address(SP, 1 * kWordSize));
1683 __ addiu(SP, SP, Immediate(2 * kWordSize)); 1778 __ addiu(SP, SP, Immediate(2 * kWordSize));
1684 __ LeaveStubFrame(); 1779 __ LeaveStubFrame();
1685 __ b(&done_stepping); 1780 __ b(&done_stepping);
1686 } 1781 }
1687 1782
1688 1783
1689 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { 1784 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) {
1690 GenerateUsageCounterIncrement(assembler, T0); 1785 GenerateUsageCounterIncrement(assembler, T0);
1691 GenerateNArgsCheckInlineCacheStub( 1786 GenerateNArgsCheckInlineCacheStub(
1692 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry); 1787 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1693 } 1788 }
1694 1789
1695 1790
1696 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1791 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1697 GenerateUsageCounterIncrement(assembler, T0); 1792 GenerateUsageCounterIncrement(assembler, T0);
1698 GenerateNArgsCheckInlineCacheStub( 1793 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1699 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); 1794 kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1700 } 1795 }
1701 1796
1702 1797
1703 // Stub for compiling a function and jumping to the compiled code. 1798 // Stub for compiling a function and jumping to the compiled code.
1704 // S5: IC-Data (for methods). 1799 // S5: IC-Data (for methods).
1705 // S4: Arguments descriptor. 1800 // S4: Arguments descriptor.
1706 // T0: Function. 1801 // T0: Function.
1707 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { 1802 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
1708 __ EnterStubFrame(); 1803 __ EnterStubFrame();
1709 __ addiu(SP, SP, Immediate(-3 * kWordSize)); 1804 __ addiu(SP, SP, Immediate(-3 * kWordSize));
(...skipping 403 matching lines...) Expand 10 before | Expand all | Expand 10 after
2113 const Register right = T0; 2208 const Register right = T0;
2114 __ lw(left, Address(SP, 1 * kWordSize)); 2209 __ lw(left, Address(SP, 1 * kWordSize));
2115 __ lw(right, Address(SP, 0 * kWordSize)); 2210 __ lw(right, Address(SP, 0 * kWordSize));
2116 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2); 2211 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp1, temp2);
2117 __ Ret(); 2212 __ Ret();
2118 } 2213 }
2119 2214
2120 } // namespace dart 2215 } // namespace dart
2121 2216
2122 #endif // defined TARGET_ARCH_MIPS 2217 #endif // defined TARGET_ARCH_MIPS
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698