| 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 |