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

Side by Side Diff: runtime/vm/stub_code_arm64.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) 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 1296 matching lines...) Expand 10 before | Expand all | Expand 10 after
1307 ASSERT(temp_reg == R6); 1307 ASSERT(temp_reg == R6);
1308 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset(), kNoPP); 1308 __ LoadFieldFromOffset(func_reg, ic_reg, ICData::owner_offset(), kNoPP);
1309 __ LoadFieldFromOffset( 1309 __ LoadFieldFromOffset(
1310 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord); 1310 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord);
1311 __ AddImmediate(R7, R7, 1, kNoPP); 1311 __ AddImmediate(R7, R7, 1, kNoPP);
1312 __ StoreFieldToOffset( 1312 __ StoreFieldToOffset(
1313 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord); 1313 R7, func_reg, Function::usage_counter_offset(), kNoPP, kWord);
1314 } 1314 }
1315 1315
1316 1316
1317 // Note: xxx must be preserved if 'not_smi_or_overflow' is jumped to.
Cutch 2014/08/15 21:23:28 xxx?
zra 2014/08/15 21:45:08 Should be R5 as on ARM.
srdjan 2014/08/15 21:49:00 R6.
zra 2014/08/15 22:12:33 Ah, right, sorry.
srdjan 2014/08/18 20:40:27 You are right: R5 :-).
1318 // Attempt a quick Smi operation for known operations ('kind'). The ICData
1319 // must have been primed with a Smi/Smi check that will be used for counting
1320 // the invocations.
1321 static void EmitFastSmiOp(Assembler* assembler,
1322 Token::Kind kind,
1323 intptr_t num_args,
1324 Label* not_smi_or_overflow) {
1325 if (FLAG_throw_on_javascript_int_overflow) {
1326 // The overflow check is more complex than implemented below.
1327 return;
1328 }
1329 __ ldr(R0, Address(SP, + 0 * kWordSize)); // Right.
1330 __ ldr(R1, Address(SP, + 1 * kWordSize)); // Left.
1331 __ orr(TMP, R0, Operand(R1));
1332 __ tsti(TMP, kSmiTagMask);
1333 __ b(not_smi_or_overflow, NE);
1334 switch (kind) {
1335 case Token::kADD: {
1336 __ adds(R0, R1, Operand(R0)); // Adds.
1337 __ b(not_smi_or_overflow, VS); // Branch if overflow.
1338 break;
1339 }
1340 case Token::kSUB: {
1341 __ subs(R0, R1, Operand(R0)); // Subtract.
1342 __ b(not_smi_or_overflow, VS); // Branch if overflow.
1343 break;
1344 }
1345 case Token::kEQ: {
1346 Label done, is_true;
zra 2014/08/15 21:45:08 Using conditional select: __ CompareRegisters(R0,
srdjan 2014/08/18 20:40:27 Done.
1347 __ cmp(R0, Operand(R1));
1348 __ b(&is_true, EQ);
1349 __ LoadObject(R0, Bool::False(), PP);
1350 __ b(&done);
1351 __ Bind(&is_true);
1352 __ LoadObject(R0, Bool::True(), PP);
1353 __ Bind(&done);
1354 break;
1355 }
1356 default: UNIMPLEMENTED();
1357 }
1358
1359 // R5: IC data object (preserved).
1360 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP);
1361 // R6: ic_data_array with check entries: classes and target functions.
1362 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP);
1363 // R6: points directly to the first ic data array element.
1364 #ifdef DEBUG
1365 // Check that first entry is for Smi/Smi.
1366 Label error, ok;
1367 const intptr_t imm_smi_cid = reinterpret_cast<intptr_t>(Smi::New(kSmiCid));
1368 __ ldr(R1, Address(R6, 0));
1369 __ CompareImmediate(R1, imm_smi_cid, kNoPP);
1370 __ b(&error, NE);
1371 __ ldr(R1, Address(R6, kWordSize));
1372 __ CompareImmediate(R1, imm_smi_cid, kNoPP);
1373 __ b(&ok, EQ);
1374 __ Bind(&error);
zra 2014/08/15 21:45:08 Same comment as on ARM.
srdjan 2014/08/18 20:40:27 Ditto.
1375 __ Stop("Incorrect IC data");
1376 __ Bind(&ok);
1377 #endif
1378 const intptr_t count_offset = ICData::CountIndexFor(num_args) * kWordSize;
1379 // Update counter.
1380 __ LoadFromOffset(R1, R6, count_offset, kNoPP);
1381 __ adds(R1, R1, Operand(Smi::RawValue(1)));
1382 __ LoadImmediate(R2, Smi::RawValue(Smi::kMaxValue), kNoPP);
1383 __ csel(R1, R2, R1, VS); // Overflow.
1384 __ StoreToOffset(R1, R6, count_offset, kNoPP);
1385
1386 __ ret();
1387 }
1388
1389
1317 // Generate inline cache check for 'num_args'. 1390 // Generate inline cache check for 'num_args'.
1318 // LR: return address. 1391 // LR: return address.
1319 // R5: inline cache data object. 1392 // R5: inline cache data object.
1320 // Control flow: 1393 // Control flow:
1321 // - If receiver is null -> jump to IC miss. 1394 // - If receiver is null -> jump to IC miss.
1322 // - If receiver is Smi -> load Smi class. 1395 // - If receiver is Smi -> load Smi class.
1323 // - If receiver is not-Smi -> load receiver's class. 1396 // - If receiver is not-Smi -> load receiver's class.
1324 // - Check if 'num_args' (including receiver) match any IC data group. 1397 // - Check if 'num_args' (including receiver) match any IC data group.
1325 // - Match found -> jump to target. 1398 // - Match found -> jump to target.
1326 // - Match not found -> jump to IC miss. 1399 // - Match not found -> jump to IC miss.
1327 void StubCode::GenerateNArgsCheckInlineCacheStub( 1400 void StubCode::GenerateNArgsCheckInlineCacheStub(
1328 Assembler* assembler, 1401 Assembler* assembler,
1329 intptr_t num_args, 1402 intptr_t num_args,
1330 const RuntimeEntry& handle_ic_miss) { 1403 const RuntimeEntry& handle_ic_miss,
1404 Token::Kind kind) {
1331 ASSERT(num_args > 0); 1405 ASSERT(num_args > 0);
1332 #if defined(DEBUG) 1406 #if defined(DEBUG)
1333 { Label ok; 1407 { Label ok;
1334 // Check that the IC data array has NumArgsTested() == num_args. 1408 // Check that the IC data array has NumArgsTested() == num_args.
1335 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1409 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1336 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, 1410 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
1337 kNoPP, kUnsignedWord); 1411 kNoPP, kUnsignedWord);
1338 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. 1412 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed.
1339 __ andi(R6, R6, ICData::NumArgsTestedMask()); 1413 __ andi(R6, R6, ICData::NumArgsTestedMask());
1340 __ CompareImmediate(R6, num_args, kNoPP); 1414 __ CompareImmediate(R6, num_args, kNoPP);
1341 __ b(&ok, EQ); 1415 __ b(&ok, EQ);
1342 __ Stop("Incorrect stub for IC data"); 1416 __ Stop("Incorrect stub for IC data");
1343 __ Bind(&ok); 1417 __ Bind(&ok);
1344 } 1418 }
1345 #endif // DEBUG 1419 #endif // DEBUG
1346 1420
1347 Label stepping, done_stepping; 1421 Label stepping, done_stepping;
1348 // Check single stepping. 1422 // Check single stepping.
1349 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset(), kNoPP); 1423 __ LoadFieldFromOffset(R6, CTX, Context::isolate_offset(), kNoPP);
1350 __ LoadFromOffset( 1424 __ LoadFromOffset(
1351 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte); 1425 R6, R6, Isolate::single_step_offset(), kNoPP, kUnsignedByte);
1352 __ CompareRegisters(R6, ZR); 1426 __ CompareRegisters(R6, ZR);
1353 __ b(&stepping, NE); 1427 __ b(&stepping, NE);
1354 __ Bind(&done_stepping); 1428 __ Bind(&done_stepping);
1355 1429
1430 if (kind != Token::kILLEGAL) {
1431 Label not_smi_or_overflow;
1432 EmitFastSmiOp(assembler, kind, num_args, &not_smi_or_overflow);
1433 __ Bind(&not_smi_or_overflow);
1434 }
1435
1356 // Load arguments descriptor into R4. 1436 // Load arguments descriptor into R4.
1357 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset(), kNoPP); 1437 __ LoadFieldFromOffset(R4, R5, ICData::arguments_descriptor_offset(), kNoPP);
1358 // Loop that checks if there is an IC data match. 1438 // Loop that checks if there is an IC data match.
1359 Label loop, update, test, found; 1439 Label loop, update, test, found;
1360 // R5: IC data object (preserved). 1440 // R5: IC data object (preserved).
1361 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP); 1441 __ LoadFieldFromOffset(R6, R5, ICData::ic_data_offset(), kNoPP);
1362 // R6: ic_data_array with check entries: classes and target functions. 1442 // R6: ic_data_array with check entries: classes and target functions.
1363 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP); 1443 __ AddImmediate(R6, R6, Array::data_offset() - kHeapObjectTag, kNoPP);
1364 // R6: points directly to the first ic data array element. 1444 // R6: points directly to the first ic data array element.
1365 1445
(...skipping 116 matching lines...) Expand 10 before | Expand all | Expand 10 after
1482 // LR: return address. 1562 // LR: return address.
1483 // R5: inline cache data object. 1563 // R5: inline cache data object.
1484 // Inline cache data object structure: 1564 // Inline cache data object structure:
1485 // 0: function-name 1565 // 0: function-name
1486 // 1: N, number of arguments checked. 1566 // 1: N, number of arguments checked.
1487 // 2 .. (length - 1): group of checks, each check containing: 1567 // 2 .. (length - 1): group of checks, each check containing:
1488 // - N classes. 1568 // - N classes.
1489 // - 1 target function. 1569 // - 1 target function.
1490 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { 1570 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) {
1491 GenerateUsageCounterIncrement(assembler, R6); 1571 GenerateUsageCounterIncrement(assembler, R6);
1492 GenerateNArgsCheckInlineCacheStub( 1572 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1493 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); 1573 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1494 } 1574 }
1495 1575
1496 1576
1497 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { 1577 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) {
1498 GenerateUsageCounterIncrement(assembler, R6); 1578 GenerateUsageCounterIncrement(assembler, R6);
1499 GenerateNArgsCheckInlineCacheStub( 1579 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1500 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); 1580 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1501 } 1581 }
1502 1582
1503 1583
1504 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { 1584 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) {
1505 GenerateUsageCounterIncrement(assembler, R6); 1585 GenerateUsageCounterIncrement(assembler, R6);
1506 GenerateNArgsCheckInlineCacheStub( 1586 GenerateNArgsCheckInlineCacheStub(assembler, 3,
1507 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); 1587 kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL);
1588 }
1589
1590
1591 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) {
1592 GenerateUsageCounterIncrement(assembler, R6);
1593 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1594 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kADD);
1595 }
1596
1597
1598 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) {
1599 GenerateUsageCounterIncrement(assembler, R6);
1600 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1601 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kSUB);
1602 }
1603
1604
1605 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) {
1606 GenerateUsageCounterIncrement(assembler, R6);
1607 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1608 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kEQ);
1508 } 1609 }
1509 1610
1510 1611
1511 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( 1612 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub(
1512 Assembler* assembler) { 1613 Assembler* assembler) {
1513 GenerateOptimizedUsageCounterIncrement(assembler); 1614 GenerateOptimizedUsageCounterIncrement(assembler);
1514 GenerateNArgsCheckInlineCacheStub( 1615 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1515 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); 1616 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1516 } 1617 }
1517 1618
1518 1619
1519 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( 1620 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub(
1520 Assembler* assembler) { 1621 Assembler* assembler) {
1521 GenerateOptimizedUsageCounterIncrement(assembler); 1622 GenerateOptimizedUsageCounterIncrement(assembler);
1522 GenerateNArgsCheckInlineCacheStub( 1623 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1523 assembler, 2, kInlineCacheMissHandlerTwoArgsRuntimeEntry); 1624 kInlineCacheMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1524 } 1625 }
1525 1626
1526 1627
1527 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub( 1628 void StubCode::GenerateThreeArgsOptimizedCheckInlineCacheStub(
1528 Assembler* assembler) { 1629 Assembler* assembler) {
1529 GenerateOptimizedUsageCounterIncrement(assembler); 1630 GenerateOptimizedUsageCounterIncrement(assembler);
1530 GenerateNArgsCheckInlineCacheStub( 1631 GenerateNArgsCheckInlineCacheStub(assembler, 3,
1531 assembler, 3, kInlineCacheMissHandlerThreeArgsRuntimeEntry); 1632 kInlineCacheMissHandlerThreeArgsRuntimeEntry, Token::kILLEGAL);
1532 } 1633 }
1533 1634
1534 1635
1535 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) { 1636 void StubCode::GenerateClosureCallInlineCacheStub(Assembler* assembler) {
1536 GenerateNArgsCheckInlineCacheStub( 1637 GenerateNArgsCheckInlineCacheStub(assembler, 1,
1537 assembler, 1, kInlineCacheMissHandlerOneArgRuntimeEntry); 1638 kInlineCacheMissHandlerOneArgRuntimeEntry, Token::kILLEGAL);
1538 } 1639 }
1539 1640
1540 1641
1541 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1642 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1542 GenerateUsageCounterIncrement(assembler, R6); 1643 GenerateUsageCounterIncrement(assembler, R6);
1543 #if defined(DEBUG) 1644 #if defined(DEBUG)
1544 { Label ok; 1645 { Label ok;
1545 // Check that the IC data array has NumArgsTested() == 0. 1646 // Check that the IC data array has NumArgsTested() == 0.
1546 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. 1647 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'.
1547 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag, 1648 __ LoadFromOffset(R6, R5, ICData::state_bits_offset() - kHeapObjectTag,
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
1597 // R0: function. 1698 // R0: function.
1598 // R2: target instructons. 1699 // R2: target instructons.
1599 __ AddImmediate( 1700 __ AddImmediate(
1600 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP); 1701 R2, R2, Instructions::HeaderSize() - kHeapObjectTag, kNoPP);
1601 __ br(R2); 1702 __ br(R2);
1602 } 1703 }
1603 1704
1604 1705
1605 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { 1706 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) {
1606 GenerateUsageCounterIncrement(assembler, R6); 1707 GenerateUsageCounterIncrement(assembler, R6);
1607 GenerateNArgsCheckInlineCacheStub( 1708 GenerateNArgsCheckInlineCacheStub(assembler, 2,
1608 assembler, 2, kStaticCallMissHandlerTwoArgsRuntimeEntry); 1709 kStaticCallMissHandlerTwoArgsRuntimeEntry, Token::kILLEGAL);
1609 } 1710 }
1610 1711
1611 1712
1612 // Stub for compiling a function and jumping to the compiled code. 1713 // Stub for compiling a function and jumping to the compiled code.
1613 // R5: IC-Data (for methods). 1714 // R5: IC-Data (for methods).
1614 // R4: Arguments descriptor. 1715 // R4: Arguments descriptor.
1615 // R0: Function. 1716 // R0: Function.
1616 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { 1717 void StubCode::GenerateLazyCompileStub(Assembler* assembler) {
1617 // Preserve arg desc. and IC data object. 1718 // Preserve arg desc. and IC data object.
1618 __ EnterStubFrame(); 1719 __ EnterStubFrame();
(...skipping 337 matching lines...) Expand 10 before | Expand all | Expand 10 after
1956 const Register right = R0; 2057 const Register right = R0;
1957 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP); 2058 __ LoadFromOffset(left, SP, 1 * kWordSize, kNoPP);
1958 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP); 2059 __ LoadFromOffset(right, SP, 0 * kWordSize, kNoPP);
1959 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp); 2060 GenerateIdenticalWithNumberCheckStub(assembler, left, right, temp);
1960 __ ret(); 2061 __ ret();
1961 } 2062 }
1962 2063
1963 } // namespace dart 2064 } // namespace dart
1964 2065
1965 #endif // defined TARGET_ARCH_ARM64 2066 #endif // defined TARGET_ARCH_ARM64
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698