Chromium Code Reviews| OLD | NEW |
|---|---|
| 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 1527 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1538 function.deoptimization_counter()); | 1538 function.deoptimization_counter()); |
| 1539 } | 1539 } |
| 1540 | 1540 |
| 1541 // Compute the stack size of the unoptimized frame. For functions with | 1541 // Compute the stack size of the unoptimized frame. For functions with |
| 1542 // optional arguments the deoptimization info does not describe the | 1542 // optional arguments the deoptimization info does not describe the |
| 1543 // incoming arguments. | 1543 // incoming arguments. |
| 1544 const Function& function = Function::Handle(optimized_code.function()); | 1544 const Function& function = Function::Handle(optimized_code.function()); |
| 1545 const intptr_t num_args = | 1545 const intptr_t num_args = |
| 1546 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 1546 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 1547 intptr_t unoptimized_stack_size = | 1547 intptr_t unoptimized_stack_size = |
| 1548 + deopt_info.TranslationLength() - num_args | 1548 + deopt_info.FrameSize() - num_args |
| 1549 - kLastParamSlotIndex; // Subtract caller FP and PC (possibly pc marker). | 1549 - kLastParamSlotIndex; // Subtract caller FP and PC (possibly pc marker). |
| 1550 return unoptimized_stack_size * kWordSize; | 1550 return unoptimized_stack_size * kWordSize; |
| 1551 } | 1551 } |
| 1552 END_LEAF_RUNTIME_ENTRY | 1552 END_LEAF_RUNTIME_ENTRY |
| 1553 | 1553 |
| 1554 | 1554 |
| 1555 static intptr_t DeoptimizeWithDeoptInfo(const Code& code, | 1555 static intptr_t DeoptimizeWithDeoptInfo(const Code& code, |
| 1556 const DeoptInfo& deopt_info, | 1556 const DeoptInfo& deopt_info, |
| 1557 const StackFrame& caller_frame, | 1557 const StackFrame& caller_frame, |
| 1558 intptr_t deopt_reason) { | 1558 intptr_t deopt_reason) { |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1570 const intptr_t to_frame_size = | 1570 const intptr_t to_frame_size = |
| 1571 - kPcSlotIndexFromSp // Deoptimized function's return address. | 1571 - kPcSlotIndexFromSp // Deoptimized function's return address. |
| 1572 + (caller_frame.fp() - caller_frame.sp()) / kWordSize | 1572 + (caller_frame.fp() - caller_frame.sp()) / kWordSize |
| 1573 + kLastParamSlotIndex | 1573 + kLastParamSlotIndex |
| 1574 + num_args; | 1574 + num_args; |
| 1575 DeoptimizationContext deopt_context(start, | 1575 DeoptimizationContext deopt_context(start, |
| 1576 to_frame_size, | 1576 to_frame_size, |
| 1577 Array::Handle(code.object_table()), | 1577 Array::Handle(code.object_table()), |
| 1578 num_args, | 1578 num_args, |
| 1579 static_cast<DeoptReasonId>(deopt_reason)); | 1579 static_cast<DeoptReasonId>(deopt_reason)); |
| 1580 for (intptr_t to_index = len - 1; to_index >= 0; to_index--) { | 1580 const intptr_t frame_size = deopt_info.FrameSize(); |
| 1581 deopt_instructions[to_index]->Execute(&deopt_context, to_index); | 1581 |
| 1582 // All kMaterializeObject instructions are emitted before the instructions | |
| 1583 // that describe stack frames. Skip them and defer materialization of | |
| 1584 // objects until the frame is fully reconstructed and it is safe to perform | |
| 1585 // GC. | |
| 1586 // Arguments (class of the instance to allocate and field-value pairs) are | |
| 1587 // described as part of the expression stack for the bottom-most deoptimized | |
| 1588 // frame. They will be used during materialization and removed from the stack | |
| 1589 // right before control switches to the unoptimized code. | |
| 1590 const intptr_t num_materializations = len - frame_size; | |
| 1591 Isolate::Current()->PrepareForDeferredMaterialization(num_materializations); | |
| 1592 for (intptr_t from_index = 0, to_index = 1; | |
| 1593 from_index < num_materializations; | |
| 1594 from_index++) { | |
| 1595 const intptr_t field_count = | |
| 1596 DeoptInstr::GetFieldCount(deopt_instructions[from_index]); | |
| 1597 intptr_t* args = deopt_context.GetToFrameAddressAt(to_index); | |
| 1598 DeferredObject* obj = new DeferredObject(field_count, args); | |
| 1599 Isolate::Current()->SetDeferredObjectAt(from_index, obj); | |
| 1600 to_index += obj->ArgumentCount(); | |
| 1582 } | 1601 } |
| 1602 | |
| 1603 // Populate stack frames. | |
| 1604 for (intptr_t to_index = frame_size - 1, from_index = len - 1; | |
| 1605 to_index >= 0; | |
| 1606 to_index--, from_index--) { | |
| 1607 intptr_t* to_addr = deopt_context.GetToFrameAddressAt(to_index); | |
| 1608 deopt_instructions[from_index]->Execute(&deopt_context, to_addr); | |
| 1609 } | |
| 1610 | |
| 1583 if (FLAG_trace_deoptimization_verbose) { | 1611 if (FLAG_trace_deoptimization_verbose) { |
| 1584 for (intptr_t i = 0; i < len; i++) { | 1612 for (intptr_t i = 0; i < frame_size; i++) { |
| 1585 OS::PrintErr("*%"Pd". [%p] %#014"Px" [%s]\n", | 1613 OS::PrintErr("*%"Pd". [%"Px"] %#014"Px" [%s]\n", |
| 1586 i, | 1614 i, |
| 1587 &start[i], | 1615 reinterpret_cast<uword>(&start[i]), |
| 1588 start[i], | 1616 start[i], |
| 1589 deopt_instructions[i]->ToCString()); | 1617 deopt_instructions[i + (len - frame_size)]->ToCString()); |
| 1590 } | 1618 } |
| 1591 } | 1619 } |
| 1592 return deopt_context.GetCallerFp(); | 1620 return deopt_context.GetCallerFp(); |
| 1593 } | 1621 } |
| 1594 | 1622 |
| 1595 | 1623 |
| 1596 // The stack has been adjusted to fit all values for unoptimized frame. | 1624 // The stack has been adjusted to fit all values for unoptimized frame. |
| 1597 // Fill the unoptimized frame. | 1625 // Fill the unoptimized frame. |
| 1598 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeFillFrame, uword last_fp) { | 1626 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeFillFrame, uword last_fp) { |
| 1599 Isolate* isolate = Isolate::Current(); | 1627 Isolate* isolate = Isolate::Current(); |
| (...skipping 30 matching lines...) Expand all Loading... | |
| 1630 delete[] frame_copy; | 1658 delete[] frame_copy; |
| 1631 delete[] cpu_registers_copy; | 1659 delete[] cpu_registers_copy; |
| 1632 delete[] fpu_registers_copy; | 1660 delete[] fpu_registers_copy; |
| 1633 | 1661 |
| 1634 return caller_fp; | 1662 return caller_fp; |
| 1635 } | 1663 } |
| 1636 END_LEAF_RUNTIME_ENTRY | 1664 END_LEAF_RUNTIME_ENTRY |
| 1637 | 1665 |
| 1638 | 1666 |
| 1639 // This is the last step in the deoptimization, GC can occur. | 1667 // This is the last step in the deoptimization, GC can occur. |
| 1640 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterializeDoubles, 0) { | 1668 // Returns number of bytes to remove from the expression stack of the |
| 1641 DeferredObject* deferred_object = Isolate::Current()->DetachDeferredObjects(); | 1669 // bottom-most deoptimized frame. Those arguments were artificially injected |
| 1670 // under return address to keep them discoverable by GC that can occur during | |
| 1671 // materialization phase. | |
|
srdjan
2013/05/07 23:11:45
Add comment what it returns.
Vyacheslav Egorov (Google)
2013/05/07 23:28:21
The comment already starts with "Returns number" e
| |
| 1672 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { | |
| 1673 // First materialize all unboxed "primitive" values (doubles, mints, simd) | |
| 1674 // then materialize objects. The order is important: objects might be | |
| 1675 // referencing boxes allocated on the first step. | |
|
srdjan
2013/05/07 23:11:45
Add comment that deferred object cannot refer to o
Vyacheslav Egorov (Google)
2013/05/07 23:28:21
Done.
| |
| 1676 isolate->MaterializeDeferredBoxes(); | |
| 1677 isolate->MaterializeDeferredObjects(); | |
| 1642 | 1678 |
| 1643 while (deferred_object != NULL) { | 1679 // Compute total number of artificial arguments used during deoptimization. |
| 1644 DeferredObject* current = deferred_object; | 1680 intptr_t deopt_arguments = 0; |
| 1645 deferred_object = deferred_object->next(); | 1681 for (intptr_t i = 0; i < isolate->DeferredObjectsCount(); i++) { |
| 1682 deopt_arguments += isolate->GetDeferredObject(i)->ArgumentCount(); | |
| 1683 } | |
| 1684 Isolate::Current()->DeleteDeferredObjects(); | |
| 1646 | 1685 |
| 1647 current->Materialize(); | 1686 // Return value tells deoptimization stub to remove the given number of bytes |
| 1648 | 1687 // from the stack. |
| 1649 delete current; | 1688 arguments.SetReturn(Smi::Handle(Smi::New(deopt_arguments * kWordSize))); |
| 1650 } | |
| 1651 | 1689 |
| 1652 // Since this is the only step where GC can occur during deoptimization, | 1690 // Since this is the only step where GC can occur during deoptimization, |
| 1653 // use it to report the source line where deoptimization occured. | 1691 // use it to report the source line where deoptimization occured. |
| 1654 if (FLAG_trace_deoptimization) { | 1692 if (FLAG_trace_deoptimization) { |
| 1655 DartFrameIterator iterator; | 1693 DartFrameIterator iterator; |
| 1656 StackFrame* top_frame = iterator.NextFrame(); | 1694 StackFrame* top_frame = iterator.NextFrame(); |
| 1657 ASSERT(top_frame != NULL); | 1695 ASSERT(top_frame != NULL); |
| 1658 const Code& code = Code::Handle(top_frame->LookupDartCode()); | 1696 const Code& code = Code::Handle(top_frame->LookupDartCode()); |
| 1659 const Function& top_function = Function::Handle(code.function()); | 1697 const Function& top_function = Function::Handle(code.function()); |
| 1660 const Script& script = Script::Handle(top_function.script()); | 1698 const Script& script = Script::Handle(top_function.script()); |
| (...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1704 // Arg1: Value that is being stored. | 1742 // Arg1: Value that is being stored. |
| 1705 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { | 1743 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { |
| 1706 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); | 1744 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); |
| 1707 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); | 1745 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); |
| 1708 const Object& value = Object::Handle(arguments.ArgAt(1)); | 1746 const Object& value = Object::Handle(arguments.ArgAt(1)); |
| 1709 | 1747 |
| 1710 field.UpdateCid(Class::Handle(value.clazz()).id()); | 1748 field.UpdateCid(Class::Handle(value.clazz()).id()); |
| 1711 } | 1749 } |
| 1712 | 1750 |
| 1713 } // namespace dart | 1751 } // namespace dart |
| OLD | NEW |