| OLD | NEW |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2011, 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/assembler_macros.h" | 9 #include "vm/assembler_macros.h" |
| 10 #include "vm/code_generator.h" | 10 #include "vm/code_generator.h" |
| (...skipping 1534 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1545 // ECX: Inline cache data object. | 1545 // ECX: Inline cache data object. |
| 1546 // EDX: Arguments descriptor array. | 1546 // EDX: Arguments descriptor array. |
| 1547 // TOS(0): return address | 1547 // TOS(0): return address |
| 1548 // Control flow: | 1548 // Control flow: |
| 1549 // - If receiver is null -> jump to IC miss. | 1549 // - If receiver is null -> jump to IC miss. |
| 1550 // - If receiver is Smi -> load Smi class. | 1550 // - If receiver is Smi -> load Smi class. |
| 1551 // - If receiver is not-Smi -> load receiver's class. | 1551 // - If receiver is not-Smi -> load receiver's class. |
| 1552 // - Check if 'num_args' (including receiver) match any IC data group. | 1552 // - Check if 'num_args' (including receiver) match any IC data group. |
| 1553 // - Match found -> jump to target. | 1553 // - Match found -> jump to target. |
| 1554 // - Match not found -> jump to IC miss. | 1554 // - Match not found -> jump to IC miss. |
| 1555 // TODO(srdjan): Change IC data to keep class ids as integers not as Smi-s. |
| 1555 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, | 1556 void StubCode::GenerateNArgsCheckInlineCacheStub(Assembler* assembler, |
| 1556 intptr_t num_args) { | 1557 intptr_t num_args) { |
| 1557 const Immediate raw_null = | 1558 const Immediate raw_null = |
| 1558 Immediate(reinterpret_cast<intptr_t>(Object::null())); | 1559 Immediate(reinterpret_cast<intptr_t>(Object::null())); |
| 1559 | 1560 |
| 1560 __ movl(EBX, FieldAddress(ECX, ICData::function_offset())); | 1561 __ movl(EBX, FieldAddress(ECX, ICData::function_offset())); |
| 1561 __ incl(FieldAddress(EBX, Function::usage_counter_offset())); | 1562 __ incl(FieldAddress(EBX, Function::usage_counter_offset())); |
| 1562 if (CodeGenerator::CanOptimize()) { | 1563 if (CodeGenerator::CanOptimize()) { |
| 1563 __ cmpl(FieldAddress(EBX, Function::usage_counter_offset()), | 1564 __ cmpl(FieldAddress(EBX, Function::usage_counter_offset()), |
| 1564 Immediate(FLAG_optimization_counter_threshold)); | 1565 Immediate(FLAG_optimization_counter_threshold)); |
| (...skipping 12 matching lines...) Expand all Loading... |
| 1577 __ LeaveFrame(); | 1578 __ LeaveFrame(); |
| 1578 __ Bind(¬_yet_hot); | 1579 __ Bind(¬_yet_hot); |
| 1579 } | 1580 } |
| 1580 | 1581 |
| 1581 ASSERT(num_args > 0); | 1582 ASSERT(num_args > 0); |
| 1582 // Get receiver (first read number of arguments from argument descriptor array | 1583 // Get receiver (first read number of arguments from argument descriptor array |
| 1583 // and then access the receiver from the stack). | 1584 // and then access the receiver from the stack). |
| 1584 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1585 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1585 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi. | 1586 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (argument_count) is Smi. |
| 1586 | 1587 |
| 1587 Label get_class, ic_miss; | 1588 Label get_class_id_as_smi, ic_miss; |
| 1588 // ECX: IC data array. | 1589 // ECX: IC data array. |
| 1589 | 1590 |
| 1590 #if defined(DEBUG) | 1591 #if defined(DEBUG) |
| 1591 { Label ok; | 1592 { Label ok; |
| 1592 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. | 1593 // Check that the IC data array has NumberOfArgumentsChecked() == num_args. |
| 1593 // 'num_args_tested' is stored as an untagged int. | 1594 // 'num_args_tested' is stored as an untagged int. |
| 1594 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); | 1595 __ movl(EBX, FieldAddress(ECX, ICData::num_args_tested_offset())); |
| 1595 __ cmpl(EBX, Immediate(num_args)); | 1596 __ cmpl(EBX, Immediate(num_args)); |
| 1596 __ j(EQUAL, &ok, Assembler::kNearJump); | 1597 __ j(EQUAL, &ok, Assembler::kNearJump); |
| 1597 __ Stop("Incorrect stub for IC data"); | 1598 __ Stop("Incorrect stub for IC data"); |
| 1598 __ Bind(&ok); | 1599 __ Bind(&ok); |
| 1599 } | 1600 } |
| 1600 #endif // DEBUG | 1601 #endif // DEBUG |
| 1601 | 1602 |
| 1602 // Loop that checks if there is an IC data match. | 1603 // Loop that checks if there is an IC data match. |
| 1603 // ECX: IC data object (preserved). | 1604 // ECX: IC data object (preserved). |
| 1604 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); | 1605 __ movl(EBX, FieldAddress(ECX, ICData::ic_data_offset())); |
| 1605 // EBX: ic_data_array with check entries: classes and target functions. | 1606 // EBX: ic_data_array with check entries: classes and target functions. |
| 1606 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); | 1607 __ leal(EBX, FieldAddress(EBX, Array::data_offset())); |
| 1607 // EBX: points directly to the first ic data array element. | 1608 // EBX: points directly to the first ic data array element. |
| 1608 Label loop, found; | 1609 Label loop, found; |
| 1609 if (num_args == 1) { | 1610 if (num_args == 1) { |
| 1610 __ call(&get_class); | 1611 __ call(&get_class_id_as_smi); |
| 1611 // EAX: receiver's class | 1612 // EAX: receiver's class id Smi. |
| 1612 __ Bind(&loop); | 1613 __ Bind(&loop); |
| 1613 __ movl(EDI, Address(EBX, 0)); // Get class to check. | 1614 __ movl(EDI, Address(EBX, 0)); // Get class id (Smi) to check. |
| 1614 __ cmpl(EAX, EDI); // Match? | 1615 __ cmpl(EAX, EDI); // Class id match? |
| 1615 __ j(EQUAL, &found, Assembler::kNearJump); | 1616 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1616 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). | 1617 __ addl(EBX, Immediate(kWordSize * 2)); // Next element (class + target). |
| 1617 __ cmpl(EDI, raw_null); // Done? | 1618 __ cmpl(EDI, raw_null); // Done? |
| 1618 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1619 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1619 } else if (num_args == 2) { | 1620 } else if (num_args == 2) { |
| 1620 // EDI: class to check. | 1621 // EDI: class to check. |
| 1621 Label no_match; | 1622 Label no_match; |
| 1622 __ Bind(&loop); | 1623 __ Bind(&loop); |
| 1623 // Get class from IC data to check. | 1624 // Get class id from IC data to check. |
| 1624 // Get receiver using argument descriptor in EDX. | 1625 // Get receiver using argument descriptor in EDX. |
| 1625 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1626 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1626 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi. | 1627 __ movl(EAX, Address(ESP, EAX, TIMES_2, 0)); // EAX (arg. count) is Smi. |
| 1627 __ call(&get_class); | 1628 __ call(&get_class_id_as_smi); |
| 1628 // TODO(vegorov): switch IC data to store class index instead of class. | |
| 1629 __ movl(EDI, Address(EBX, 0)); | 1629 __ movl(EDI, Address(EBX, 0)); |
| 1630 __ cmpl(EAX, EDI); // Match? | 1630 __ cmpl(EAX, EDI); // Class id match? |
| 1631 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); | 1631 __ j(NOT_EQUAL, &no_match, Assembler::kNearJump); |
| 1632 // Check second class/argument. | 1632 // Check second class/argument. |
| 1633 // Get class from IC data to check. | 1633 // Get class id from IC data to check. |
| 1634 // Get next argument. | 1634 // Get next argument. |
| 1635 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); | 1635 __ movl(EAX, FieldAddress(EDX, Array::data_offset())); |
| 1636 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); | 1636 __ movl(EAX, Address(ESP, EAX, TIMES_2, -kWordSize)); |
| 1637 // EAX (argument count) is Smi. | 1637 // EAX (argument count) is Smi. |
| 1638 __ call(&get_class); | 1638 __ call(&get_class_id_as_smi); |
| 1639 __ movl(EDI, Address(EBX, kWordSize)); | 1639 __ movl(EDI, Address(EBX, kWordSize)); |
| 1640 __ cmpl(EAX, EDI); // Match? | 1640 __ cmpl(EAX, EDI); // Class id match? |
| 1641 __ j(EQUAL, &found, Assembler::kNearJump); | 1641 __ j(EQUAL, &found, Assembler::kNearJump); |
| 1642 __ Bind(&no_match); | 1642 __ Bind(&no_match); |
| 1643 // Each test entry has (1 + num_args) array elements. | 1643 // Each test entry has (1 + num_args) array elements. |
| 1644 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. | 1644 __ addl(EBX, Immediate(kWordSize * (1 + num_args))); // Next element. |
| 1645 __ cmpl(EDI, raw_null); // Done? | 1645 __ cmpl(EDI, raw_null); // Done? |
| 1646 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); | 1646 __ j(NOT_EQUAL, &loop, Assembler::kNearJump); |
| 1647 } | 1647 } |
| 1648 | 1648 |
| 1649 __ Bind(&ic_miss); | 1649 __ Bind(&ic_miss); |
| 1650 // Compute address of arguments (first read number of arguments from argument | 1650 // Compute address of arguments (first read number of arguments from argument |
| (...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1687 // EBX: Pointer to an IC data check group (classes + target) | 1687 // EBX: Pointer to an IC data check group (classes + target) |
| 1688 __ movl(EAX, Address(EBX, kWordSize * num_args)); // Target function. | 1688 __ movl(EAX, Address(EBX, kWordSize * num_args)); // Target function. |
| 1689 | 1689 |
| 1690 __ Bind(&call_target_function); | 1690 __ Bind(&call_target_function); |
| 1691 // EAX: Target function. | 1691 // EAX: Target function. |
| 1692 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); | 1692 __ movl(EAX, FieldAddress(EAX, Function::code_offset())); |
| 1693 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); | 1693 __ movl(EAX, FieldAddress(EAX, Code::instructions_offset())); |
| 1694 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); | 1694 __ addl(EAX, Immediate(Instructions::HeaderSize() - kHeapObjectTag)); |
| 1695 __ jmp(EAX); | 1695 __ jmp(EAX); |
| 1696 | 1696 |
| 1697 __ Bind(&get_class); | 1697 __ Bind(&get_class_id_as_smi); |
| 1698 Label not_smi; | 1698 Label not_smi; |
| 1699 // Test if Smi -> load Smi class for comparison. | 1699 // Test if Smi -> load Smi class for comparison. |
| 1700 __ testl(EAX, Immediate(kSmiTagMask)); | 1700 __ testl(EAX, Immediate(kSmiTagMask)); |
| 1701 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); | 1701 __ j(NOT_ZERO, ¬_smi, Assembler::kNearJump); |
| 1702 const Class& smi_class = | 1702 __ movl(EAX, Immediate(Smi::RawValue(kSmi))); |
| 1703 Class::ZoneHandle(Isolate::Current()->object_store()->smi_class()); | |
| 1704 __ LoadObject(EAX, smi_class); | |
| 1705 __ ret(); | 1703 __ ret(); |
| 1706 | 1704 |
| 1707 __ Bind(¬_smi); | 1705 __ Bind(¬_smi); |
| 1708 __ LoadClass(EAX, EAX, EDI); | 1706 __ LoadClassId(EAX, EAX); |
| 1707 __ SmiTag(EAX); |
| 1709 __ ret(); | 1708 __ ret(); |
| 1710 } | 1709 } |
| 1711 | 1710 |
| 1712 | 1711 |
| 1713 // Use inline cache data array to invoke the target or continue in inline | 1712 // Use inline cache data array to invoke the target or continue in inline |
| 1714 // cache miss handler. Stub for 1-argument check (receiver class). | 1713 // cache miss handler. Stub for 1-argument check (receiver class). |
| 1715 // ECX: Inline cache data array | 1714 // ECX: Inline cache data array |
| 1716 // EDX: Arguments array | 1715 // EDX: Arguments array |
| 1717 // TOS(0): return address | 1716 // TOS(0): return address |
| 1718 // Inline cache data array structure: | 1717 // Inline cache data array structure: |
| (...skipping 181 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1900 // TOS + 2: instance. | 1899 // TOS + 2: instance. |
| 1901 // TOS + 3: cache array. | 1900 // TOS + 3: cache array. |
| 1902 // Result in ECX: null -> not found, otherwise result (true or false). | 1901 // Result in ECX: null -> not found, otherwise result (true or false). |
| 1903 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { | 1902 void StubCode::GenerateSubtype3TestCacheStub(Assembler* assembler) { |
| 1904 GenerateSubtypeNTestCacheStub(assembler, 3); | 1903 GenerateSubtypeNTestCacheStub(assembler, 3); |
| 1905 } | 1904 } |
| 1906 | 1905 |
| 1907 } // namespace dart | 1906 } // namespace dart |
| 1908 | 1907 |
| 1909 #endif // defined TARGET_ARCH_IA32 | 1908 #endif // defined TARGET_ARCH_IA32 |
| OLD | NEW |