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