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

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

Issue 2660863002: reland Optimizations to IC stub for unoptimized code performance (Closed)
Patch Set: Toiten up MIPS stub code Created 3 years, 10 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
« no previous file with comments | « runtime/vm/stub_code_ia32.cc ('k') | runtime/vm/stub_code_x64.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1385 matching lines...) Expand 10 before | Expand all | Expand 10 after
1396 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid)); 1396 const int32_t imm_smi_cid = reinterpret_cast<int32_t>(Smi::New(kSmiCid));
1397 __ lw(T4, Address(T0)); 1397 __ lw(T4, Address(T0));
1398 __ BranchNotEqual(T4, Immediate(imm_smi_cid), &error); 1398 __ BranchNotEqual(T4, Immediate(imm_smi_cid), &error);
1399 __ lw(T4, Address(T0, kWordSize)); 1399 __ lw(T4, Address(T0, kWordSize));
1400 __ BranchEqual(T4, Immediate(imm_smi_cid), &ok); 1400 __ BranchEqual(T4, Immediate(imm_smi_cid), &ok);
1401 __ Bind(&error); 1401 __ Bind(&error);
1402 __ Stop("Incorrect IC data"); 1402 __ Stop("Incorrect IC data");
1403 __ Bind(&ok); 1403 __ Bind(&ok);
1404 #endif 1404 #endif
1405 if (FLAG_optimization_counter_threshold >= 0) { 1405 if (FLAG_optimization_counter_threshold >= 0) {
1406 // Update counter. 1406 // Update counter, ignore overflow.
1407 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1407 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1408 __ lw(T4, Address(T0, count_offset)); 1408 __ lw(T4, Address(T0, count_offset));
1409 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); 1409 __ AddImmediate(T4, T4, Smi::RawValue(1));
1410 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow.
1411 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue));
1412 __ movz(T4, T7, CMPRES1);
1413 __ sw(T4, Address(T0, count_offset)); 1410 __ sw(T4, Address(T0, count_offset));
1414 } 1411 }
1415 1412
1416 __ Ret(); 1413 __ Ret();
1417 } 1414 }
1418 1415
1419 1416
1420 // Generate inline cache check for 'num_args'. 1417 // Generate inline cache check for 'num_args'.
1421 // RA: return address 1418 // RA: return address
1422 // S5: Inline cache data object. 1419 // S5: Inline cache data object.
1423 // Control flow: 1420 // Control flow:
1424 // - If receiver is null -> jump to IC miss. 1421 // - If receiver is null -> jump to IC miss.
1425 // - If receiver is Smi -> load Smi class. 1422 // - If receiver is Smi -> load Smi class.
1426 // - If receiver is not-Smi -> load receiver's class. 1423 // - If receiver is not-Smi -> load receiver's class.
1427 // - Check if 'num_args' (including receiver) match any IC data group. 1424 // - Check if 'num_args' (including receiver) match any IC data group.
1428 // - Match found -> jump to target. 1425 // - Match found -> jump to target.
1429 // - Match not found -> jump to IC miss. 1426 // - Match not found -> jump to IC miss.
1430 void StubCode::GenerateNArgsCheckInlineCacheStub( 1427 void StubCode::GenerateNArgsCheckInlineCacheStub(
1431 Assembler* assembler, 1428 Assembler* assembler,
1432 intptr_t num_args, 1429 intptr_t num_args,
1433 const RuntimeEntry& handle_ic_miss, 1430 const RuntimeEntry& handle_ic_miss,
1434 Token::Kind kind, 1431 Token::Kind kind,
1435 bool optimized) { 1432 bool optimized) {
1436 __ Comment("NArgsCheckInlineCacheStub"); 1433 __ Comment("NArgsCheckInlineCacheStub");
1437 ASSERT(num_args > 0); 1434 ASSERT(num_args == 1 || num_args == 2);
1438 #if defined(DEBUG) 1435 #if defined(DEBUG)
1439 { 1436 {
1440 Label ok; 1437 Label ok;
1441 // Check that the IC data array has NumArgsTested() == num_args. 1438 // Check that the IC data array has NumArgsTested() == num_args.
1442 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1439 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1443 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset())); 1440 __ lw(T0, FieldAddress(S5, ICData::state_bits_offset()));
1444 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1441 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1445 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask())); 1442 __ andi(T0, T0, Immediate(ICData::NumArgsTestedMask()));
1446 __ BranchEqual(T0, Immediate(num_args), &ok); 1443 __ BranchEqual(T0, Immediate(num_args), &ok);
1447 __ Stop("Incorrect stub for IC data"); 1444 __ Stop("Incorrect stub for IC data");
(...skipping 16 matching lines...) Expand all
1464 EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow); 1461 EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
1465 } 1462 }
1466 __ Bind(&not_smi_or_overflow); 1463 __ Bind(&not_smi_or_overflow);
1467 1464
1468 __ Comment("Extract ICData initial values and receiver cid"); 1465 __ Comment("Extract ICData initial values and receiver cid");
1469 // Load argument descriptor into S4. 1466 // Load argument descriptor into S4.
1470 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); 1467 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
1471 // Preserve return address, since RA is needed for subroutine call. 1468 // Preserve return address, since RA is needed for subroutine call.
1472 __ mov(T2, RA); 1469 __ mov(T2, RA);
1473 // Loop that checks if there is an IC data match. 1470 // Loop that checks if there is an IC data match.
1474 Label loop, update, test, found; 1471 Label loop, found, miss;
1475 // S5: IC data object (preserved). 1472 // S5: IC data object (preserved).
1476 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); 1473 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset()));
1477 // T0: ic_data_array with check entries: classes and target functions. 1474 // T0: ic_data_array with check entries: classes and target functions.
1478 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); 1475 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag);
1479 // T0: points directly to the first ic data array element. 1476 // T0: points directly to the first ic data array element.
1480 1477
1481 // Get the receiver's class ID (first read number of arguments from 1478 // Get the receiver's class ID (first read number of arguments from
1482 // arguments descriptor array and then access the receiver from the stack). 1479 // arguments descriptor array and then access the receiver from the stack).
1483 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset())); 1480 __ lw(T1, FieldAddress(S4, ArgumentsDescriptor::count_offset()));
1484 __ LoadImmediate(TMP, Smi::RawValue(1)); 1481 __ sll(T5, T1, 1); // T1 (argument_count - 1) is smi.
1485 __ subu(T1, T1, TMP); 1482 __ addu(T5, T5, SP);
1486 __ sll(T3, T1, 1); // T1 (argument_count - 1) is smi. 1483 __ lw(T3, Address(T5, -kWordSize));
1487 __ addu(T3, T3, SP);
1488 __ lw(T3, Address(T3));
1489 __ LoadTaggedClassIdMayBeSmi(T3, T3); 1484 __ LoadTaggedClassIdMayBeSmi(T3, T3);
1490 1485
1491 // T1: argument_count - 1 (smi). 1486 if (num_args == 2) {
1487 __ lw(T5, Address(T5, -2 * kWordSize));
1488 __ LoadTaggedClassIdMayBeSmi(T5, T5);
1489 }
1490
1491 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize;
1492 // T1: argument_count (smi).
1492 // T3: receiver's class ID (smi). 1493 // T3: receiver's class ID (smi).
1493 __ b(&test); 1494 // T5: first argument's class ID (smi).
1494 __ delay_slot()->lw(T4, Address(T0)); // First class id (smi) to check. 1495
1496 // We unroll the generic one that is generated once more than the others.
1497 const bool optimize = kind == Token::kILLEGAL;
1495 1498
1496 __ Comment("ICData loop"); 1499 __ Comment("ICData loop");
1497 __ Bind(&loop); 1500 __ Bind(&loop);
1498 for (int i = 0; i < num_args; i++) { 1501 for (int unroll = optimize ? 4 : 2; unroll >= 0; unroll--) {
1499 if (i > 0) { 1502 __ lw(T4, Address(T0, 0));
1500 // If not the first, load the next argument's class ID. 1503 if (num_args == 1) {
1501 __ LoadImmediate(T3, Smi::RawValue(-i)); 1504 __ beq(T3, T4, &found); // IC hit.
1502 __ addu(T3, T1, T3); 1505 } else {
1503 __ sll(T3, T3, 1); 1506 ASSERT(num_args == 2);
1504 __ addu(T3, SP, T3); 1507 Label update;
1505 __ lw(T3, Address(T3)); 1508 __ bne(T3, T4, &update); // Continue.
1506 __ LoadTaggedClassIdMayBeSmi(T3, T3); 1509 __ lw(T4, Address(T0, kWordSize));
1507 // T3: next argument class ID (smi). 1510 __ beq(T5, T4, &found); // IC hit.
1508 __ lw(T4, Address(T0, i * kWordSize)); 1511 __ Bind(&update);
1509 // T4: next class ID to check (smi).
1510 } 1512 }
1511 if (i < (num_args - 1)) { 1513
1512 __ bne(T3, T4, &update); // Continue. 1514 __ AddImmediate(T0, entry_size); // Next entry.
1515 if (unroll == 0) {
1516 __ BranchNotEqual(T4, Immediate(Smi::RawValue(kIllegalCid)),
1517 &loop); // Done?
1513 } else { 1518 } else {
1514 // Last check, all checks before matched. 1519 __ BranchEqual(T4, Immediate(Smi::RawValue(kIllegalCid)),
1515 Label skip; 1520 &miss); // Done?
1516 __ bne(T3, T4, &skip);
1517 __ b(&found); // Break.
1518 __ delay_slot()->mov(RA, T2); // Restore return address if found.
1519 __ Bind(&skip);
1520 } 1521 }
1521 } 1522 }
1522 __ Bind(&update);
1523 // Reload receiver class ID. It has not been destroyed when num_args == 1.
1524 if (num_args > 1) {
1525 __ sll(T3, T1, 1);
1526 __ addu(T3, T3, SP);
1527 __ lw(T3, Address(T3));
1528 __ LoadTaggedClassIdMayBeSmi(T3, T3);
1529 }
1530 1523
1531 const intptr_t entry_size = ICData::TestEntryLengthFor(num_args) * kWordSize; 1524 __ Bind(&miss);
1532 __ AddImmediate(T0, entry_size); // Next entry.
1533 __ lw(T4, Address(T0)); // Next class ID.
1534
1535 __ Bind(&test);
1536 __ BranchNotEqual(T4, Immediate(Smi::RawValue(kIllegalCid)), &loop); // Done?
1537
1538 __ Comment("IC miss"); 1525 __ Comment("IC miss");
1539 // Restore return address. 1526 // Restore return address.
1540 __ mov(RA, T2); 1527 __ mov(RA, T2);
1541 1528
1542 // Compute address of arguments (first read number of arguments from 1529 // Compute address of arguments (first read number of arguments from
1543 // arguments descriptor array and then compute address on the stack). 1530 // arguments descriptor array and then compute address on the stack).
1544 // T1: argument_count - 1 (smi). 1531 // T1: argument_count (smi).
1532 __ addiu(T1, T1, Immediate(Smi::RawValue(-1)));
1545 __ sll(T1, T1, 1); // T1 is Smi. 1533 __ sll(T1, T1, 1); // T1 is Smi.
1546 __ addu(T1, SP, T1); 1534 __ addu(T1, SP, T1);
1547 // T1: address of receiver. 1535 // T1: address of receiver.
1548 // Create a stub frame as we are pushing some objects on the stack before 1536 // Create a stub frame as we are pushing some objects on the stack before
1549 // calling into the runtime. 1537 // calling into the runtime.
1550 __ EnterStubFrame(); 1538 __ EnterStubFrame();
1551 // Preserve IC data object and arguments descriptor array and 1539 // Preserve IC data object and arguments descriptor array and
1552 // setup space on stack for result (target code object). 1540 // setup space on stack for result (target code object).
1553 int num_slots = num_args + 4; 1541 int num_slots = num_args + 4;
1554 __ addiu(SP, SP, Immediate(-num_slots * kWordSize)); 1542 __ addiu(SP, SP, Immediate(-num_slots * kWordSize));
(...skipping 22 matching lines...) Expand all
1577 1565
1578 Label call_target_function; 1566 Label call_target_function;
1579 if (!FLAG_lazy_dispatchers) { 1567 if (!FLAG_lazy_dispatchers) {
1580 __ mov(T0, T3); 1568 __ mov(T0, T3);
1581 GenerateDispatcherCode(assembler, &call_target_function); 1569 GenerateDispatcherCode(assembler, &call_target_function);
1582 } else { 1570 } else {
1583 __ b(&call_target_function); 1571 __ b(&call_target_function);
1584 } 1572 }
1585 1573
1586 __ Bind(&found); 1574 __ Bind(&found);
1575 __ mov(RA, T2); // Restore return address if found.
1587 __ Comment("Update caller's counter"); 1576 __ Comment("Update caller's counter");
1588 // T0: Pointer to an IC data check group. 1577 // T0: Pointer to an IC data check group.
1589 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize; 1578 const intptr_t target_offset = ICData::TargetIndexFor(num_args) * kWordSize;
1590 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize; 1579 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1591 __ lw(T3, Address(T0, target_offset)); 1580 __ lw(T3, Address(T0, target_offset));
1592 1581
1593 if (FLAG_optimization_counter_threshold >= 0) { 1582 if (FLAG_optimization_counter_threshold >= 0) {
1594 // Update counter. 1583 // Update counter, ignore overflow.
1595 __ lw(T4, Address(T0, count_offset)); 1584 __ lw(T4, Address(T0, count_offset));
1596 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); 1585 __ AddImmediate(T4, T4, Smi::RawValue(1));
1597 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow.
1598 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue));
1599 __ movz(T4, T7, CMPRES1);
1600 __ sw(T4, Address(T0, count_offset)); 1586 __ sw(T4, Address(T0, count_offset));
1601 } 1587 }
1602 1588
1603 __ Comment("Call target"); 1589 __ Comment("Call target");
1604 __ Bind(&call_target_function); 1590 __ Bind(&call_target_function);
1605 // T0 <- T3: Target function. 1591 // T0 <- T3: Target function.
1606 __ mov(T0, T3); 1592 __ mov(T0, T3);
1607 Label is_compiled; 1593 Label is_compiled;
1608 __ lw(T4, FieldAddress(T0, Function::entry_point_offset())); 1594 __ lw(T4, FieldAddress(T0, Function::entry_point_offset()));
1609 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); 1595 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset()));
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after
1722 1708
1723 // S5: IC data object (preserved). 1709 // S5: IC data object (preserved).
1724 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset())); 1710 __ lw(T0, FieldAddress(S5, ICData::ic_data_offset()));
1725 // T0: ic_data_array with entries: target functions and count. 1711 // T0: ic_data_array with entries: target functions and count.
1726 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag); 1712 __ AddImmediate(T0, Array::data_offset() - kHeapObjectTag);
1727 // T0: points directly to the first ic data array element. 1713 // T0: points directly to the first ic data array element.
1728 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize; 1714 const intptr_t target_offset = ICData::TargetIndexFor(0) * kWordSize;
1729 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize; 1715 const intptr_t count_offset = ICData::CountIndexFor(0) * kWordSize;
1730 1716
1731 if (FLAG_optimization_counter_threshold >= 0) { 1717 if (FLAG_optimization_counter_threshold >= 0) {
1732 // Increment count for this call. 1718 // Increment count for this call, ignore overflow.
1733 __ lw(T4, Address(T0, count_offset)); 1719 __ lw(T4, Address(T0, count_offset));
1734 __ AddImmediateDetectOverflow(T7, T4, Smi::RawValue(1), T5, T6); 1720 __ AddImmediate(T4, T4, Smi::RawValue(1));
1735 __ slt(CMPRES1, T5, ZR); // T5 is < 0 if there was overflow.
1736 __ LoadImmediate(T4, Smi::RawValue(Smi::kMaxValue));
1737 __ movz(T4, T7, CMPRES1);
1738 __ sw(T4, Address(T0, count_offset)); 1721 __ sw(T4, Address(T0, count_offset));
1739 } 1722 }
1740 1723
1741 // Load arguments descriptor into S4. 1724 // Load arguments descriptor into S4.
1742 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset())); 1725 __ lw(S4, FieldAddress(S5, ICData::arguments_descriptor_offset()));
1743 1726
1744 // Get function and call it, if possible. 1727 // Get function and call it, if possible.
1745 __ lw(T0, Address(T0, target_offset)); 1728 __ lw(T0, Address(T0, target_offset));
1746 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset())); 1729 __ lw(CODE_REG, FieldAddress(T0, Function::code_offset()));
1747 __ lw(T4, FieldAddress(T0, Function::entry_point_offset())); 1730 __ lw(T4, FieldAddress(T0, Function::entry_point_offset()));
(...skipping 673 matching lines...) Expand 10 before | Expand all | Expand 10 after
2421 } 2404 }
2422 2405
2423 2406
2424 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { 2407 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) {
2425 __ break_(0); 2408 __ break_(0);
2426 } 2409 }
2427 2410
2428 } // namespace dart 2411 } // namespace dart
2429 2412
2430 #endif // defined TARGET_ARCH_MIPS 2413 #endif // defined TARGET_ARCH_MIPS
OLDNEW
« no previous file with comments | « runtime/vm/stub_code_ia32.cc ('k') | runtime/vm/stub_code_x64.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698