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 1398 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1409 __ popl(EAX); | 1409 __ popl(EAX); |
1410 __ popl(EAX); | 1410 __ popl(EAX); |
1411 __ popl(EAX); // Get result into EAX. | 1411 __ popl(EAX); // Get result into EAX. |
1412 | 1412 |
1413 // Remove the stub frame as we are about to return. | 1413 // Remove the stub frame as we are about to return. |
1414 __ LeaveFrame(); | 1414 __ LeaveFrame(); |
1415 __ ret(); | 1415 __ ret(); |
1416 } | 1416 } |
1417 | 1417 |
1418 | 1418 |
| 1419 // Cannot use function object from ICData as it may be the inlined |
| 1420 // function and not the top-scope function. |
1419 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { | 1421 void StubCode::GenerateOptimizedUsageCounterIncrement(Assembler* assembler) { |
1420 Register argdesc_reg = EDX; | |
1421 Register ic_reg = ECX; | 1422 Register ic_reg = ECX; |
1422 Register func_reg = EDI; | 1423 Register func_reg = EDI; |
1423 if (FLAG_trace_optimized_ic_calls) { | 1424 if (FLAG_trace_optimized_ic_calls) { |
1424 __ EnterStubFrame(); | 1425 __ EnterStubFrame(); |
1425 __ pushl(func_reg); // Preserve | 1426 __ pushl(func_reg); // Preserve |
1426 __ pushl(argdesc_reg); // Preserve. | |
1427 __ pushl(ic_reg); // Preserve. | 1427 __ pushl(ic_reg); // Preserve. |
1428 __ pushl(ic_reg); // Argument. | 1428 __ pushl(ic_reg); // Argument. |
1429 __ pushl(func_reg); // Argument. | 1429 __ pushl(func_reg); // Argument. |
1430 __ CallRuntime(kTraceICCallRuntimeEntry); | 1430 __ CallRuntime(kTraceICCallRuntimeEntry); |
1431 __ popl(EAX); // Discard argument; | 1431 __ popl(EAX); // Discard argument; |
1432 __ popl(EAX); // Discard argument; | 1432 __ popl(EAX); // Discard argument; |
1433 __ popl(ic_reg); // Restore. | 1433 __ popl(ic_reg); // Restore. |
1434 __ popl(argdesc_reg); // Restore. | |
1435 __ popl(func_reg); // Restore. | 1434 __ popl(func_reg); // Restore. |
1436 __ LeaveFrame(); | 1435 __ LeaveFrame(); |
1437 } | 1436 } |
1438 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); | 1437 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); |
1439 } | 1438 } |
1440 | 1439 |
1441 | 1440 |
1442 // Loads function into 'temp_reg'. | 1441 // Loads function into 'temp_reg'. |
1443 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, | 1442 void StubCode::GenerateUsageCounterIncrement(Assembler* assembler, |
1444 Register temp_reg) { | 1443 Register temp_reg) { |
1445 Register ic_reg = ECX; | 1444 Register ic_reg = ECX; |
1446 Register func_reg = temp_reg; | 1445 Register func_reg = temp_reg; |
1447 ASSERT(ic_reg != func_reg); | 1446 ASSERT(ic_reg != func_reg); |
1448 __ movl(func_reg, FieldAddress(ic_reg, ICData::function_offset())); | 1447 __ movl(func_reg, FieldAddress(ic_reg, ICData::function_offset())); |
1449 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); | 1448 __ incl(FieldAddress(func_reg, Function::usage_counter_offset())); |
1450 } | 1449 } |
1451 | 1450 |
1452 | 1451 |
1453 // Generate inline cache check for 'num_args'. | 1452 // Generate inline cache check for 'num_args'. |
1454 // ECX: Inline cache data object. | 1453 // ECX: Inline cache data object. |
1455 // EDX: Arguments descriptor array. | |
1456 // TOS(0): return address | 1454 // TOS(0): return address |
1457 // Control flow: | 1455 // Control flow: |
1458 // - If receiver is null -> jump to IC miss. | 1456 // - If receiver is null -> jump to IC miss. |
1459 // - If receiver is Smi -> load Smi class. | 1457 // - If receiver is Smi -> load Smi class. |
1460 // - If receiver is not-Smi -> load receiver's class. | 1458 // - If receiver is not-Smi -> load receiver's class. |
1461 // - Check if 'num_args' (including receiver) match any IC data group. | 1459 // - Check if 'num_args' (including receiver) match any IC data group. |
1462 // - Match found -> jump to target. | 1460 // - Match found -> jump to target. |
1463 // - Match not found -> jump to IC miss. | 1461 // - Match not found -> jump to IC miss. |
1464 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1462 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
1465 intptr_t num_args) { | 1463 intptr_t num_args) { |
1466 ASSERT(num_args > 0); | 1464 ASSERT(num_args > 0); |
1467 #if defined(DEBUG) | 1465 #if defined(DEBUG) |
1468 { Label ok; | 1466 { Label ok; |
1469 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1467 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
1470 // 'num_args_tested' is stored as an untagged int. | 1468 // 'num_args_tested' is stored as an untagged int. |
1471 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); | 1469 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
1472 __ cmpl(EBX, Immediate(num_args)); | 1470 __ cmpl(EBX, Immediate(num_args)); |
1473 __ j(EQUAL, &ok, Assembler::kNearJump); | 1471 __ j(EQUAL, &ok, Assembler::kNearJump); |
1474 __ Stop("Incorrect stub for IC data"); | 1472 __ Stop("Incorrect stub for IC data"); |
1475 __ Bind(&ok); | 1473 __ Bind(&ok); |
1476 } | 1474 } |
1477 #endif // DEBUG | 1475 #endif // DEBUG |
1478 | 1476 |
| 1477 // Load arguments descriptor into EDX. |
| 1478 __ movl(EDX, FieldAddress(ECX, ICData::arguments_descriptor_offset())); |
1479 // Loop that checks if there is an IC data match. | 1479 // Loop that checks if there is an IC data match. |
1480 Label loop, update, test, found, get_class_id_as_smi; | 1480 Label loop, update, test, found, get_class_id_as_smi; |
1481 // ECX: IC data object (preserved). | 1481 // ECX: IC data object (preserved). |
1482 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1482 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
1483 // EBX: ic_data_array with check entries: classes and target functions. | 1483 // EBX: ic_data_array with check entries: classes and target functions. |
1484 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1484 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
1485 // EBX: points directly to the first ic data array element. | 1485 // EBX: points directly to the first ic data array element. |
1486 | 1486 |
1487 // Get the receiver's class ID (first read number of arguments from | 1487 // Get the receiver's class ID (first read number of arguments from |
1488 // arguments descriptor array and then access the receiver from the stack). | 1488 // arguments descriptor array and then access the receiver from the stack). |
(...skipping 115 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1604 __ Bind(¬_smi); | 1604 __ Bind(¬_smi); |
1605 __ LoadClassId(EAX, EAX); | 1605 __ LoadClassId(EAX, EAX); |
1606 __ SmiTag(EAX); | 1606 __ SmiTag(EAX); |
1607 __ ret(); | 1607 __ ret(); |
1608 } | 1608 } |
1609 | 1609 |
1610 | 1610 |
1611 // Use inline cache data array to invoke the target or continue in inline | 1611 // Use inline cache data array to invoke the target or continue in inline |
1612 // cache miss handler. Stub for 1-argument check (receiver class). | 1612 // cache miss handler. Stub for 1-argument check (receiver class). |
1613 // ECX: Inline cache data object. | 1613 // ECX: Inline cache data object. |
1614 // EDX: Arguments descriptor array. | |
1615 // TOS(0): Return address. | 1614 // TOS(0): Return address. |
1616 // Inline cache data object structure: | 1615 // Inline cache data object structure: |
1617 // 0: function-name | 1616 // 0: function-name |
1618 // 1: N, number of arguments checked. | 1617 // 1: N, number of arguments checked. |
1619 // 2 .. (length - 1): group of checks, each check containing: | 1618 // 2 .. (length - 1): group of checks, each check containing: |
1620 // - N classes. | 1619 // - N classes. |
1621 // - 1 target function. | 1620 // - 1 target function. |
1622 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { | 1621 void StubCode::GenerateOneArgCheckInlineCacheStub(Assembler* assembler) { |
1623 GenerateUsageCounterIncrement(assembler, EBX); | 1622 GenerateUsageCounterIncrement(assembler, EBX); |
1624 GenerateNArgsCheckInlineCacheStub(assembler, 1); | 1623 GenerateNArgsCheckInlineCacheStub(assembler, 1); |
1625 } | 1624 } |
1626 | 1625 |
1627 | 1626 |
1628 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { | 1627 void StubCode::GenerateTwoArgsCheckInlineCacheStub(Assembler* assembler) { |
1629 GenerateUsageCounterIncrement(assembler, EBX); | 1628 GenerateUsageCounterIncrement(assembler, EBX); |
1630 GenerateNArgsCheckInlineCacheStub(assembler, 2); | 1629 GenerateNArgsCheckInlineCacheStub(assembler, 2); |
1631 } | 1630 } |
1632 | 1631 |
1633 | 1632 |
1634 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { | 1633 void StubCode::GenerateThreeArgsCheckInlineCacheStub(Assembler* assembler) { |
1635 GenerateUsageCounterIncrement(assembler, EBX); | 1634 GenerateUsageCounterIncrement(assembler, EBX); |
1636 GenerateNArgsCheckInlineCacheStub(assembler, 3); | 1635 GenerateNArgsCheckInlineCacheStub(assembler, 3); |
1637 } | 1636 } |
1638 | 1637 |
1639 | 1638 |
1640 // Use inline cache data array to invoke the target or continue in inline | 1639 // Use inline cache data array to invoke the target or continue in inline |
1641 // cache miss handler. Stub for 1-argument check (receiver class). | 1640 // cache miss handler. Stub for 1-argument check (receiver class). |
1642 // EDI: function which counter needs to be incremented. | 1641 // EDI: function which counter needs to be incremented. |
1643 // ECX: Inline cache data object. | 1642 // ECX: Inline cache data object. |
1644 // EDX: Arguments descriptor array. | |
1645 // TOS(0): Return address. | 1643 // TOS(0): Return address. |
1646 // Inline cache data object structure: | 1644 // Inline cache data object structure: |
1647 // 0: function-name | 1645 // 0: function-name |
1648 // 1: N, number of arguments checked. | 1646 // 1: N, number of arguments checked. |
1649 // 2 .. (length - 1): group of checks, each check containing: | 1647 // 2 .. (length - 1): group of checks, each check containing: |
1650 // - N classes. | 1648 // - N classes. |
1651 // - 1 target function. | 1649 // - 1 target function. |
1652 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( | 1650 void StubCode::GenerateOneArgOptimizedCheckInlineCacheStub( |
1653 Assembler* assembler) { | 1651 Assembler* assembler) { |
1654 GenerateOptimizedUsageCounterIncrement(assembler); | 1652 GenerateOptimizedUsageCounterIncrement(assembler); |
(...skipping 87 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1742 // Instead of returning to the patched Dart function, emulate the | 1740 // Instead of returning to the patched Dart function, emulate the |
1743 // smashed return code pattern and return to the function's caller. | 1741 // smashed return code pattern and return to the function's caller. |
1744 __ popl(ECX); // Discard return address to patched dart code. | 1742 __ popl(ECX); // Discard return address to patched dart code. |
1745 // Execute function epilog code that was smashed in the Dart code. | 1743 // Execute function epilog code that was smashed in the Dart code. |
1746 __ LeaveFrame(); | 1744 __ LeaveFrame(); |
1747 __ ret(); | 1745 __ ret(); |
1748 } | 1746 } |
1749 | 1747 |
1750 | 1748 |
1751 // ECX: Inline cache data array. | 1749 // ECX: Inline cache data array. |
1752 // EDX: Arguments descriptor array. | |
1753 // TOS(0): return address (Dart code). | 1750 // TOS(0): return address (Dart code). |
1754 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { | 1751 void StubCode::GenerateBreakpointDynamicStub(Assembler* assembler) { |
1755 // Create a stub frame as we are pushing some objects on the stack before | 1752 // Create a stub frame as we are pushing some objects on the stack before |
1756 // calling into the runtime. | 1753 // calling into the runtime. |
1757 __ EnterStubFrame(); | 1754 __ EnterStubFrame(); |
1758 __ pushl(ECX); | 1755 __ pushl(ECX); |
1759 __ pushl(EDX); | |
1760 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); | 1756 __ CallRuntime(kBreakpointDynamicHandlerRuntimeEntry); |
1761 __ popl(EDX); | |
1762 __ popl(ECX); | 1757 __ popl(ECX); |
1763 __ LeaveFrame(); | 1758 __ LeaveFrame(); |
1764 | 1759 |
1765 // Find out which dispatch stub to call. | 1760 // Find out which dispatch stub to call. |
1766 Label test_two, test_three, test_four; | 1761 Label test_two, test_three, test_four; |
1767 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); | 1762 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
1768 __ cmpl(EBX, Immediate(1)); | 1763 __ cmpl(EBX, Immediate(1)); |
1769 __ j(NOT_EQUAL, &test_two, Assembler::kNearJump); | 1764 __ j(NOT_EQUAL, &test_two, Assembler::kNearJump); |
1770 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); | 1765 __ jmp(&StubCode::OneArgCheckInlineCacheLabel()); |
1771 __ Bind(&test_two); | 1766 __ Bind(&test_two); |
(...skipping 350 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
2122 __ Bind(&done); | 2117 __ Bind(&done); |
2123 __ popl(temp); | 2118 __ popl(temp); |
2124 __ popl(right); | 2119 __ popl(right); |
2125 __ popl(left); | 2120 __ popl(left); |
2126 __ ret(); | 2121 __ ret(); |
2127 } | 2122 } |
2128 | 2123 |
2129 } // namespace dart | 2124 } // namespace dart |
2130 | 2125 |
2131 #endif // defined TARGET_ARCH_IA32 | 2126 #endif // defined TARGET_ARCH_IA32 |
OLD | NEW |