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_IA32) | 6 #if defined(TARGET_ARCH_IA32) |
7 | 7 |
8 #include "vm/assembler.h" | 8 #include "vm/assembler.h" |
9 #include "vm/compiler.h" | 9 #include "vm/compiler.h" |
10 #include "vm/dart_entry.h" | 10 #include "vm/dart_entry.h" |
(...skipping 1260 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1271 // - If receiver is Smi -> load Smi class. | 1271 // - If receiver is Smi -> load Smi class. |
1272 // - If receiver is not-Smi -> load receiver's class. | 1272 // - If receiver is not-Smi -> load receiver's class. |
1273 // - Check if 'num_args' (including receiver) match any IC data group. | 1273 // - Check if 'num_args' (including receiver) match any IC data group. |
1274 // - Match found -> jump to target. | 1274 // - Match found -> jump to target. |
1275 // - Match not found -> jump to IC miss. | 1275 // - Match not found -> jump to IC miss. |
1276 void StubCode::GenerateNArgsCheckInlineCacheStub( | 1276 void StubCode::GenerateNArgsCheckInlineCacheStub( |
1277 Assembler* assembler, | 1277 Assembler* assembler, |
1278 intptr_t num_args, | 1278 intptr_t num_args, |
1279 const RuntimeEntry& handle_ic_miss, | 1279 const RuntimeEntry& handle_ic_miss, |
1280 Token::Kind kind, | 1280 Token::Kind kind, |
1281 RangeCollectionMode range_collection_mode, | |
1282 bool optimized) { | 1281 bool optimized) { |
1283 ASSERT(num_args > 0); | 1282 ASSERT(num_args > 0); |
1284 #if defined(DEBUG) | 1283 #if defined(DEBUG) |
1285 { Label ok; | 1284 { Label ok; |
1286 // Check that the IC data array has NumArgsTested() == num_args. | 1285 // Check that the IC data array has NumArgsTested() == num_args. |
1287 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. | 1286 // 'NumArgsTested' is stored in the least significant bits of 'state_bits'. |
1288 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); | 1287 __ movl(EBX, FieldAddress(ECX, ICData::state_bits_offset())); |
1289 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. | 1288 ASSERT(ICData::NumArgsTestedShift() == 0); // No shift needed. |
1290 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); | 1289 __ andl(EBX, Immediate(ICData::NumArgsTestedMask())); |
1291 __ cmpl(EBX, Immediate(num_args)); | 1290 __ cmpl(EBX, Immediate(num_args)); |
1292 __ j(EQUAL, &ok, Assembler::kNearJump); | 1291 __ j(EQUAL, &ok, Assembler::kNearJump); |
1293 __ Stop("Incorrect stub for IC data"); | 1292 __ Stop("Incorrect stub for IC data"); |
1294 __ Bind(&ok); | 1293 __ Bind(&ok); |
1295 } | 1294 } |
1296 #endif // DEBUG | 1295 #endif // DEBUG |
1297 | 1296 |
1298 Label stepping, done_stepping; | 1297 Label stepping, done_stepping; |
1299 if (FLAG_support_debugger && !optimized) { | 1298 if (FLAG_support_debugger && !optimized) { |
1300 __ Comment("Check single stepping"); | 1299 __ Comment("Check single stepping"); |
1301 __ LoadIsolate(EAX); | 1300 __ LoadIsolate(EAX); |
1302 __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0)); | 1301 __ cmpb(Address(EAX, Isolate::single_step_offset()), Immediate(0)); |
1303 __ j(NOT_EQUAL, &stepping); | 1302 __ j(NOT_EQUAL, &stepping); |
1304 __ Bind(&done_stepping); | 1303 __ Bind(&done_stepping); |
1305 } | 1304 } |
1306 __ Comment("Range feedback collection"); | |
1307 Label not_smi_or_overflow; | 1305 Label not_smi_or_overflow; |
1308 if (range_collection_mode == kCollectRanges) { | |
1309 ASSERT((num_args == 1) || (num_args == 2)); | |
1310 if (num_args == 2) { | |
1311 __ movl(EAX, Address(ESP, + 2 * kWordSize)); | |
1312 __ UpdateRangeFeedback(EAX, 0, ECX, EBX, EDI, EDX, ¬_smi_or_overflow); | |
1313 } | |
1314 | |
1315 __ movl(EAX, Address(ESP, + 1 * kWordSize)); | |
1316 __ UpdateRangeFeedback(EAX, (num_args - 1), ECX, EBX, EDI, EDX, | |
1317 ¬_smi_or_overflow); | |
1318 } | |
1319 if (kind != Token::kILLEGAL) { | 1306 if (kind != Token::kILLEGAL) { |
1320 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); | 1307 EmitFastSmiOp(assembler, kind, num_args, ¬_smi_or_overflow); |
1321 } | 1308 } |
1322 __ Bind(¬_smi_or_overflow); | 1309 __ Bind(¬_smi_or_overflow); |
1323 | 1310 |
1324 __ Comment("Extract ICData initial values and receiver cid"); | 1311 __ Comment("Extract ICData initial values and receiver cid"); |
1325 // ECX: IC data object (preserved). | 1312 // ECX: IC data object (preserved). |
1326 // Load arguments descriptor into EDX. | 1313 // Load arguments descriptor into EDX. |
1327 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); | 1314 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); |
1328 // Loop that checks if there is an IC data match. | 1315 // Loop that checks if there is an IC data match. |
(...skipping 98 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1427 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); | 1414 __ movl(EDI, Immediate(Smi::RawValue(Smi::kMaxValue))); |
1428 __ cmovno(EDI, EAX); | 1415 __ cmovno(EDI, EAX); |
1429 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); | 1416 __ StoreIntoSmiField(Address(EBX, count_offset), EDI); |
1430 } | 1417 } |
1431 | 1418 |
1432 __ movl(EAX, Address(EBX, target_offset)); | 1419 __ movl(EAX, Address(EBX, target_offset)); |
1433 __ Bind(&call_target_function); | 1420 __ Bind(&call_target_function); |
1434 __ Comment("Call target"); | 1421 __ Comment("Call target"); |
1435 // EAX: Target function. | 1422 // EAX: Target function. |
1436 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); | 1423 __ movl(EBX, FieldAddress(EAX, Function::entry_point_offset())); |
1437 if (range_collection_mode == kCollectRanges) { | 1424 __ jmp(EBX); |
1438 __ EnterStubFrame(); | |
1439 __ pushl(ECX); | |
1440 const intptr_t arg_offset_words = num_args + | |
1441 Assembler::kEnterStubFramePushedWords + | |
1442 1; // ECX | |
1443 for (intptr_t i = 0; i < num_args; i++) { | |
1444 __ movl(EDI, Address(ESP, arg_offset_words * kWordSize)); | |
1445 __ pushl(EDI); | |
1446 } | |
1447 __ call(EBX); | |
1448 | |
1449 __ movl(ECX, Address(EBP, kFirstLocalSlotFromFp * kWordSize)); | |
1450 Label done; | |
1451 __ UpdateRangeFeedback(EAX, 2, ECX, EBX, EDI, EDX, &done); | |
1452 __ Bind(&done); | |
1453 __ LeaveFrame(); | |
1454 __ ret(); | |
1455 } else { | |
1456 __ jmp(EBX); | |
1457 } | |
1458 | 1425 |
1459 if (FLAG_support_debugger && !optimized) { | 1426 if (FLAG_support_debugger && !optimized) { |
1460 __ Bind(&stepping); | 1427 __ Bind(&stepping); |
1461 __ EnterStubFrame(); | 1428 __ EnterStubFrame(); |
1462 __ pushl(ECX); | 1429 __ pushl(ECX); |
1463 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); | 1430 __ CallRuntime(kSingleStepHandlerRuntimeEntry, 0); |
1464 __ popl(ECX); | 1431 __ popl(ECX); |
1465 __ LeaveFrame(); | 1432 __ LeaveFrame(); |
1466 __ jmp(&done_stepping); | 1433 __ jmp(&done_stepping); |
1467 } | 1434 } |
1468 } | 1435 } |
1469 | 1436 |
1470 | 1437 |
1471 // Use inline cache data array to invoke the target or continue in inline | 1438 // Use inline cache data array to invoke the target or continue in inline |
1472 // cache miss handler. Stub for 1-argument check (receiver class). | 1439 // cache miss handler. Stub for 1-argument check (receiver class). |
1473 // ECX: Inline cache data object. | 1440 // ECX: Inline cache data object. |
1474 // TOS(0): Return address. | 1441 // TOS(0): Return address. |
1475 // Inline cache data object structure: | 1442 // Inline cache data object structure: |
1476 // 0: function-name | 1443 // 0: function-name |
1477 // 1: N, number of arguments checked. | 1444 // 1: N, number of arguments checked. |
1478 // 2 .. (length - 1): group of checks, each check containing: | 1445 // 2 .. (length - 1): group of checks, each check containing: |
1479 // - N classes. | 1446 // - N classes. |
1480 // - 1 target function. | 1447 // - 1 target function. |
1481 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1448 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
1482 GenerateUsageCounterIncrement(assembler, EBX); | 1449 GenerateUsageCounterIncrement(assembler, EBX); |
1483 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1450 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
1484 kInlineCacheMissHandlerOneArgRuntimeEntry, | 1451 kInlineCacheMissHandlerOneArgRuntimeEntry, |
1485 Token::kILLEGAL, | 1452 Token::kILLEGAL); |
1486 kIgnoreRanges); | |
1487 } | 1453 } |
1488 | 1454 |
1489 | 1455 |
1490 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1456 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
1491 GenerateUsageCounterIncrement(assembler, EBX); | 1457 GenerateUsageCounterIncrement(assembler, EBX); |
1492 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1458 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1493 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1459 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1494 Token::kILLEGAL, | 1460 Token::kILLEGAL); |
1495 kIgnoreRanges); | |
1496 } | 1461 } |
1497 | 1462 |
1498 | 1463 |
1499 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { | 1464 void StubCode::GenerateSmiAddInlineCacheStub(Assembler* assembler) { |
1500 GenerateUsageCounterIncrement(assembler, EBX); | 1465 GenerateUsageCounterIncrement(assembler, EBX); |
1501 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1466 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1502 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1467 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1503 Token::kADD, | 1468 Token::kADD); |
1504 kCollectRanges); | |
1505 } | 1469 } |
1506 | 1470 |
1507 | 1471 |
1508 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { | 1472 void StubCode::GenerateSmiSubInlineCacheStub(Assembler* assembler) { |
1509 GenerateUsageCounterIncrement(assembler, EBX); | 1473 GenerateUsageCounterIncrement(assembler, EBX); |
1510 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1474 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1511 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1475 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1512 Token::kSUB, | 1476 Token::kSUB); |
1513 kCollectRanges); | |
1514 } | 1477 } |
1515 | 1478 |
1516 | 1479 |
1517 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { | 1480 void StubCode::GenerateSmiEqualInlineCacheStub(Assembler* assembler) { |
1518 GenerateUsageCounterIncrement(assembler, EBX); | 1481 GenerateUsageCounterIncrement(assembler, EBX); |
1519 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1482 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1520 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1483 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1521 Token::kEQ, | 1484 Token::kEQ); |
1522 kIgnoreRanges); | |
1523 } | 1485 } |
1524 | 1486 |
1525 | 1487 |
1526 void StubCode::GenerateUnaryRangeCollectingInlineCacheStub( | 1488 void StubCode::GenerateUnaryRangeCollectingInlineCacheStub( |
1527 Assembler* assembler) { | 1489 Assembler* assembler) { |
1528 GenerateUsageCounterIncrement(assembler, EBX); | 1490 GenerateUsageCounterIncrement(assembler, EBX); |
1529 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1491 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
1530 kInlineCacheMissHandlerOneArgRuntimeEntry, | 1492 kInlineCacheMissHandlerOneArgRuntimeEntry, |
1531 Token::kILLEGAL, | 1493 Token::kILLEGAL); |
1532 kCollectRanges); | |
1533 } | 1494 } |
1534 | 1495 |
1535 | 1496 |
1536 void StubCode::GenerateBinaryRangeCollectingInlineCacheStub( | 1497 void StubCode::GenerateBinaryRangeCollectingInlineCacheStub( |
1537 Assembler* assembler) { | 1498 Assembler* assembler) { |
1538 GenerateUsageCounterIncrement(assembler, EBX); | 1499 GenerateUsageCounterIncrement(assembler, EBX); |
1539 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1500 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1540 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1501 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1541 Token::kILLEGAL, | 1502 Token::kILLEGAL); |
1542 kCollectRanges); | |
1543 } | 1503 } |
1544 | 1504 |
1545 | 1505 |
1546 // Use inline cache data array to invoke the target or continue in inline | 1506 // Use inline cache data array to invoke the target or continue in inline |
1547 // cache miss handler. Stub for 1-argument check (receiver class). | 1507 // cache miss handler. Stub for 1-argument check (receiver class). |
1548 // EDI: function which counter needs to be incremented. | 1508 // EDI: function which counter needs to be incremented. |
1549 // ECX: Inline cache data object. | 1509 // ECX: Inline cache data object. |
1550 // TOS(0): Return address. | 1510 // TOS(0): Return address. |
1551 // Inline cache data object structure: | 1511 // Inline cache data object structure: |
1552 // 0: function-name | 1512 // 0: function-name |
1553 // 1: N, number of arguments checked. | 1513 // 1: N, number of arguments checked. |
1554 // 2 .. (length - 1): group of checks, each check containing: | 1514 // 2 .. (length - 1): group of checks, each check containing: |
1555 // - N classes. | 1515 // - N classes. |
1556 // - 1 target function. | 1516 // - 1 target function. |
1557 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1517 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
1558 Assembler* assembler) { | 1518 Assembler* assembler) { |
1559 GenerateOptimizedUsageCounterIncrement(assembler); | 1519 GenerateOptimizedUsageCounterIncrement(assembler); |
1560 GenerateNArgsCheckInlineCacheStub(assembler, 1, | 1520 GenerateNArgsCheckInlineCacheStub(assembler, 1, |
1561 kInlineCacheMissHandlerOneArgRuntimeEntry, | 1521 kInlineCacheMissHandlerOneArgRuntimeEntry, |
1562 Token::kILLEGAL, | 1522 Token::kILLEGAL, |
1563 kIgnoreRanges, | |
1564 true /* optimized */); | 1523 true /* optimized */); |
1565 } | 1524 } |
1566 | 1525 |
1567 | 1526 |
1568 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( | 1527 void StubCode::GenerateTwoArgsOptimizedCheckInlineCacheStub( |
1569 Assembler* assembler) { | 1528 Assembler* assembler) { |
1570 GenerateOptimizedUsageCounterIncrement(assembler); | 1529 GenerateOptimizedUsageCounterIncrement(assembler); |
1571 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1530 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1572 kInlineCacheMissHandlerTwoArgsRuntimeEntry, | 1531 kInlineCacheMissHandlerTwoArgsRuntimeEntry, |
1573 Token::kILLEGAL, | 1532 Token::kILLEGAL, |
1574 kIgnoreRanges, | |
1575 true /* optimized */); | 1533 true /* optimized */); |
1576 } | 1534 } |
1577 | 1535 |
1578 | 1536 |
1579 // Intermediary stub between a static call and its target. ICData contains | 1537 // Intermediary stub between a static call and its target. ICData contains |
1580 // the target function and the call count. | 1538 // the target function and the call count. |
1581 // ECX: ICData | 1539 // ECX: ICData |
1582 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1540 void StubCode::GenerateZeroArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1583 GenerateUsageCounterIncrement(assembler, EBX); | 1541 GenerateUsageCounterIncrement(assembler, EBX); |
1584 | 1542 |
(...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1638 __ LeaveFrame(); | 1596 __ LeaveFrame(); |
1639 __ jmp(&done_stepping, Assembler::kNearJump); | 1597 __ jmp(&done_stepping, Assembler::kNearJump); |
1640 } | 1598 } |
1641 } | 1599 } |
1642 | 1600 |
1643 | 1601 |
1644 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { | 1602 void StubCode::GenerateOneArgUnoptimizedStaticCallStub(Assembler* assembler) { |
1645 GenerateUsageCounterIncrement(assembler, EBX); | 1603 GenerateUsageCounterIncrement(assembler, EBX); |
1646 GenerateNArgsCheckInlineCacheStub( | 1604 GenerateNArgsCheckInlineCacheStub( |
1647 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, | 1605 assembler, 1, kStaticCallMissHandlerOneArgRuntimeEntry, |
1648 Token::kILLEGAL, | 1606 Token::kILLEGAL); |
1649 kIgnoreRanges); | |
1650 } | 1607 } |
1651 | 1608 |
1652 | 1609 |
1653 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { | 1610 void StubCode::GenerateTwoArgsUnoptimizedStaticCallStub(Assembler* assembler) { |
1654 GenerateUsageCounterIncrement(assembler, EBX); | 1611 GenerateUsageCounterIncrement(assembler, EBX); |
1655 GenerateNArgsCheckInlineCacheStub(assembler, 2, | 1612 GenerateNArgsCheckInlineCacheStub(assembler, 2, |
1656 kStaticCallMissHandlerTwoArgsRuntimeEntry, | 1613 kStaticCallMissHandlerTwoArgsRuntimeEntry, |
1657 Token::kILLEGAL, | 1614 Token::kILLEGAL); |
1658 kIgnoreRanges); | |
1659 } | 1615 } |
1660 | 1616 |
1661 | 1617 |
1662 // Stub for compiling a function and jumping to the compiled code. | 1618 // Stub for compiling a function and jumping to the compiled code. |
1663 // ECX: IC-Data (for methods). | 1619 // ECX: IC-Data (for methods). |
1664 // EDX: Arguments descriptor. | 1620 // EDX: Arguments descriptor. |
1665 // EAX: Function. | 1621 // EAX: Function. |
1666 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { | 1622 void StubCode::GenerateLazyCompileStub(Assembler* assembler) { |
1667 __ EnterStubFrame(); | 1623 __ EnterStubFrame(); |
1668 __ pushl(EDX); // Preserve arguments descriptor array. | 1624 __ pushl(EDX); // Preserve arguments descriptor array. |
(...skipping 439 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2108 | 2064 |
2109 | 2065 |
2110 | 2066 |
2111 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { | 2067 void StubCode::GenerateFrameAwaitingMaterializationStub(Assembler* assembler) { |
2112 __ int3(); | 2068 __ int3(); |
2113 } | 2069 } |
2114 | 2070 |
2115 } // namespace dart | 2071 } // namespace dart |
2116 | 2072 |
2117 #endif // defined TARGET_ARCH_IA32 | 2073 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |