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 1476 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1487 const intptr_t owner_cid = Class::Handle(Function::Handle( | 1487 const intptr_t owner_cid = Class::Handle(Function::Handle( |
| 1488 optimized_code.function()).Owner()).id(); | 1488 optimized_code.function()).Owner()).id(); |
| 1489 if (ContainsCid(classes, owner_cid)) { | 1489 if (ContainsCid(classes, owner_cid)) { |
| 1490 DeoptimizeAt(optimized_code, frame->pc()); | 1490 DeoptimizeAt(optimized_code, frame->pc()); |
| 1491 } | 1491 } |
| 1492 } | 1492 } |
| 1493 } | 1493 } |
| 1494 } | 1494 } |
| 1495 | 1495 |
| 1496 | 1496 |
| 1497 // Copy saved registers into the isolate buffer. | 1497 static void CopySavedRegisters(uword saved_registers_address, |
| 1498 static void CopySavedRegisters(uword saved_registers_address) { | 1498 fpu_register_t** fpu_registers, |
| 1499 intptr_t** cpu_registers) { | |
| 1499 ASSERT(sizeof(fpu_register_t) == kFpuRegisterSize); | 1500 ASSERT(sizeof(fpu_register_t) == kFpuRegisterSize); |
| 1500 fpu_register_t* fpu_registers_copy = | 1501 fpu_register_t* fpu_registers_copy = |
| 1501 new fpu_register_t[kNumberOfFpuRegisters]; | 1502 new fpu_register_t[kNumberOfFpuRegisters]; |
| 1502 ASSERT(fpu_registers_copy != NULL); | 1503 ASSERT(fpu_registers_copy != NULL); |
| 1503 for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) { | 1504 for (intptr_t i = 0; i < kNumberOfFpuRegisters; i++) { |
| 1504 fpu_registers_copy[i] = | 1505 fpu_registers_copy[i] = |
| 1505 *reinterpret_cast<fpu_register_t*>(saved_registers_address); | 1506 *reinterpret_cast<fpu_register_t*>(saved_registers_address); |
| 1506 saved_registers_address += kFpuRegisterSize; | 1507 saved_registers_address += kFpuRegisterSize; |
| 1507 } | 1508 } |
| 1508 Isolate::Current()->set_deopt_fpu_registers_copy(fpu_registers_copy); | 1509 *fpu_registers = fpu_registers_copy; |
| 1509 | 1510 |
| 1510 ASSERT(sizeof(intptr_t) == kWordSize); | 1511 ASSERT(sizeof(intptr_t) == kWordSize); |
| 1511 intptr_t* cpu_registers_copy = new intptr_t[kNumberOfCpuRegisters]; | 1512 intptr_t* cpu_registers_copy = new intptr_t[kNumberOfCpuRegisters]; |
| 1512 ASSERT(cpu_registers_copy != NULL); | 1513 ASSERT(cpu_registers_copy != NULL); |
| 1513 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { | 1514 for (intptr_t i = 0; i < kNumberOfCpuRegisters; i++) { |
| 1514 cpu_registers_copy[i] = | 1515 cpu_registers_copy[i] = |
| 1515 *reinterpret_cast<intptr_t*>(saved_registers_address); | 1516 *reinterpret_cast<intptr_t*>(saved_registers_address); |
| 1516 saved_registers_address += kWordSize; | 1517 saved_registers_address += kWordSize; |
| 1517 } | 1518 } |
| 1518 Isolate::Current()->set_deopt_cpu_registers_copy(cpu_registers_copy); | 1519 *cpu_registers = cpu_registers_copy; |
| 1519 } | 1520 } |
| 1520 | 1521 |
| 1521 | 1522 |
| 1522 // Copy optimized frame into the isolate buffer. | 1523 // Copy optimized frame into the DeoptContext.. |
| 1523 // The first incoming argument is stored at the last entry in the | 1524 // The first incoming argument is stored at the last entry in the |
| 1524 // copied frame buffer. | 1525 // copied frame buffer. |
| 1525 static void CopyFrame(const Code& optimized_code, const StackFrame& frame) { | 1526 static void CopyFrame(DeoptContext* deopt_context, |
| 1527 const Code& optimized_code, | |
| 1528 const StackFrame& frame) { | |
| 1526 const Function& function = Function::Handle(optimized_code.function()); | 1529 const Function& function = Function::Handle(optimized_code.function()); |
| 1527 // Do not copy incoming arguments if there are optional arguments (they | 1530 // Do not copy incoming arguments if there are optional arguments (they |
| 1528 // are copied into local space at method entry). | 1531 // are copied into local space at method entry). |
| 1529 const intptr_t num_args = | 1532 const intptr_t num_args = |
| 1530 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 1533 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 1531 // The fixed size section of the (fake) Dart frame called via a stub by the | 1534 // The fixed size section of the (fake) Dart frame called via a stub by the |
| 1532 // optimized function contains FP, PP (ARM and MIPS only), PC-marker and | 1535 // optimized function contains FP, PP (ARM and MIPS only), PC-marker and |
| 1533 // return-address. This section is copied as well, so that its contained | 1536 // return-address. This section is copied as well, so that its contained |
| 1534 // values can be updated before returning to the deoptimized function. | 1537 // values can be updated before returning to the deoptimized function. |
| 1535 const intptr_t frame_copy_size = | 1538 const intptr_t frame_copy_size = |
| 1536 + kDartFrameFixedSize // For saved values below sp. | 1539 + kDartFrameFixedSize // For saved values below sp. |
| 1537 + ((frame.fp() - frame.sp()) / kWordSize) // For frame size incl. sp. | 1540 + ((frame.fp() - frame.sp()) / kWordSize) // For frame size incl. sp. |
| 1538 + 1 // For fp. | 1541 + 1 // For fp. |
| 1539 + kParamEndSlotFromFp // For saved values above fp. | 1542 + kParamEndSlotFromFp // For saved values above fp. |
| 1540 + num_args; // For arguments. | 1543 + num_args; // For arguments. |
| 1541 intptr_t* frame_copy = new intptr_t[frame_copy_size]; | 1544 intptr_t* frame_copy = new intptr_t[frame_copy_size]; |
| 1542 ASSERT(frame_copy != NULL); | 1545 ASSERT(frame_copy != NULL); |
| 1543 intptr_t* start = reinterpret_cast<intptr_t*>( | 1546 intptr_t* start = reinterpret_cast<intptr_t*>( |
| 1544 frame.sp() - (kDartFrameFixedSize * kWordSize)); | 1547 frame.sp() - (kDartFrameFixedSize * kWordSize)); |
| 1545 for (intptr_t i = 0; i < frame_copy_size; i++) { | 1548 for (intptr_t i = 0; i < frame_copy_size; i++) { |
| 1546 frame_copy[i] = *(start + i); | 1549 frame_copy[i] = *(start + i); |
| 1547 } | 1550 } |
| 1548 Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size); | 1551 deopt_context->SetFromFrame(frame_copy, frame_copy_size); |
| 1549 } | 1552 } |
| 1550 | 1553 |
| 1551 | 1554 |
| 1552 // Copies saved registers and caller's frame into temporary buffers. | 1555 // Copies saved registers and caller's frame into temporary buffers. |
| 1553 // Returns the stack size of unoptimized frame. | 1556 // Returns the stack size of unoptimized frame. |
| 1554 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, | 1557 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, |
| 1555 1, uword saved_registers_address) { | 1558 1, uword saved_registers_address) { |
| 1556 Isolate* isolate = Isolate::Current(); | 1559 Isolate* isolate = Isolate::Current(); |
| 1557 StackZone zone(isolate); | 1560 StackZone zone(isolate); |
| 1558 HANDLESCOPE(isolate); | 1561 HANDLESCOPE(isolate); |
| 1559 | 1562 |
| 1560 // All registers have been saved below last-fp as if they were locals. | 1563 // All registers have been saved below last-fp as if they were locals. |
| 1561 const uword last_fp = saved_registers_address | 1564 const uword last_fp = saved_registers_address |
| 1562 + (kNumberOfCpuRegisters * kWordSize) | 1565 + (kNumberOfCpuRegisters * kWordSize) |
| 1563 + (kNumberOfFpuRegisters * kFpuRegisterSize) | 1566 + (kNumberOfFpuRegisters * kFpuRegisterSize) |
| 1564 - ((kFirstLocalSlotFromFp + 1) * kWordSize); | 1567 - ((kFirstLocalSlotFromFp + 1) * kWordSize); |
| 1565 CopySavedRegisters(saved_registers_address); | 1568 fpu_register_t* fpu_registers; |
| 1569 intptr_t* cpu_registers; | |
| 1570 CopySavedRegisters(saved_registers_address, &fpu_registers, &cpu_registers); | |
| 1566 | 1571 |
| 1567 // Get optimized code and frame that need to be deoptimized. | 1572 // Get optimized code and frame that need to be deoptimized. |
| 1568 DartFrameIterator iterator(last_fp); | 1573 DartFrameIterator iterator(last_fp); |
| 1569 StackFrame* caller_frame = iterator.NextFrame(); | 1574 StackFrame* caller_frame = iterator.NextFrame(); |
| 1570 ASSERT(caller_frame != NULL); | 1575 ASSERT(caller_frame != NULL); |
| 1571 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1576 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
| 1572 ASSERT(optimized_code.is_optimized()); | 1577 ASSERT(optimized_code.is_optimized()); |
| 1573 | 1578 |
| 1574 intptr_t deopt_reason = kDeoptUnknown; | 1579 intptr_t deopt_reason = kDeoptUnknown; |
| 1575 const DeoptInfo& deopt_info = DeoptInfo::Handle( | 1580 const DeoptInfo& deopt_info = DeoptInfo::Handle( |
| 1576 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); | 1581 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); |
| 1577 ASSERT(!deopt_info.IsNull()); | 1582 ASSERT(!deopt_info.IsNull()); |
| 1578 | 1583 |
| 1579 CopyFrame(optimized_code, *caller_frame); | 1584 // Create the DeoptContext for this deoptimization. Store in isolate. |
| 1585 const Function& function = Function::Handle(optimized_code.function()); | |
| 1586 const intptr_t num_args = | |
| 1587 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | |
| 1588 DeoptContext* deopt_context = new DeoptContext( | |
| 1589 Array::Handle(optimized_code.object_table()), | |
| 1590 num_args, | |
| 1591 static_cast<DeoptReasonId>(deopt_reason)); | |
| 1592 isolate->set_deopt_context(deopt_context); | |
| 1593 | |
| 1594 // TODO(turnidge): Why can't I move CopySavedRegisters here? | |
| 1595 deopt_context->SetSavedRegisters(fpu_registers, cpu_registers); | |
|
Florian Schneider
2013/09/30 11:32:29
Wouldn't it work to pass fpu_registers and cpu_reg
turnidge
2013/09/30 17:40:22
See next reply for full discussion.
| |
| 1596 CopyFrame(deopt_context, optimized_code, *caller_frame); | |
|
Florian Schneider
2013/09/30 11:32:29
It is quite confusing that the different members o
turnidge
2013/09/30 17:40:22
SetToFrame is done in the following runtime call,
turnidge
2013/09/30 19:35:10
Okay, I have cleanup up the interface a bit here i
| |
| 1597 | |
| 1580 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | 1598 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| 1581 Function& function = Function::Handle(optimized_code.function()); | |
| 1582 OS::PrintErr( | 1599 OS::PrintErr( |
| 1583 "Deoptimizing (reason %" Pd " '%s') at pc %#" Px " '%s' (count %d)\n", | 1600 "Deoptimizing (reason %" Pd " '%s') at pc %#" Px " '%s' (count %d)\n", |
| 1584 deopt_reason, | 1601 deopt_reason, |
| 1585 DeoptReasonToText(deopt_reason), | 1602 DeoptReasonToText(deopt_reason), |
| 1586 caller_frame->pc(), | 1603 caller_frame->pc(), |
| 1587 function.ToFullyQualifiedCString(), | 1604 function.ToFullyQualifiedCString(), |
| 1588 function.deoptimization_counter()); | 1605 function.deoptimization_counter()); |
| 1589 } | 1606 } |
| 1590 | 1607 |
| 1591 // Compute the stack size of the unoptimized frame. For functions with | 1608 // Compute the stack size of the unoptimized frame. For functions with |
| 1592 // optional arguments the deoptimization info does not describe the | 1609 // optional arguments the deoptimization info does not describe the |
| 1593 // incoming arguments. | 1610 // incoming arguments. |
| 1594 const Function& function = Function::Handle(optimized_code.function()); | |
| 1595 const intptr_t num_args = | |
| 1596 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | |
| 1597 const intptr_t unoptimized_stack_size = | 1611 const intptr_t unoptimized_stack_size = |
| 1598 + deopt_info.FrameSize() | 1612 + deopt_info.FrameSize() |
| 1599 - kDartFrameFixedSize | 1613 - kDartFrameFixedSize |
| 1600 - num_args | 1614 - num_args |
| 1601 - kParamEndSlotFromFp | 1615 - kParamEndSlotFromFp |
| 1602 - 1; // For fp. | 1616 - 1; // For fp. |
| 1603 return unoptimized_stack_size * kWordSize; // Stack size (FP - SP) in bytes. | 1617 return unoptimized_stack_size * kWordSize; // Stack size (FP - SP) in bytes. |
| 1604 } | 1618 } |
| 1605 END_LEAF_RUNTIME_ENTRY | 1619 END_LEAF_RUNTIME_ENTRY |
| 1606 | 1620 |
| 1607 | 1621 |
| 1608 static void DeoptimizeWithDeoptInfo(const Code& code, | 1622 static void DeoptimizeWithDeoptInfo(DeoptContext* deopt_context, |
| 1623 const Code& code, | |
| 1609 const DeoptInfo& deopt_info, | 1624 const DeoptInfo& deopt_info, |
| 1610 const StackFrame& caller_frame, | 1625 const StackFrame& caller_frame) { |
| 1611 intptr_t deopt_reason) { | |
| 1612 const intptr_t len = deopt_info.TranslationLength(); | 1626 const intptr_t len = deopt_info.TranslationLength(); |
| 1613 GrowableArray<DeoptInstr*> deopt_instructions(len); | 1627 GrowableArray<DeoptInstr*> deopt_instructions(len); |
| 1614 const Array& deopt_table = Array::Handle(code.deopt_info_array()); | 1628 const Array& deopt_table = Array::Handle(code.deopt_info_array()); |
| 1615 ASSERT(!deopt_table.IsNull()); | 1629 ASSERT(!deopt_table.IsNull()); |
| 1616 deopt_info.ToInstructions(deopt_table, &deopt_instructions); | 1630 deopt_info.ToInstructions(deopt_table, &deopt_instructions); |
| 1617 | 1631 |
| 1618 intptr_t* start = reinterpret_cast<intptr_t*>( | 1632 intptr_t* start = reinterpret_cast<intptr_t*>( |
| 1619 caller_frame.sp() - (kDartFrameFixedSize * kWordSize)); | 1633 caller_frame.sp() - (kDartFrameFixedSize * kWordSize)); |
| 1620 const Function& function = Function::Handle(code.function()); | 1634 const Function& function = Function::Handle(code.function()); |
| 1621 const intptr_t num_args = | 1635 const intptr_t num_args = |
| 1622 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); | 1636 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); |
| 1623 const intptr_t to_frame_size = | 1637 const intptr_t to_frame_size = |
| 1624 + kDartFrameFixedSize // For saved values below sp. | 1638 + kDartFrameFixedSize // For saved values below sp. |
| 1625 + (caller_frame.fp() - caller_frame.sp()) / kWordSize | 1639 + (caller_frame.fp() - caller_frame.sp()) / kWordSize |
| 1626 + 1 // For fp. | 1640 + 1 // For fp. |
| 1627 + kParamEndSlotFromFp | 1641 + kParamEndSlotFromFp |
| 1628 + num_args; | 1642 + num_args; |
| 1629 DeoptimizationContext deopt_context(start, | 1643 |
| 1630 to_frame_size, | 1644 deopt_context->SetToFrame(start, to_frame_size); |
| 1631 Array::Handle(code.object_table()), | 1645 |
| 1632 num_args, | |
| 1633 static_cast<DeoptReasonId>(deopt_reason)); | |
| 1634 const intptr_t frame_size = deopt_info.FrameSize(); | 1646 const intptr_t frame_size = deopt_info.FrameSize(); |
| 1635 | 1647 |
| 1636 // All kMaterializeObject instructions are emitted before the instructions | 1648 // All kMaterializeObject instructions are emitted before the instructions |
| 1637 // that describe stack frames. Skip them and defer materialization of | 1649 // that describe stack frames. Skip them and defer materialization of |
| 1638 // objects until the frame is fully reconstructed and it is safe to perform | 1650 // objects until the frame is fully reconstructed and it is safe to perform |
| 1639 // GC. | 1651 // GC. |
| 1640 // Arguments (class of the instance to allocate and field-value pairs) are | 1652 // Arguments (class of the instance to allocate and field-value pairs) are |
| 1641 // described as part of the expression stack for the bottom-most deoptimized | 1653 // described as part of the expression stack for the bottom-most deoptimized |
| 1642 // frame. They will be used during materialization and removed from the stack | 1654 // frame. They will be used during materialization and removed from the stack |
| 1643 // right before control switches to the unoptimized code. | 1655 // right before control switches to the unoptimized code. |
| 1644 const intptr_t num_materializations = len - frame_size; | 1656 const intptr_t num_materializations = len - frame_size; |
| 1645 Isolate::Current()->PrepareForDeferredMaterialization(num_materializations); | 1657 deopt_context->PrepareForDeferredMaterialization(num_materializations); |
| 1646 for (intptr_t from_index = 0, to_index = kDartFrameFixedSize; | 1658 for (intptr_t from_index = 0, to_index = kDartFrameFixedSize; |
| 1647 from_index < num_materializations; | 1659 from_index < num_materializations; |
| 1648 from_index++) { | 1660 from_index++) { |
| 1649 const intptr_t field_count = | 1661 const intptr_t field_count = |
| 1650 DeoptInstr::GetFieldCount(deopt_instructions[from_index]); | 1662 DeoptInstr::GetFieldCount(deopt_instructions[from_index]); |
| 1651 intptr_t* args = deopt_context.GetToFrameAddressAt(to_index); | 1663 intptr_t* args = deopt_context->GetToFrameAddressAt(to_index); |
| 1652 DeferredObject* obj = new DeferredObject(field_count, args); | 1664 DeferredObject* obj = new DeferredObject(field_count, args); |
| 1653 Isolate::Current()->SetDeferredObjectAt(from_index, obj); | 1665 deopt_context->SetDeferredObjectAt(from_index, obj); |
| 1654 to_index += obj->ArgumentCount(); | 1666 to_index += obj->ArgumentCount(); |
| 1655 } | 1667 } |
| 1656 | 1668 |
| 1657 // Populate stack frames. | 1669 // Populate stack frames. |
| 1658 for (intptr_t to_index = frame_size - 1, from_index = len - 1; | 1670 for (intptr_t to_index = frame_size - 1, from_index = len - 1; |
| 1659 to_index >= 0; | 1671 to_index >= 0; |
| 1660 to_index--, from_index--) { | 1672 to_index--, from_index--) { |
| 1661 intptr_t* to_addr = deopt_context.GetToFrameAddressAt(to_index); | 1673 intptr_t* to_addr = deopt_context->GetToFrameAddressAt(to_index); |
| 1662 deopt_instructions[from_index]->Execute(&deopt_context, to_addr); | 1674 deopt_instructions[from_index]->Execute(deopt_context, to_addr); |
| 1663 } | 1675 } |
| 1664 | 1676 |
| 1665 if (FLAG_trace_deoptimization_verbose) { | 1677 if (FLAG_trace_deoptimization_verbose) { |
| 1666 for (intptr_t i = 0; i < frame_size; i++) { | 1678 for (intptr_t i = 0; i < frame_size; i++) { |
| 1667 OS::PrintErr("*%" Pd ". [%" Px "] %#014" Px " [%s]\n", | 1679 OS::PrintErr("*%" Pd ". [%" Px "] %#014" Px " [%s]\n", |
| 1668 i, | 1680 i, |
| 1669 reinterpret_cast<uword>(&start[i]), | 1681 reinterpret_cast<uword>(&start[i]), |
| 1670 start[i], | 1682 start[i], |
| 1671 deopt_instructions[i + (len - frame_size)]->ToCString()); | 1683 deopt_instructions[i + (len - frame_size)]->ToCString()); |
| 1672 } | 1684 } |
| (...skipping 11 matching lines...) Expand all Loading... | |
| 1684 DartFrameIterator iterator(last_fp); | 1696 DartFrameIterator iterator(last_fp); |
| 1685 StackFrame* caller_frame = iterator.NextFrame(); | 1697 StackFrame* caller_frame = iterator.NextFrame(); |
| 1686 ASSERT(caller_frame != NULL); | 1698 ASSERT(caller_frame != NULL); |
| 1687 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); | 1699 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); |
| 1688 const Function& function = Function::Handle(optimized_code.function()); | 1700 const Function& function = Function::Handle(optimized_code.function()); |
| 1689 ASSERT(!function.IsNull()); | 1701 ASSERT(!function.IsNull()); |
| 1690 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); | 1702 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); |
| 1691 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); | 1703 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); |
| 1692 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); | 1704 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); |
| 1693 | 1705 |
| 1694 intptr_t* frame_copy = isolate->deopt_frame_copy(); | |
| 1695 intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy(); | |
| 1696 fpu_register_t* fpu_registers_copy = isolate->deopt_fpu_registers_copy(); | |
| 1697 | |
| 1698 intptr_t deopt_reason = kDeoptUnknown; | 1706 intptr_t deopt_reason = kDeoptUnknown; |
| 1699 const DeoptInfo& deopt_info = DeoptInfo::Handle( | 1707 const DeoptInfo& deopt_info = DeoptInfo::Handle( |
| 1700 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); | 1708 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); |
| 1701 ASSERT(!deopt_info.IsNull()); | 1709 ASSERT(!deopt_info.IsNull()); |
| 1702 | 1710 |
| 1703 DeoptimizeWithDeoptInfo(optimized_code, | 1711 DeoptContext* deopt_context = isolate->deopt_context(); |
| 1712 DeoptimizeWithDeoptInfo(deopt_context, | |
| 1713 optimized_code, | |
| 1704 deopt_info, | 1714 deopt_info, |
| 1705 *caller_frame, | 1715 *caller_frame); |
| 1706 deopt_reason); | |
| 1707 | |
| 1708 isolate->SetDeoptFrameCopy(NULL, 0); | |
| 1709 isolate->set_deopt_cpu_registers_copy(NULL); | |
| 1710 isolate->set_deopt_fpu_registers_copy(NULL); | |
| 1711 delete[] frame_copy; | |
| 1712 delete[] cpu_registers_copy; | |
| 1713 delete[] fpu_registers_copy; | |
| 1714 } | 1716 } |
| 1715 END_LEAF_RUNTIME_ENTRY | 1717 END_LEAF_RUNTIME_ENTRY |
| 1716 | 1718 |
| 1717 | 1719 |
| 1718 // This is the last step in the deoptimization, GC can occur. | 1720 // This is the last step in the deoptimization, GC can occur. |
| 1719 // Returns number of bytes to remove from the expression stack of the | 1721 // Returns number of bytes to remove from the expression stack of the |
| 1720 // bottom-most deoptimized frame. Those arguments were artificially injected | 1722 // bottom-most deoptimized frame. Those arguments were artificially injected |
| 1721 // under return address to keep them discoverable by GC that can occur during | 1723 // under return address to keep them discoverable by GC that can occur during |
| 1722 // materialization phase. | 1724 // materialization phase. |
| 1723 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { | 1725 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { |
| 1724 // First materialize all unboxed "primitive" values (doubles, mints, simd) | 1726 DeoptContext* deopt_context = isolate->deopt_context(); |
| 1725 // then materialize objects. The order is important: objects might be | |
| 1726 // referencing boxes allocated on the first step. At the same time | |
| 1727 // objects can't be referencing other deferred objects because storing | |
| 1728 // an object into a field is always conservatively treated as escaping by | |
| 1729 // allocation sinking and load forwarding. | |
| 1730 isolate->MaterializeDeferredBoxes(); | |
| 1731 isolate->MaterializeDeferredObjects(); | |
| 1732 | 1727 |
| 1733 // Compute total number of artificial arguments used during deoptimization. | 1728 intptr_t deopt_arg_count = deopt_context->MaterializeDeferredObjects(); |
| 1734 intptr_t deopt_arguments = 0; | 1729 |
| 1735 for (intptr_t i = 0; i < isolate->DeferredObjectsCount(); i++) { | 1730 // Delete temporary copies of frame and registers. |
| 1736 deopt_arguments += isolate->GetDeferredObject(i)->ArgumentCount(); | 1731 isolate->set_deopt_context(NULL); |
| 1737 } | 1732 delete[] deopt_context->from_frame(); // Allocated in CopyFrame. |
| 1738 Isolate::Current()->DeleteDeferredObjects(); | 1733 delete[] deopt_context->fpu_registers(); // Allocated in CopySavedRegisters. |
| 1734 delete[] deopt_context->cpu_registers(); // Allocated in CopySavedRegisters. | |
| 1735 delete deopt_context; | |
|
Florian Schneider
2013/09/30 11:32:29
Maybe change the destructor of DeoptContext so tha
turnidge
2013/09/30 17:40:22
I agree that it is unsightly to have this memory m
Ivan Posva
2013/09/30 18:00:01
Would it be possible to keep track whether these s
turnidge
2013/09/30 19:35:10
You and Florian are right here. Changed.
On 2013
| |
| 1739 | 1736 |
| 1740 // Return value tells deoptimization stub to remove the given number of bytes | 1737 // Return value tells deoptimization stub to remove the given number of bytes |
| 1741 // from the stack. | 1738 // from the stack. |
| 1742 arguments.SetReturn(Smi::Handle(Smi::New(deopt_arguments * kWordSize))); | 1739 arguments.SetReturn(Smi::Handle(Smi::New(deopt_arg_count * kWordSize))); |
| 1743 | 1740 |
| 1744 // Since this is the only step where GC can occur during deoptimization, | 1741 // Since this is the only step where GC can occur during deoptimization, |
| 1745 // use it to report the source line where deoptimization occured. | 1742 // use it to report the source line where deoptimization occured. |
| 1746 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { | 1743 if (FLAG_trace_deoptimization || FLAG_trace_deoptimization_verbose) { |
| 1747 DartFrameIterator iterator; | 1744 DartFrameIterator iterator; |
| 1748 StackFrame* top_frame = iterator.NextFrame(); | 1745 StackFrame* top_frame = iterator.NextFrame(); |
| 1749 ASSERT(top_frame != NULL); | 1746 ASSERT(top_frame != NULL); |
| 1750 const Code& code = Code::Handle(top_frame->LookupDartCode()); | 1747 const Code& code = Code::Handle(top_frame->LookupDartCode()); |
| 1751 const Function& top_function = Function::Handle(code.function()); | 1748 const Function& top_function = Function::Handle(code.function()); |
| 1752 const Script& script = Script::Handle(top_function.script()); | 1749 const Script& script = Script::Handle(top_function.script()); |
| 1753 const intptr_t token_pos = code.GetTokenIndexOfPC(top_frame->pc()); | 1750 const intptr_t token_pos = code.GetTokenIndexOfPC(top_frame->pc()); |
| 1754 intptr_t line, column; | 1751 intptr_t line, column; |
| 1755 script.GetTokenLocation(token_pos, &line, &column); | 1752 script.GetTokenLocation(token_pos, &line, &column); |
| 1756 String& line_string = String::Handle(script.GetLine(line)); | 1753 String& line_string = String::Handle(script.GetLine(line)); |
| 1757 OS::PrintErr(" Function: %s\n", top_function.ToFullyQualifiedCString()); | 1754 OS::PrintErr(" Function: %s\n", top_function.ToFullyQualifiedCString()); |
| 1758 OS::PrintErr(" Line %" Pd ": '%s'\n", line, line_string.ToCString()); | 1755 OS::PrintErr(" Line %" Pd ": '%s'\n", line, line_string.ToCString()); |
| 1759 OS::PrintErr(" Deopt args: %" Pd "\n", deopt_arguments); | 1756 OS::PrintErr(" Deopt args: %" Pd "\n", deopt_arg_count); |
| 1760 } | 1757 } |
| 1761 } | 1758 } |
| 1762 | 1759 |
| 1763 | 1760 |
| 1764 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, | 1761 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, |
| 1765 BigintCompare, | 1762 BigintCompare, |
| 1766 2, | 1763 2, |
| 1767 RawBigint* left, | 1764 RawBigint* left, |
| 1768 RawBigint* right) { | 1765 RawBigint* right) { |
| 1769 Isolate* isolate = Isolate::Current(); | 1766 Isolate* isolate = Isolate::Current(); |
| (...skipping 58 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 1828 field.UpdateCid(cid); | 1825 field.UpdateCid(cid); |
| 1829 intptr_t list_length = Field::kNoFixedLength; | 1826 intptr_t list_length = Field::kNoFixedLength; |
| 1830 if ((field.guarded_cid() != kDynamicCid) && | 1827 if ((field.guarded_cid() != kDynamicCid) && |
| 1831 field.is_final() && RawObject::IsBuiltinListClassId(cid)) { | 1828 field.is_final() && RawObject::IsBuiltinListClassId(cid)) { |
| 1832 list_length = GetListLength(value); | 1829 list_length = GetListLength(value); |
| 1833 } | 1830 } |
| 1834 field.UpdateLength(list_length); | 1831 field.UpdateLength(list_length); |
| 1835 } | 1832 } |
| 1836 | 1833 |
| 1837 } // namespace dart | 1834 } // namespace dart |
| OLD | NEW |