Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(491)

Side by Side Diff: runtime/vm/code_generator.cc

Issue 26255004: Allow the debugger to inspect local variables from optimized and (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 2 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
« no previous file with comments | « no previous file | runtime/vm/debugger.h » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/code_generator.h" 5 #include "vm/code_generator.h"
6 6
7 #include "vm/assembler.h" 7 #include "vm/assembler.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 1502 matching lines...) Expand 10 before | Expand all | Expand 10 after
1513 ASSERT(cpu_registers_copy != NULL); 1513 ASSERT(cpu_registers_copy != NULL);
1514 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { 1514 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) {
1515 cpu_registers_copy[i] = 1515 cpu_registers_copy[i] =
1516 *reinterpret_cast<intptr_t*>(saved_registers_address); 1516 *reinterpret_cast<intptr_t*>(saved_registers_address);
1517 saved_registers_address += kWordSize; 1517 saved_registers_address += kWordSize;
1518 } 1518 }
1519 *cpu_registers = cpu_registers_copy; 1519 *cpu_registers = cpu_registers_copy;
1520 } 1520 }
1521 1521
1522 1522
1523 // Copy optimized frame. The first incoming argument is stored at the
1524 // last entry in the copied frame buffer.
1525 static void CopyFrame(const Code& optimized_code,
1526 const StackFrame& frame,
1527 intptr_t** frame_start,
1528 intptr_t* frame_size) {
1529 const Function& function = Function::Handle(optimized_code.function());
1530 // Do not copy incoming arguments if there are optional arguments (they
1531 // are copied into local space at method entry).
1532 const intptr_t num_args =
1533 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
1534 // The fixed size section of the (fake) Dart frame called via a stub by the
1535 // optimized function contains FP, PP (ARM and MIPS only), PC-marker and
1536 // return-address. This section is copied as well, so that its contained
1537 // values can be updated before returning to the deoptimized function.
1538 const intptr_t frame_copy_size =
1539 + kDartFrameFixedSize // For saved values below sp.
1540 + ((frame.fp() - frame.sp()) / kWordSize) // For frame size incl. sp.
1541 + 1 // For fp.
1542 + kParamEndSlotFromFp // For saved values above fp.
1543 + num_args; // For arguments.
1544 intptr_t* frame_copy = new intptr_t[frame_copy_size];
1545 ASSERT(frame_copy != NULL);
1546 intptr_t* start = reinterpret_cast<intptr_t*>(
1547 frame.sp() - (kDartFrameFixedSize * kWordSize));
1548 for (intptr_t i = 0; i < frame_copy_size; i++) {
1549 frame_copy[i] = *(start + i);
1550 }
1551 *frame_start = frame_copy;
1552 *frame_size = frame_copy_size;
1553 }
1554
1555
1556 // Copies saved registers and caller's frame into temporary buffers. 1523 // Copies saved registers and caller's frame into temporary buffers.
1557 // Returns the stack size of unoptimized frame. 1524 // Returns the stack size of unoptimized frame.
1558 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, 1525 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
1559 1, uword saved_registers_address) { 1526 1, uword saved_registers_address) {
1560 Isolate* isolate = Isolate::Current(); 1527 Isolate* isolate = Isolate::Current();
1561 StackZone zone(isolate); 1528 StackZone zone(isolate);
1562 HANDLESCOPE(isolate); 1529 HANDLESCOPE(isolate);
1563 1530
1564 // All registers have been saved below last-fp as if they were locals. 1531 // All registers have been saved below last-fp as if they were locals.
1565 const uword last_fp = saved_registers_address 1532 const uword last_fp = saved_registers_address
1566 + (kNumberOfCpuRegisters * kWordSize) 1533 + (kNumberOfCpuRegisters * kWordSize)
1567 + (kNumberOfFpuRegisters * kFpuRegisterSize) 1534 + (kNumberOfFpuRegisters * kFpuRegisterSize)
1568 - ((kFirstLocalSlotFromFp + 1) * kWordSize); 1535 - ((kFirstLocalSlotFromFp + 1) * kWordSize);
1569 1536
1570 // Get optimized code and frame that need to be deoptimized. 1537 // Get optimized code and frame that need to be deoptimized.
1571 DartFrameIterator iterator(last_fp); 1538 DartFrameIterator iterator(last_fp);
1572 StackFrame* caller_frame = iterator.NextFrame(); 1539 StackFrame* caller_frame = iterator.NextFrame();
1573 ASSERT(caller_frame != NULL); 1540 ASSERT(caller_frame != NULL);
1574 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); 1541 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
1575 ASSERT(optimized_code.is_optimized()); 1542 ASSERT(optimized_code.is_optimized());
1576 1543
1577 intptr_t deopt_reason = kDeoptUnknown; 1544 // Copy the saved registers from the stack.
1578 const DeoptInfo& deopt_info = DeoptInfo::Handle( 1545 fpu_register_t* fpu_registers;
1579 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); 1546 intptr_t* cpu_registers;
1580 ASSERT(!deopt_info.IsNull()); 1547 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers);
1581 1548
1582 // Create the DeoptContext for this deoptimization. Store in isolate. 1549 // Create the DeoptContext.
1583 const Function& function = Function::Handle(optimized_code.function()); 1550 DeoptContext* deopt_context =
1584 const intptr_t num_args = 1551 new DeoptContext(caller_frame, optimized_code,
1585 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); 1552 DeoptContext::kDestIsOriginalFrame,
1586 DeoptContext* deopt_context = new DeoptContext( 1553 fpu_registers, cpu_registers);
1587 Array::Handle(optimized_code.object_table()),
1588 num_args,
1589 static_cast<DeoptReasonId>(deopt_reason));
1590 isolate->set_deopt_context(deopt_context); 1554 isolate->set_deopt_context(deopt_context);
1591 1555
1592 // Copy the saved registers and the source frame. 1556 // Stack size (FP - SP) in bytes.
1593 fpu_register_t* fpu_registers; 1557 return deopt_context->DestStackAdjustment() * kWordSize;
1594 intptr_t* cpu_registers;
1595 intptr_t* frame_start;
1596 intptr_t frame_size;
1597 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers);
1598 CopyFrame(optimized_code, *caller_frame, &frame_start, &frame_size);
1599 deopt_context->SetSourceArgs(frame_start, frame_size,
1600 fpu_registers, cpu_registers,
1601 true); // true = source frame is a copy.
1602
1603 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
1604 OS::PrintErr(
1605 "Deoptimizing (reason %" Pd " '%s') at pc %#" Px " '%s' (count %d)\n",
1606 deopt_reason,
1607 DeoptReasonToText(deopt_reason),
1608 caller_frame->pc(),
1609 function.ToFullyQualifiedCString(),
1610 function.deoptimization_counter());
1611 }
1612
1613 // Compute the stack size of the unoptimized frame. For functions with
1614 // optional arguments the deoptimization info does not describe the
1615 // incoming arguments.
1616 const intptr_t unoptimized_stack_size =
1617 + deopt_info.FrameSize()
1618 - kDartFrameFixedSize
1619 - num_args
1620 - kParamEndSlotFromFp
1621 - 1; // For fp.
1622 return unoptimized_stack_size * kWordSize; // Stack size (FP - SP) in bytes.
1623 } 1558 }
1624 END_LEAF_RUNTIME_ENTRY 1559 END_LEAF_RUNTIME_ENTRY
1625 1560
1626 1561
1627 static void DeoptimizeWithDeoptInfo(DeoptContext* deopt_context,
1628 const Code& code,
1629 const DeoptInfo& deopt_info,
1630 const StackFrame& caller_frame) {
1631 const intptr_t len = deopt_info.TranslationLength();
1632 GrowableArray<DeoptInstr*> deopt_instructions(len);
1633 const Array& deopt_table = Array::Handle(code.deopt_info_array());
1634 ASSERT(!deopt_table.IsNull());
1635 deopt_info.ToInstructions(deopt_table, &deopt_instructions);
1636
1637 intptr_t* start = reinterpret_cast<intptr_t*>(
1638 caller_frame.sp() - (kDartFrameFixedSize * kWordSize));
1639 const Function& function = Function::Handle(code.function());
1640 const intptr_t num_args =
1641 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
1642 const intptr_t to_frame_size =
1643 + kDartFrameFixedSize // For saved values below sp.
1644 + (caller_frame.fp() - caller_frame.sp()) / kWordSize
1645 + 1 // For fp.
1646 + kParamEndSlotFromFp
1647 + num_args;
1648
1649 deopt_context->SetDestArgs(start, to_frame_size);
1650
1651 const intptr_t frame_size = deopt_info.FrameSize();
1652
1653 // All kMaterializeObject instructions are emitted before the instructions
1654 // that describe stack frames. Skip them and defer materialization of
1655 // objects until the frame is fully reconstructed and it is safe to perform
1656 // GC.
1657 // Arguments (class of the instance to allocate and field-value pairs) are
1658 // described as part of the expression stack for the bottom-most deoptimized
1659 // frame. They will be used during materialization and removed from the stack
1660 // right before control switches to the unoptimized code.
1661 const intptr_t num_materializations = len - frame_size;
1662 deopt_context->PrepareForDeferredMaterialization(num_materializations);
1663 for (intptr_t from_index = 0, to_index = kDartFrameFixedSize;
1664 from_index < num_materializations;
1665 from_index++) {
1666 const intptr_t field_count =
1667 DeoptInstr::GetFieldCount(deopt_instructions[from_index]);
1668 intptr_t* args = deopt_context->GetDestFrameAddressAt(to_index);
1669 DeferredObject* obj = new DeferredObject(field_count, args);
1670 deopt_context->SetDeferredObjectAt(from_index, obj);
1671 to_index += obj->ArgumentCount();
1672 }
1673
1674 // Populate stack frames.
1675 for (intptr_t to_index = frame_size - 1, from_index = len - 1;
1676 to_index >= 0;
1677 to_index--, from_index--) {
1678 intptr_t* to_addr = deopt_context->GetDestFrameAddressAt(to_index);
1679 deopt_instructions[from_index]->Execute(deopt_context, to_addr);
1680 }
1681
1682 if (FLAG_trace_deoptimization_verbose) {
1683 for (intptr_t i = 0; i < frame_size; i++) {
1684 OS::PrintErr("*%" Pd ". [%" Px "] %#014" Px " [%s]\n",
1685 i,
1686 reinterpret_cast<uword>(&start[i]),
1687 start[i],
1688 deopt_instructions[i + (len - frame_size)]->ToCString());
1689 }
1690 }
1691 }
1692
1693
1694 // The stack has been adjusted to fit all values for unoptimized frame. 1562 // The stack has been adjusted to fit all values for unoptimized frame.
1695 // Fill the unoptimized frame. 1563 // Fill the unoptimized frame.
1696 DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, 1, uword last_fp) { 1564 DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, 1, uword last_fp) {
1697 Isolate* isolate = Isolate::Current(); 1565 Isolate* isolate = Isolate::Current();
1698 StackZone zone(isolate); 1566 StackZone zone(isolate);
1699 HANDLESCOPE(isolate); 1567 HANDLESCOPE(isolate);
1700 1568
1569 DeoptContext* deopt_context = isolate->deopt_context();
1701 DartFrameIterator iterator(last_fp); 1570 DartFrameIterator iterator(last_fp);
1702 StackFrame* caller_frame = iterator.NextFrame(); 1571 StackFrame* caller_frame = iterator.NextFrame();
1703 ASSERT(caller_frame != NULL); 1572 ASSERT(caller_frame != NULL);
1704 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
1705 const Function& function = Function::Handle(optimized_code.function());
1706 ASSERT(!function.IsNull());
1707 const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
1708 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized());
1709 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized());
1710 1573
1711 intptr_t deopt_reason = kDeoptUnknown; 1574 #if defined(DEBUG)
1712 const DeoptInfo& deopt_info = DeoptInfo::Handle( 1575 {
1713 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); 1576 // The code from the deopt_context.
1714 ASSERT(!deopt_info.IsNull()); 1577 const Code& code = Code::Handle(deopt_context->code());
1715 1578
1716 DeoptContext* deopt_context = isolate->deopt_context(); 1579 // The code from our frame.
1717 DeoptimizeWithDeoptInfo(deopt_context, 1580 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
1718 optimized_code, 1581 const Function& function = Function::Handle(optimized_code.function());
1719 deopt_info, 1582 ASSERT(!function.IsNull());
1720 *caller_frame); 1583
1584 // The code will be the same as before.
1585 ASSERT(code.raw() == optimized_code.raw());
1586
1587 // Some sanity checking of the optimized/unoptimized code.
1588 const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
1589 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized());
1590 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized());
1591 }
1592 #endif
1593
1594 // TODO(turnidge): Compute the start of the dest frame in the
1595 // DeoptContext instead of passing it in here.
1596 intptr_t* start = reinterpret_cast<intptr_t*>(
1597 caller_frame->sp() - (kDartFrameFixedSize * kWordSize));
1598 deopt_context->set_dest_frame(start);
1599 deopt_context->FillDestFrame();
1721 } 1600 }
1722 END_LEAF_RUNTIME_ENTRY 1601 END_LEAF_RUNTIME_ENTRY
1723 1602
1724 1603
1725 // This is the last step in the deoptimization, GC can occur. 1604 // This is the last step in the deoptimization, GC can occur.
1726 // Returns number of bytes to remove from the expression stack of the 1605 // Returns number of bytes to remove from the expression stack of the
1727 // bottom-most deoptimized frame. Those arguments were artificially injected 1606 // bottom-most deoptimized frame. Those arguments were artificially injected
1728 // under return address to keep them discoverable by GC that can occur during 1607 // under return address to keep them discoverable by GC that can occur during
1729 // materialization phase. 1608 // materialization phase.
1730 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { 1609 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) {
1731 DeoptContext* deopt_context = isolate->deopt_context(); 1610 DeoptContext* deopt_context = isolate->deopt_context();
1732
1733 intptr_t deopt_arg_count = deopt_context->MaterializeDeferredObjects(); 1611 intptr_t deopt_arg_count = deopt_context->MaterializeDeferredObjects();
1734 isolate->set_deopt_context(NULL); 1612 isolate->set_deopt_context(NULL);
1735 delete deopt_context; 1613 delete deopt_context;
1736 1614
1737 // Return value tells deoptimization stub to remove the given number of bytes 1615 // Return value tells deoptimization stub to remove the given number of bytes
1738 // from the stack. 1616 // from the stack.
1739 arguments.SetReturn(Smi::Handle(Smi::New(deopt_arg_count * kWordSize))); 1617 arguments.SetReturn(Smi::Handle(Smi::New(deopt_arg_count * kWordSize)));
1740
1741 // Since this is the only step where GC can occur during deoptimization,
1742 // use it to report the source line where deoptimization occured.
1743 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) {
1744 DartFrameIterator iterator;
1745 StackFrame* top_frame = iterator.NextFrame();
1746 ASSERT(top_frame != NULL);
1747 const Code& code = Code::Handle(top_frame->LookupDartCode());
1748 const Function& top_function = Function::Handle(code.function());
1749 const Script& script = Script::Handle(top_function.script());
1750 const intptr_t token_pos = code.GetTokenIndexOfPC(top_frame->pc());
1751 intptr_t line, column;
1752 script.GetTokenLocation(token_pos, &line, &column);
1753 String& line_string = String::Handle(script.GetLine(line));
1754 OS::PrintErr(" Function: %s\n", top_function.ToFullyQualifiedCString());
1755 OS::PrintErr(" Line %" Pd ": '%s'\n", line, line_string.ToCString());
1756 OS::PrintErr(" Deopt args: %" Pd "\n", deopt_arg_count);
1757 }
1758 } 1618 }
1759 1619
1760 1620
1761 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, 1621 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t,
1762 BigintCompare, 1622 BigintCompare,
1763 2, 1623 2,
1764 RawBigint* left, 1624 RawBigint* left,
1765 RawBigint* right) { 1625 RawBigint* right) {
1766 Isolate* isolate = Isolate::Current(); 1626 Isolate* isolate = Isolate::Current();
1767 StackZone zone(isolate); 1627 StackZone zone(isolate);
(...skipping 57 matching lines...) Expand 10 before | Expand all | Expand 10 after
1825 field.UpdateCid(cid); 1685 field.UpdateCid(cid);
1826 intptr_t list_length = Field::kNoFixedLength; 1686 intptr_t list_length = Field::kNoFixedLength;
1827 if ((field.guarded_cid() != kDynamicCid) && 1687 if ((field.guarded_cid() != kDynamicCid) &&
1828 field.is_final() && RawObject::IsBuiltinListClassId(cid)) { 1688 field.is_final() && RawObject::IsBuiltinListClassId(cid)) {
1829 list_length = GetListLength(value); 1689 list_length = GetListLength(value);
1830 } 1690 }
1831 field.UpdateLength(list_length); 1691 field.UpdateLength(list_length);
1832 } 1692 }
1833 1693
1834 } // namespace dart 1694 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/debugger.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698