Chromium Code Reviews| 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/code_patcher.h" | 9 #include "vm/code_patcher.h" |
| 10 #include "vm/compiler.h" | 10 #include "vm/compiler.h" |
| (...skipping 1409 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1420 if (FLAG_trace_patching) { | 1420 if (FLAG_trace_patching) { |
| 1421 OS::Print("FixCallersTarget: patching from %#"Px" to '%s' %#"Px"\n", | 1421 OS::Print("FixCallersTarget: patching from %#"Px" to '%s' %#"Px"\n", |
| 1422 frame->pc(), | 1422 frame->pc(), |
| 1423 target_function.ToFullyQualifiedCString(), | 1423 target_function.ToFullyQualifiedCString(), |
| 1424 new_entry_point); | 1424 new_entry_point); |
| 1425 } | 1425 } |
| 1426 } | 1426 } |
| 1427 } | 1427 } |
| 1428 | 1428 |
| 1429 | 1429 |
| 1430 static const char* DeoptReasonToText(intptr_t deopt_id) { | 1430 const char* DeoptReasonToText(intptr_t deopt_id) { |
| 1431 switch (deopt_id) { | 1431 switch (deopt_id) { |
| 1432 #define DEOPT_REASON_ID_TO_TEXT(name) case k##name: return #name; | 1432 #define DEOPT_REASON_ID_TO_TEXT(name) case kDeopt##name: return #name; |
| 1433 DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT) | 1433 DEOPT_REASONS(DEOPT_REASON_ID_TO_TEXT) |
| 1434 #undef DEOPT_REASON_ID_TO_TEXT | 1434 #undef DEOPT_REASON_ID_TO_TEXT |
| 1435 default: | 1435 default: |
| 1436 UNREACHABLE(); | 1436 UNREACHABLE(); |
| 1437 return ""; | 1437 return ""; |
| 1438 } | 1438 } |
| 1439 } | 1439 } |
| 1440 | 1440 |
| 1441 | 1441 |
| 1442 static void GetDeoptIxDescrAtPc(const Code& code, | 1442 static void GetDeoptInfoAtPc(const Code& code, |
| 1443 uword pc, | 1443 uword pc, |
| 1444 intptr_t* deopt_id, | 1444 DeoptInfo* deopt_info, |
| 1445 intptr_t* deopt_reason, | 1445 intptr_t* deopt_reason) { |
| 1446 intptr_t* deopt_index) { | |
| 1447 ASSERT(code.is_optimized()); | 1446 ASSERT(code.is_optimized()); |
| 1448 const PcDescriptors& descriptors = | 1447 const Instructions& instructions = Instructions::Handle(code.instructions()); |
| 1449 PcDescriptors::Handle(code.pc_descriptors()); | 1448 uword code_entry = instructions.EntryPoint(); |
| 1450 ASSERT(!descriptors.IsNull()); | 1449 const Array& deopt_info_array = Array::Handle(code.deopt_info_array()); |
| 1451 // Locate deopt id at deoptimization point inside optimized code. | 1450 ASSERT(!deopt_info_array.IsNull()); |
| 1452 for (int i = 0; i < descriptors.Length(); i++) { | 1451 // Linear search for the PC offset matching the target PC. |
| 1453 if ((static_cast<uword>(descriptors.PC(i)) == pc) && | 1452 // An entry is a triple of (pc_offset, deopt_info, deopt_reason). |
| 1454 (descriptors.DescriptorKind(i) == PcDescriptors::kDeoptIndex)) { | 1453 const intptr_t kEntrySize = 3; |
| 1455 *deopt_id = descriptors.DeoptId(i); | 1454 Smi& offset = Smi::Handle(); |
| 1456 *deopt_reason = descriptors.DeoptReason(i); | 1455 for (intptr_t i = 0; i < deopt_info_array.Length(); i += kEntrySize) { |
| 1457 *deopt_index = descriptors.DeoptIndex(i); | 1456 offset ^= deopt_info_array.At(i); |
| 1457 if (pc == (code_entry + offset.Value())) { | |
| 1458 *deopt_info ^= deopt_info_array.At(i + 1); | |
| 1459 *deopt_reason = | |
| 1460 Smi::Cast(Object::Handle(deopt_info_array.At(i + 2))).Value(); | |
| 1458 return; | 1461 return; |
| 1459 } | 1462 } |
| 1460 } | 1463 } |
|
srdjan
2012/09/28 21:00:26
Iniitialize deopt_info and deopt_reason to somethi
Kevin Millikin (Google)
2012/10/01 09:38:56
OK, done.
srdjan
2012/10/01 17:18:28
Please upload your changes, before submitting, so
| |
| 1461 *deopt_id = Isolate::kNoDeoptId; | |
| 1462 *deopt_reason = kDeoptUnknown; | |
| 1463 *deopt_index = -1; | |
| 1464 } | 1464 } |
| 1465 | 1465 |
| 1466 | 1466 |
| 1467 // Currently checks only that all optimized frames have kDeoptIndex | 1467 // Currently checks only that all optimized frames have kDeoptIndex |
| 1468 // and unoptimized code has the kDeoptAfter. | 1468 // and unoptimized code has the kDeoptAfter. |
| 1469 void DeoptimizeAll() { | 1469 void DeoptimizeAll() { |
| 1470 DartFrameIterator iterator; | 1470 DartFrameIterator iterator; |
| 1471 StackFrame* frame = iterator.NextFrame(); | 1471 StackFrame* frame = iterator.NextFrame(); |
| 1472 Code& optimized_code = Code::Handle(); | 1472 Code& optimized_code = Code::Handle(); |
| 1473 Function& function = Function::Handle(); | 1473 Function& function = Function::Handle(); |
| 1474 Code& unoptimized_code = Code::Handle(); | 1474 Code& unoptimized_code = Code::Handle(); |
| 1475 while (frame != NULL) { | 1475 while (frame != NULL) { |
| 1476 optimized_code = frame->LookupDartCode(); | 1476 optimized_code = frame->LookupDartCode(); |
| 1477 if (optimized_code.is_optimized()) { | 1477 if (optimized_code.is_optimized()) { |
| 1478 intptr_t deopt_id, deopt_reason, deopt_index; | 1478 DeoptInfo& deopt_info = DeoptInfo::Handle(); |
| 1479 GetDeoptIxDescrAtPc(optimized_code, frame->pc(), | 1479 intptr_t deopt_reason = kDeoptUnknown; |
| 1480 &deopt_id, &deopt_reason, &deopt_index); | 1480 GetDeoptInfoAtPc(optimized_code, frame->pc(), &deopt_info, &deopt_reason); |
| 1481 ASSERT(deopt_id != Isolate::kNoDeoptId); | 1481 ASSERT(!deopt_info.IsNull()); |
| 1482 function = optimized_code.function(); | 1482 function = optimized_code.function(); |
| 1483 unoptimized_code = function.unoptimized_code(); | 1483 unoptimized_code = function.unoptimized_code(); |
| 1484 ASSERT(!unoptimized_code.IsNull()); | 1484 ASSERT(!unoptimized_code.IsNull()); |
| 1485 // The switch to unoptimized code may have already occured. | 1485 // The switch to unoptimized code may have already occured. |
| 1486 if (function.HasOptimizedCode()) { | 1486 if (function.HasOptimizedCode()) { |
| 1487 function.SwitchToUnoptimizedCode(); | 1487 function.SwitchToUnoptimizedCode(); |
| 1488 } | 1488 } |
| 1489 // Patch call site (lazy deoptimization is quite rare, patching it twice | 1489 // Patch call site (lazy deoptimization is quite rare, patching it twice |
| 1490 // is not a performance issue). | 1490 // is not a performance issue). |
| 1491 uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc(); | 1491 uword lazy_deopt_jump = optimized_code.GetLazyDeoptPc(); |
| (...skipping 68 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1560 kNumberOfCpuRegisters * kWordSize + kNumberOfXmmRegisters * kDoubleSize; | 1560 kNumberOfCpuRegisters * kWordSize + kNumberOfXmmRegisters * kDoubleSize; |
| 1561 CopySavedRegisters(saved_registers_address); | 1561 CopySavedRegisters(saved_registers_address); |
| 1562 | 1562 |
| 1563 // Get optimized code and frame that need to be deoptimized. | 1563 // Get optimized code and frame that need to be deoptimized. |
| 1564 DartFrameIterator iterator(last_fp); | 1564 DartFrameIterator iterator(last_fp); |
| 1565 StackFrame* caller_frame = iterator.NextFrame(); | 1565 StackFrame* caller_frame = iterator.NextFrame(); |
| 1566 ASSERT(caller_frame != NULL); | 1566 ASSERT(caller_frame != NULL); |
| 1567 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1567 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
| 1568 ASSERT(optimized_code.is_optimized()); | 1568 ASSERT(optimized_code.is_optimized()); |
| 1569 | 1569 |
| 1570 intptr_t deopt_id, deopt_reason, deopt_index; | 1570 |
| 1571 GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(), | 1571 DeoptInfo& deopt_info = DeoptInfo::Handle(); |
| 1572 &deopt_id, &deopt_reason, &deopt_index); | 1572 intptr_t deopt_reason = kDeoptUnknown; |
| 1573 ASSERT(deopt_id != Isolate::kNoDeoptId); | 1573 GetDeoptInfoAtPc(optimized_code, caller_frame->pc(), &deopt_info, |
| 1574 &deopt_reason); | |
| 1575 ASSERT(!deopt_info.IsNull()); | |
| 1574 | 1576 |
| 1575 CopyFrame(optimized_code, *caller_frame); | 1577 CopyFrame(optimized_code, *caller_frame); |
| 1576 if (FLAG_trace_deopt) { | 1578 if (FLAG_trace_deopt) { |
| 1577 intptr_t deopt_id, deopt_reason, deopt_index; | 1579 OS::Print("Deoptimizing (reason %"Pd" '%s') at pc %#"Px" '%s'\n", |
| 1578 GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(), | |
| 1579 &deopt_id, &deopt_reason, &deopt_index); | |
| 1580 OS::Print("Deoptimizing (reason %"Pd" '%s') at pc %#"Px" id %"Pd" '%s'\n", | |
| 1581 deopt_reason, | 1580 deopt_reason, |
| 1582 DeoptReasonToText(deopt_reason), | 1581 DeoptReasonToText(deopt_reason), |
| 1583 caller_frame->pc(), | 1582 caller_frame->pc(), |
| 1584 deopt_id, | |
| 1585 Function::Handle(optimized_code.function()).ToFullyQualifiedCString()); | 1583 Function::Handle(optimized_code.function()).ToFullyQualifiedCString()); |
| 1586 } | 1584 } |
| 1587 | 1585 |
| 1588 // Compute the stack size of unoptimized frame | 1586 // Compute the stack size of the unoptimized frame. For functions with |
| 1589 const Array& deopt_info_array = | 1587 // optional arguments the deoptimization info does not describe the |
| 1590 Array::Handle(optimized_code.deopt_info_array()); | 1588 // incoming arguments. |
| 1591 ASSERT(!deopt_info_array.IsNull()); | |
| 1592 DeoptInfo& deopt_info = DeoptInfo::Handle(); | |
| 1593 deopt_info ^= deopt_info_array.At(deopt_index); | |
| 1594 ASSERT(!deopt_info.IsNull()); | |
| 1595 // For functions with optional argument deoptimization info does not | |
| 1596 // describe incoming arguments. | |
| 1597 const Function& function = Function::Handle(optimized_code.function()); | 1589 const Function& function = Function::Handle(optimized_code.function()); |
| 1598 const intptr_t num_args = | 1590 const intptr_t num_args = |
| 1599 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 1591 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 1600 intptr_t unoptimized_stack_size = | 1592 intptr_t unoptimized_stack_size = |
| 1601 + deopt_info.Length() - num_args | 1593 + deopt_info.Length() - num_args |
| 1602 - 2; // Subtract caller FP and PC. | 1594 - 2; // Subtract caller FP and PC. |
| 1603 return unoptimized_stack_size * kWordSize; | 1595 return unoptimized_stack_size * kWordSize; |
| 1604 } | 1596 } |
| 1605 END_LEAF_RUNTIME_ENTRY | 1597 END_LEAF_RUNTIME_ENTRY |
| 1606 | 1598 |
| (...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1659 const Function& function = Function::Handle(optimized_code.function()); | 1651 const Function& function = Function::Handle(optimized_code.function()); |
| 1660 ASSERT(!function.IsNull()); | 1652 ASSERT(!function.IsNull()); |
| 1661 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); | 1653 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); |
| 1662 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); | 1654 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); |
| 1663 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); | 1655 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); |
| 1664 | 1656 |
| 1665 intptr_t* frame_copy = isolate->deopt_frame_copy(); | 1657 intptr_t* frame_copy = isolate->deopt_frame_copy(); |
| 1666 intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy(); | 1658 intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy(); |
| 1667 double* xmm_registers_copy = isolate->deopt_xmm_registers_copy(); | 1659 double* xmm_registers_copy = isolate->deopt_xmm_registers_copy(); |
| 1668 | 1660 |
| 1669 intptr_t deopt_id, deopt_reason, deopt_index; | |
| 1670 GetDeoptIxDescrAtPc(optimized_code, caller_frame->pc(), | |
| 1671 &deopt_id, &deopt_reason, &deopt_index); | |
| 1672 ASSERT(deopt_id != Isolate::kNoDeoptId); | |
| 1673 const Array& deopt_info_array = | |
| 1674 Array::Handle(optimized_code.deopt_info_array()); | |
| 1675 ASSERT(!deopt_info_array.IsNull()); | |
| 1676 DeoptInfo& deopt_info = DeoptInfo::Handle(); | 1661 DeoptInfo& deopt_info = DeoptInfo::Handle(); |
| 1677 deopt_info ^= deopt_info_array.At(deopt_index); | 1662 intptr_t deopt_reason = kDeoptUnknown; |
| 1663 GetDeoptInfoAtPc(optimized_code, caller_frame->pc(), &deopt_info, | |
| 1664 &deopt_reason); | |
| 1678 ASSERT(!deopt_info.IsNull()); | 1665 ASSERT(!deopt_info.IsNull()); |
| 1666 | |
| 1679 const intptr_t caller_fp = | 1667 const intptr_t caller_fp = |
| 1680 DeoptimizeWithDeoptInfo(optimized_code, deopt_info, *caller_frame); | 1668 DeoptimizeWithDeoptInfo(optimized_code, deopt_info, *caller_frame); |
| 1681 | 1669 |
| 1682 isolate->SetDeoptFrameCopy(NULL, 0); | 1670 isolate->SetDeoptFrameCopy(NULL, 0); |
| 1683 isolate->set_deopt_cpu_registers_copy(NULL); | 1671 isolate->set_deopt_cpu_registers_copy(NULL); |
| 1684 isolate->set_deopt_xmm_registers_copy(NULL); | 1672 isolate->set_deopt_xmm_registers_copy(NULL); |
| 1685 delete[] frame_copy; | 1673 delete[] frame_copy; |
| 1686 delete[] cpu_registers_copy; | 1674 delete[] cpu_registers_copy; |
| 1687 delete[] xmm_registers_copy; | 1675 delete[] xmm_registers_copy; |
| 1688 | 1676 |
| (...skipping 25 matching lines...) Expand all Loading... | |
| 1714 current->slot(), | 1702 current->slot(), |
| 1715 current->value()); | 1703 current->value()); |
| 1716 } | 1704 } |
| 1717 | 1705 |
| 1718 delete current; | 1706 delete current; |
| 1719 } | 1707 } |
| 1720 } | 1708 } |
| 1721 | 1709 |
| 1722 | 1710 |
| 1723 } // namespace dart | 1711 } // namespace dart |
| OLD | NEW |