OLD | NEW |
1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, 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/code_generator.h" | 5 #include "vm/code_generator.h" |
6 | 6 |
7 #include "vm/assembler_macros.h" | 7 #include "vm/assembler_macros.h" |
8 #include "vm/ast.h" | 8 #include "vm/ast.h" |
9 #include "vm/bigint_operations.h" | 9 #include "vm/bigint_operations.h" |
10 #include "vm/code_patcher.h" | 10 #include "vm/code_patcher.h" |
(...skipping 1420 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1431 #define DEOPT_REASON_ID_TO_TEXT(name) case kDeopt##name: return #name; | 1431 #define DEOPT_REASON_ID_TO_TEXT(name) case kDeopt##name: return #name; |
1432 DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT) | 1432 DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT) |
1433 #undef DEOPT_REASON_ID_TO_TEXT | 1433 #undef DEOPT_REASON_ID_TO_TEXT |
1434 default: | 1434 default: |
1435 UNREACHABLE(); | 1435 UNREACHABLE(); |
1436 return ""; | 1436 return ""; |
1437 } | 1437 } |
1438 } | 1438 } |
1439 | 1439 |
1440 | 1440 |
1441 static void GetDeoptInfoAtPc(const Code& code, | |
1442 uword pc, | |
1443 DeoptInfo* deopt_info, | |
1444 DeoptReasonId* deopt_reason) { | |
1445 ASSERT(code.is_optimized()); | |
1446 const Instructions& instructions = Instructions::Handle(code.instructions()); | |
1447 uword code_entry = instructions.EntryPoint(); | |
1448 const Array& table = Array::Handle(code.deopt_info_array()); | |
1449 ASSERT(!table.IsNull()); | |
1450 // Linear search for the PC offset matching the target PC. | |
1451 intptr_t length = DeoptTable::GetLength(table); | |
1452 Smi& offset = Smi::Handle(); | |
1453 Smi& reason = Smi::Handle(); | |
1454 for (intptr_t i = 0; i < length; ++i) { | |
1455 DeoptTable::GetEntry(table, i, &offset, deopt_info, &reason); | |
1456 if (pc == (code_entry + offset.Value())) { | |
1457 *deopt_reason = static_cast<DeoptReasonId>(reason.Value()); | |
1458 return; | |
1459 } | |
1460 } | |
1461 *deopt_info = DeoptInfo::null(); | |
1462 *deopt_reason = kDeoptUnknown; | |
1463 } | |
1464 | |
1465 | |
1466 static void DeoptimizeAt(const Code& optimized_code, uword pc) { | 1441 static void DeoptimizeAt(const Code& optimized_code, uword pc) { |
1467 DeoptInfo& deopt_info = DeoptInfo::Handle(); | 1442 intptr_t deopt_reason = kDeoptUnknown; |
1468 DeoptReasonId deopt_reason = kDeoptUnknown; | 1443 const DeoptInfo& deopt_info = |
1469 GetDeoptInfoAtPc(optimized_code, pc, &deopt_info, &deopt_reason); | 1444 DeoptInfo::Handle(optimized_code.GetDeoptInfoAtPc(pc, &deopt_reason)); |
1470 ASSERT(!deopt_info.IsNull()); | 1445 ASSERT(!deopt_info.IsNull()); |
1471 const Function& function = Function::Handle(optimized_code.function()); | 1446 const Function& function = Function::Handle(optimized_code.function()); |
1472 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); | 1447 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); |
1473 ASSERT(!unoptimized_code.IsNull()); | 1448 ASSERT(!unoptimized_code.IsNull()); |
1474 // The switch to unoptimized code may have already occured. | 1449 // The switch to unoptimized code may have already occured. |
1475 if (function.HasOptimizedCode()) { | 1450 if (function.HasOptimizedCode()) { |
1476 function.SwitchToUnoptimizedCode(); | 1451 function.SwitchToUnoptimizedCode(); |
1477 } | 1452 } |
1478 // Patch call site (lazy deoptimization is quite rare, patching it twice | 1453 // Patch call site (lazy deoptimization is quite rare, patching it twice |
1479 // is not a performance issue). | 1454 // is not a performance issue). |
(...skipping 112 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1592 CopySavedRegisters(saved_registers_address); | 1567 CopySavedRegisters(saved_registers_address); |
1593 | 1568 |
1594 // Get optimized code and frame that need to be deoptimized. | 1569 // Get optimized code and frame that need to be deoptimized. |
1595 DartFrameIterator iterator(last_fp); | 1570 DartFrameIterator iterator(last_fp); |
1596 StackFrame* caller_frame = iterator.NextFrame(); | 1571 StackFrame* caller_frame = iterator.NextFrame(); |
1597 ASSERT(caller_frame != NULL); | 1572 ASSERT(caller_frame != NULL); |
1598 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1573 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
1599 ASSERT(optimized_code.is_optimized()); | 1574 ASSERT(optimized_code.is_optimized()); |
1600 | 1575 |
1601 | 1576 |
1602 DeoptInfo& deopt_info = DeoptInfo::Handle(); | 1577 intptr_t deopt_reason = kDeoptUnknown; |
1603 DeoptReasonId deopt_reason = kDeoptUnknown; | 1578 const DeoptInfo& deopt_info = DeoptInfo::Handle( |
1604 GetDeoptInfoAtPc(optimized_code, caller_frame->pc(), &deopt_info, | 1579 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); |
1605 &deopt_reason); | |
1606 ASSERT(!deopt_info.IsNull()); | 1580 ASSERT(!deopt_info.IsNull()); |
1607 | 1581 |
1608 CopyFrame(optimized_code, *caller_frame); | 1582 CopyFrame(optimized_code, *caller_frame); |
1609 if (FLAG_trace_deoptimization) { | 1583 if (FLAG_trace_deoptimization) { |
1610 Function& function = Function::Handle(optimized_code.function()); | 1584 Function& function = Function::Handle(optimized_code.function()); |
1611 OS::PrintErr("Deoptimizing (reason %d '%s') at pc %#"Px" '%s' (count %d)\n", | 1585 OS::PrintErr( |
| 1586 "Deoptimizing (reason %"Pd" '%s') at pc %#"Px" '%s' (count %d)\n", |
1612 deopt_reason, | 1587 deopt_reason, |
1613 DeoptReasonToText(deopt_reason), | 1588 DeoptReasonToText(deopt_reason), |
1614 caller_frame->pc(), | 1589 caller_frame->pc(), |
1615 function.ToFullyQualifiedCString(), | 1590 function.ToFullyQualifiedCString(), |
1616 function.deoptimization_counter()); | 1591 function.deoptimization_counter()); |
1617 } | 1592 } |
1618 | 1593 |
1619 // Compute the stack size of the unoptimized frame. For functions with | 1594 // Compute the stack size of the unoptimized frame. For functions with |
1620 // optional arguments the deoptimization info does not describe the | 1595 // optional arguments the deoptimization info does not describe the |
1621 // incoming arguments. | 1596 // incoming arguments. |
1622 const Function& function = Function::Handle(optimized_code.function()); | 1597 const Function& function = Function::Handle(optimized_code.function()); |
1623 const intptr_t num_args = | 1598 const intptr_t num_args = |
1624 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 1599 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
1625 intptr_t unoptimized_stack_size = | 1600 intptr_t unoptimized_stack_size = |
1626 + deopt_info.TranslationLength() - num_args | 1601 + deopt_info.TranslationLength() - num_args |
1627 - 2; // Subtract caller FP and PC. | 1602 - 2; // Subtract caller FP and PC. |
1628 return unoptimized_stack_size * kWordSize; | 1603 return unoptimized_stack_size * kWordSize; |
1629 } | 1604 } |
1630 END_LEAF_RUNTIME_ENTRY | 1605 END_LEAF_RUNTIME_ENTRY |
1631 | 1606 |
1632 | 1607 |
1633 | 1608 |
1634 static intptr_t DeoptimizeWithDeoptInfo(const Code& code, | 1609 static intptr_t DeoptimizeWithDeoptInfo(const Code& code, |
1635 const DeoptInfo& deopt_info, | 1610 const DeoptInfo& deopt_info, |
1636 const StackFrame& caller_frame, | 1611 const StackFrame& caller_frame, |
1637 DeoptReasonId deopt_reason) { | 1612 intptr_t deopt_reason) { |
1638 const intptr_t len = deopt_info.TranslationLength(); | 1613 const intptr_t len = deopt_info.TranslationLength(); |
1639 GrowableArray<DeoptInstr*> deopt_instructions(len); | 1614 GrowableArray<DeoptInstr*> deopt_instructions(len); |
1640 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 1615 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
1641 ASSERT(!deopt_table.IsNull()); | 1616 ASSERT(!deopt_table.IsNull()); |
1642 deopt_info.ToInstructions(deopt_table, &deopt_instructions); | 1617 deopt_info.ToInstructions(deopt_table, &deopt_instructions); |
1643 | 1618 |
1644 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame.sp() - kWordSize); | 1619 intptr_t* start = reinterpret_cast<intptr_t*>(caller_frame.sp() - kWordSize); |
1645 const Function& function = Function::Handle(code.function()); | 1620 const Function& function = Function::Handle(code.function()); |
1646 const intptr_t num_args = | 1621 const intptr_t num_args = |
1647 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 1622 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
1648 intptr_t to_frame_size = | 1623 intptr_t to_frame_size = |
1649 1 // Deoptimized function's return address. | 1624 1 // Deoptimized function's return address. |
1650 + (caller_frame.fp() - caller_frame.sp()) / kWordSize | 1625 + (caller_frame.fp() - caller_frame.sp()) / kWordSize |
1651 + 3 // caller-fp, pc, pc-marker. | 1626 + 3 // caller-fp, pc, pc-marker. |
1652 + num_args; | 1627 + num_args; |
1653 DeoptimizationContext deopt_context(start, | 1628 DeoptimizationContext deopt_context(start, |
1654 to_frame_size, | 1629 to_frame_size, |
1655 Array::Handle(code.object_table()), | 1630 Array::Handle(code.object_table()), |
1656 num_args, | 1631 num_args, |
1657 deopt_reason); | 1632 static_cast<DeoptReasonId>(deopt_reason)); |
1658 for (intptr_t to_index = len - 1; to_index >= 0; to_index--) { | 1633 for (intptr_t to_index = len - 1; to_index >= 0; to_index--) { |
1659 deopt_instructions[to_index]->Execute(&deopt_context, to_index); | 1634 deopt_instructions[to_index]->Execute(&deopt_context, to_index); |
1660 } | 1635 } |
1661 if (FLAG_trace_deoptimization_verbose) { | 1636 if (FLAG_trace_deoptimization_verbose) { |
1662 for (intptr_t i = 0; i < len; i++) { | 1637 for (intptr_t i = 0; i < len; i++) { |
1663 OS::PrintErr("*%"Pd". [%p] %#014"Px" [%s]\n", | 1638 OS::PrintErr("*%"Pd". [%p] %#014"Px" [%s]\n", |
1664 i, | 1639 i, |
1665 &start[i], | 1640 &start[i], |
1666 start[i], | 1641 start[i], |
1667 deopt_instructions[i]->ToCString()); | 1642 deopt_instructions[i]->ToCString()); |
(...skipping 17 matching lines...) Expand all Loading... |
1685 const Function& function = Function::Handle(optimized_code.function()); | 1660 const Function& function = Function::Handle(optimized_code.function()); |
1686 ASSERT(!function.IsNull()); | 1661 ASSERT(!function.IsNull()); |
1687 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); | 1662 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); |
1688 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); | 1663 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); |
1689 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); | 1664 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); |
1690 | 1665 |
1691 intptr_t* frame_copy = isolate->deopt_frame_copy(); | 1666 intptr_t* frame_copy = isolate->deopt_frame_copy(); |
1692 intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy(); | 1667 intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy(); |
1693 double* xmm_registers_copy = isolate->deopt_xmm_registers_copy(); | 1668 double* xmm_registers_copy = isolate->deopt_xmm_registers_copy(); |
1694 | 1669 |
1695 DeoptInfo& deopt_info = DeoptInfo::Handle(); | 1670 intptr_t deopt_reason = kDeoptUnknown; |
1696 DeoptReasonId deopt_reason = kDeoptUnknown; | 1671 const DeoptInfo& deopt_info = DeoptInfo::Handle( |
1697 GetDeoptInfoAtPc(optimized_code, caller_frame->pc(), &deopt_info, | 1672 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); |
1698 &deopt_reason); | |
1699 ASSERT(!deopt_info.IsNull()); | 1673 ASSERT(!deopt_info.IsNull()); |
1700 | 1674 |
1701 const intptr_t caller_fp = | 1675 const intptr_t caller_fp = DeoptimizeWithDeoptInfo(optimized_code, |
1702 DeoptimizeWithDeoptInfo(optimized_code, deopt_info, *caller_frame, | 1676 deopt_info, |
1703 deopt_reason); | 1677 *caller_frame, |
| 1678 deopt_reason); |
1704 | 1679 |
1705 isolate->SetDeoptFrameCopy(NULL, 0); | 1680 isolate->SetDeoptFrameCopy(NULL, 0); |
1706 isolate->set_deopt_cpu_registers_copy(NULL); | 1681 isolate->set_deopt_cpu_registers_copy(NULL); |
1707 isolate->set_deopt_xmm_registers_copy(NULL); | 1682 isolate->set_deopt_xmm_registers_copy(NULL); |
1708 delete[] frame_copy; | 1683 delete[] frame_copy; |
1709 delete[] cpu_registers_copy; | 1684 delete[] cpu_registers_copy; |
1710 delete[] xmm_registers_copy; | 1685 delete[] xmm_registers_copy; |
1711 | 1686 |
1712 return caller_fp; | 1687 return caller_fp; |
1713 } | 1688 } |
(...skipping 80 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1794 return; | 1769 return; |
1795 } | 1770 } |
1796 HeapTrace* heap_trace = Isolate::Current()->heap()->trace(); | 1771 HeapTrace* heap_trace = Isolate::Current()->heap()->trace(); |
1797 heap_trace->TraceStoreIntoObject(RawObject::ToAddr(object), | 1772 heap_trace->TraceStoreIntoObject(RawObject::ToAddr(object), |
1798 field_addr, | 1773 field_addr, |
1799 RawObject::ToAddr(value)); | 1774 RawObject::ToAddr(value)); |
1800 } | 1775 } |
1801 END_LEAF_RUNTIME_ENTRY | 1776 END_LEAF_RUNTIME_ENTRY |
1802 | 1777 |
1803 } // namespace dart | 1778 } // namespace dart |
OLD | NEW |