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

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

Issue 15110003: Make deoptimization architecture dependent (it depends on the frame layout). (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 7 years, 7 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/deopt_instructions.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 1471 matching lines...) Expand 10 before | Expand all | Expand 10 after
1482 1482
1483 // Copy optimized frame into the isolate buffer. 1483 // Copy optimized frame into the isolate buffer.
1484 // The first incoming argument is stored at the last entry in the 1484 // The first incoming argument is stored at the last entry in the
1485 // copied frame buffer. 1485 // copied frame buffer.
1486 static void CopyFrame(const Code& optimized_code, const StackFrame& frame) { 1486 static void CopyFrame(const Code& optimized_code, const StackFrame& frame) {
1487 const Function& function = Function::Handle(optimized_code.function()); 1487 const Function& function = Function::Handle(optimized_code.function());
1488 // Do not copy incoming arguments if there are optional arguments (they 1488 // Do not copy incoming arguments if there are optional arguments (they
1489 // are copied into local space at method entry). 1489 // are copied into local space at method entry).
1490 const intptr_t num_args = 1490 const intptr_t num_args =
1491 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); 1491 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
1492 // FP, PC-marker and return-address will be copied as well. 1492 // The fixed size section of the (fake) Dart frame called via a stub by the
1493 // optimized function contains FP, PP (ARM and MIPS only), PC-marker and
1494 // return-address. This section is copied as well, so that its contained
1495 // values can be updated before returning to the deoptimized function.
1493 const intptr_t frame_copy_size = 1496 const intptr_t frame_copy_size =
1494 // Deoptimized function's return address: caller_frame->pc(). 1497 + kDartFrameFixedSize // For saved values below sp.
1495 - kSavedPcSlotFromSp 1498 + ((frame.fp() - frame.sp()) / kWordSize) // For frame size incl. sp.
1496 + ((frame.fp() - frame.sp()) / kWordSize)
1497 + 1 // For fp. 1499 + 1 // For fp.
1498 + kParamEndSlotFromFp 1500 + kParamEndSlotFromFp // For saved values above fp.
1499 + num_args; 1501 + num_args; // For arguments.
1500 intptr_t* frame_copy = new intptr_t[frame_copy_size]; 1502 intptr_t* frame_copy = new intptr_t[frame_copy_size];
1501 ASSERT(frame_copy != NULL); 1503 ASSERT(frame_copy != NULL);
1502 // Include the return address of optimized code.
1503 intptr_t* start = reinterpret_cast<intptr_t*>( 1504 intptr_t* start = reinterpret_cast<intptr_t*>(
1504 frame.sp() + (kSavedPcSlotFromSp * kWordSize)); 1505 frame.sp() - (kDartFrameFixedSize * kWordSize));
1505 for (intptr_t i = 0; i < frame_copy_size; i++) { 1506 for (intptr_t i = 0; i < frame_copy_size; i++) {
1506 frame_copy[i] = *(start + i); 1507 frame_copy[i] = *(start + i);
1507 } 1508 }
1508 Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size); 1509 Isolate::Current()->SetDeoptFrameCopy(frame_copy, frame_copy_size);
1509 } 1510 }
1510 1511
1511 1512
1512 // Copies saved registers and caller's frame into temporary buffers. 1513 // Copies saved registers and caller's frame into temporary buffers.
1513 // Returns the stack size of unoptimized frame. 1514 // Returns the stack size of unoptimized frame.
1514 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame, 1515 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeCopyFrame,
1515 uword saved_registers_address) { 1516 uword saved_registers_address) {
1516 Isolate* isolate = Isolate::Current(); 1517 Isolate* isolate = Isolate::Current();
1517 StackZone zone(isolate); 1518 StackZone zone(isolate);
1518 HANDLESCOPE(isolate); 1519 HANDLESCOPE(isolate);
1519 1520
1520 // All registers have been saved below last-fp. 1521 // All registers have been saved below last-fp as if they were locals.
1521 // Note that the deopt stub is not allowed to save any other values (pc 1522 const uword last_fp = saved_registers_address
1522 // marker, pool pointer, alignment, etc...) below last-fp. 1523 + (kNumberOfCpuRegisters * kWordSize)
1523 const uword last_fp = saved_registers_address + 1524 + (kNumberOfFpuRegisters * kFpuRegisterSize)
1524 kNumberOfCpuRegisters * kWordSize + 1525 - ((kFirstLocalSlotFromFp + 1) * kWordSize);
1525 kNumberOfFpuRegisters * kFpuRegisterSize;
1526 CopySavedRegisters(saved_registers_address); 1526 CopySavedRegisters(saved_registers_address);
1527 1527
1528 // Get optimized code and frame that need to be deoptimized. 1528 // Get optimized code and frame that need to be deoptimized.
1529 DartFrameIterator iterator(last_fp); 1529 DartFrameIterator iterator(last_fp);
1530 StackFrame* caller_frame = iterator.NextFrame(); 1530 StackFrame* caller_frame = iterator.NextFrame();
1531 ASSERT(caller_frame != NULL); 1531 ASSERT(caller_frame != NULL);
1532 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); 1532 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
1533 ASSERT(optimized_code.is_optimized()); 1533 ASSERT(optimized_code.is_optimized());
1534 1534
1535 intptr_t deopt_reason = kDeoptUnknown; 1535 intptr_t deopt_reason = kDeoptUnknown;
(...skipping 12 matching lines...) Expand all
1548 function.ToFullyQualifiedCString(), 1548 function.ToFullyQualifiedCString(),
1549 function.deoptimization_counter()); 1549 function.deoptimization_counter());
1550 } 1550 }
1551 1551
1552 // Compute the stack size of the unoptimized frame. For functions with 1552 // Compute the stack size of the unoptimized frame. For functions with
1553 // optional arguments the deoptimization info does not describe the 1553 // optional arguments the deoptimization info does not describe the
1554 // incoming arguments. 1554 // incoming arguments.
1555 const Function& function = Function::Handle(optimized_code.function()); 1555 const Function& function = Function::Handle(optimized_code.function());
1556 const intptr_t num_args = 1556 const intptr_t num_args =
1557 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); 1557 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
1558 intptr_t unoptimized_stack_size = 1558 const intptr_t unoptimized_stack_size =
1559 + deopt_info.FrameSize() 1559 + deopt_info.FrameSize()
1560 - kDartFrameFixedSize
1560 - num_args 1561 - num_args
1561 - kParamEndSlotFromFp 1562 - kParamEndSlotFromFp
1562 - 1; // For fp. 1563 - 1; // For fp.
1563 return unoptimized_stack_size * kWordSize; 1564 return unoptimized_stack_size * kWordSize; // Stack size (FP - SP) in bytes.
1564 } 1565 }
1565 END_LEAF_RUNTIME_ENTRY 1566 END_LEAF_RUNTIME_ENTRY
1566 1567
1567 1568
1568 static intptr_t DeoptimizeWithDeoptInfo(const Code& code, 1569 static void DeoptimizeWithDeoptInfo(const Code& code,
1569 const DeoptInfo& deopt_info, 1570 const DeoptInfo& deopt_info,
1570 const StackFrame& caller_frame, 1571 const StackFrame& caller_frame,
1571 intptr_t deopt_reason) { 1572 intptr_t deopt_reason) {
1572 const intptr_t len = deopt_info.TranslationLength(); 1573 const intptr_t len = deopt_info.TranslationLength();
1573 GrowableArray<DeoptInstr*> deopt_instructions(len); 1574 GrowableArray<DeoptInstr*> deopt_instructions(len);
1574 const Array& deopt_table = Array::Handle(code.deopt_info_array()); 1575 const Array& deopt_table = Array::Handle(code.deopt_info_array());
1575 ASSERT(!deopt_table.IsNull()); 1576 ASSERT(!deopt_table.IsNull());
1576 deopt_info.ToInstructions(deopt_table, &deopt_instructions); 1577 deopt_info.ToInstructions(deopt_table, &deopt_instructions);
1577 1578
1578 intptr_t* start = reinterpret_cast<intptr_t*>( 1579 intptr_t* start = reinterpret_cast<intptr_t*>(
1579 caller_frame.sp() + (kSavedPcSlotFromSp * kWordSize)); 1580 caller_frame.sp() - (kDartFrameFixedSize * kWordSize));
1580 const Function& function = Function::Handle(code.function()); 1581 const Function& function = Function::Handle(code.function());
1581 const intptr_t num_args = 1582 const intptr_t num_args =
1582 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters(); 1583 function.HasOptionalParameters() ? 0 : function.num_fixed_parameters();
1583 const intptr_t to_frame_size = 1584 const intptr_t to_frame_size =
1584 - kSavedPcSlotFromSp // Deoptimized function's return address. 1585 + kDartFrameFixedSize // For saved values below sp.
1585 + (caller_frame.fp() - caller_frame.sp()) / kWordSize 1586 + (caller_frame.fp() - caller_frame.sp()) / kWordSize
1586 + 1 // For fp. 1587 + 1 // For fp.
1587 + kParamEndSlotFromFp 1588 + kParamEndSlotFromFp
1588 + num_args; 1589 + num_args;
1589 DeoptimizationContext deopt_context(start, 1590 DeoptimizationContext deopt_context(start,
1590 to_frame_size, 1591 to_frame_size,
1591 Array::Handle(code.object_table()), 1592 Array::Handle(code.object_table()),
1592 num_args, 1593 num_args,
1593 static_cast<DeoptReasonId>(deopt_reason)); 1594 static_cast<DeoptReasonId>(deopt_reason));
1594 const intptr_t frame_size = deopt_info.FrameSize(); 1595 const intptr_t frame_size = deopt_info.FrameSize();
1595 1596
1596 // All kMaterializeObject instructions are emitted before the instructions 1597 // All kMaterializeObject instructions are emitted before the instructions
1597 // that describe stack frames. Skip them and defer materialization of 1598 // that describe stack frames. Skip them and defer materialization of
1598 // objects until the frame is fully reconstructed and it is safe to perform 1599 // objects until the frame is fully reconstructed and it is safe to perform
1599 // GC. 1600 // GC.
1600 // Arguments (class of the instance to allocate and field-value pairs) are 1601 // Arguments (class of the instance to allocate and field-value pairs) are
1601 // described as part of the expression stack for the bottom-most deoptimized 1602 // described as part of the expression stack for the bottom-most deoptimized
1602 // frame. They will be used during materialization and removed from the stack 1603 // frame. They will be used during materialization and removed from the stack
1603 // right before control switches to the unoptimized code. 1604 // right before control switches to the unoptimized code.
1604 const intptr_t num_materializations = len - frame_size; 1605 const intptr_t num_materializations = len - frame_size;
1605 Isolate::Current()->PrepareForDeferredMaterialization(num_materializations); 1606 Isolate::Current()->PrepareForDeferredMaterialization(num_materializations);
1606 for (intptr_t from_index = 0, to_index = 1; 1607 for (intptr_t from_index = 0, to_index = kDartFrameFixedSize;
1607 from_index < num_materializations; 1608 from_index < num_materializations;
1608 from_index++) { 1609 from_index++) {
1609 const intptr_t field_count = 1610 const intptr_t field_count =
1610 DeoptInstr::GetFieldCount(deopt_instructions[from_index]); 1611 DeoptInstr::GetFieldCount(deopt_instructions[from_index]);
1611 intptr_t* args = deopt_context.GetToFrameAddressAt(to_index); 1612 intptr_t* args = deopt_context.GetToFrameAddressAt(to_index);
1612 DeferredObject* obj = new DeferredObject(field_count, args); 1613 DeferredObject* obj = new DeferredObject(field_count, args);
1613 Isolate::Current()->SetDeferredObjectAt(from_index, obj); 1614 Isolate::Current()->SetDeferredObjectAt(from_index, obj);
1614 to_index += obj->ArgumentCount(); 1615 to_index += obj->ArgumentCount();
1615 } 1616 }
1616 1617
1617 // Populate stack frames. 1618 // Populate stack frames.
1618 for (intptr_t to_index = frame_size - 1, from_index = len - 1; 1619 for (intptr_t to_index = frame_size - 1, from_index = len - 1;
1619 to_index >= 0; 1620 to_index >= 0;
1620 to_index--, from_index--) { 1621 to_index--, from_index--) {
1621 intptr_t* to_addr = deopt_context.GetToFrameAddressAt(to_index); 1622 intptr_t* to_addr = deopt_context.GetToFrameAddressAt(to_index);
1622 deopt_instructions[from_index]->Execute(&deopt_context, to_addr); 1623 deopt_instructions[from_index]->Execute(&deopt_context, to_addr);
1623 } 1624 }
1624 1625
1625 if (FLAG_trace_deoptimization_verbose) { 1626 if (FLAG_trace_deoptimization_verbose) {
1626 for (intptr_t i = 0; i < frame_size; i++) { 1627 for (intptr_t i = 0; i < frame_size; i++) {
1627 OS::PrintErr("*%"Pd". [%"Px"] %#014"Px" [%s]\n", 1628 OS::PrintErr("*%"Pd". [%"Px"] %#014"Px" [%s]\n",
1628 i, 1629 i,
1629 reinterpret_cast<uword>(&start[i]), 1630 reinterpret_cast<uword>(&start[i]),
1630 start[i], 1631 start[i],
1631 deopt_instructions[i + (len - frame_size)]->ToCString()); 1632 deopt_instructions[i + (len - frame_size)]->ToCString());
1632 } 1633 }
1633 } 1634 }
1634 return deopt_context.GetCallerFp();
1635 } 1635 }
1636 1636
1637 1637
1638 // The stack has been adjusted to fit all values for unoptimized frame. 1638 // The stack has been adjusted to fit all values for unoptimized frame.
1639 // Fill the unoptimized frame. 1639 // Fill the unoptimized frame.
1640 DEFINE_LEAF_RUNTIME_ENTRY(intptr_t, DeoptimizeFillFrame, uword last_fp) { 1640 DEFINE_LEAF_RUNTIME_ENTRY(void, DeoptimizeFillFrame, uword last_fp) {
1641 Isolate* isolate = Isolate::Current(); 1641 Isolate* isolate = Isolate::Current();
1642 StackZone zone(isolate); 1642 StackZone zone(isolate);
1643 HANDLESCOPE(isolate); 1643 HANDLESCOPE(isolate);
1644 1644
1645 DartFrameIterator iterator(last_fp); 1645 DartFrameIterator iterator(last_fp);
1646 StackFrame* caller_frame = iterator.NextFrame(); 1646 StackFrame* caller_frame = iterator.NextFrame();
1647 ASSERT(caller_frame != NULL); 1647 ASSERT(caller_frame != NULL);
1648 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode()); 1648 const Code& optimized_code = Code::Handle(caller_frame->LookupDartCode());
1649 const Function& function = Function::Handle(optimized_code.function()); 1649 const Function& function = Function::Handle(optimized_code.function());
1650 ASSERT(!function.IsNull()); 1650 ASSERT(!function.IsNull());
1651 const Code& unoptimized_code = Code::Handle(function.unoptimized_code()); 1651 const Code& unoptimized_code = Code::Handle(function.unoptimized_code());
1652 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized()); 1652 ASSERT(!optimized_code.IsNull() && optimized_code.is_optimized());
1653 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized()); 1653 ASSERT(!unoptimized_code.IsNull() && !unoptimized_code.is_optimized());
1654 1654
1655 intptr_t* frame_copy = isolate->deopt_frame_copy(); 1655 intptr_t* frame_copy = isolate->deopt_frame_copy();
1656 intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy(); 1656 intptr_t* cpu_registers_copy = isolate->deopt_cpu_registers_copy();
1657 fpu_register_t* fpu_registers_copy = isolate->deopt_fpu_registers_copy(); 1657 fpu_register_t* fpu_registers_copy = isolate->deopt_fpu_registers_copy();
1658 1658
1659 intptr_t deopt_reason = kDeoptUnknown; 1659 intptr_t deopt_reason = kDeoptUnknown;
1660 const DeoptInfo& deopt_info = DeoptInfo::Handle( 1660 const DeoptInfo& deopt_info = DeoptInfo::Handle(
1661 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason)); 1661 optimized_code.GetDeoptInfoAtPc(caller_frame->pc(), &deopt_reason));
1662 ASSERT(!deopt_info.IsNull()); 1662 ASSERT(!deopt_info.IsNull());
1663 1663
1664 const intptr_t caller_fp = DeoptimizeWithDeoptInfo(optimized_code, 1664 DeoptimizeWithDeoptInfo(optimized_code,
1665 deopt_info, 1665 deopt_info,
1666 *caller_frame, 1666 *caller_frame,
1667 deopt_reason); 1667 deopt_reason);
1668 1668
1669 isolate->SetDeoptFrameCopy(NULL, 0); 1669 isolate->SetDeoptFrameCopy(NULL, 0);
1670 isolate->set_deopt_cpu_registers_copy(NULL); 1670 isolate->set_deopt_cpu_registers_copy(NULL);
1671 isolate->set_deopt_fpu_registers_copy(NULL); 1671 isolate->set_deopt_fpu_registers_copy(NULL);
1672 delete[] frame_copy; 1672 delete[] frame_copy;
1673 delete[] cpu_registers_copy; 1673 delete[] cpu_registers_copy;
1674 delete[] fpu_registers_copy; 1674 delete[] fpu_registers_copy;
1675
1676 return caller_fp;
1677 } 1675 }
1678 END_LEAF_RUNTIME_ENTRY 1676 END_LEAF_RUNTIME_ENTRY
1679 1677
1680 1678
1681 // This is the last step in the deoptimization, GC can occur. 1679 // This is the last step in the deoptimization, GC can occur.
1682 // Returns number of bytes to remove from the expression stack of the 1680 // Returns number of bytes to remove from the expression stack of the
1683 // bottom-most deoptimized frame. Those arguments were artificially injected 1681 // bottom-most deoptimized frame. Those arguments were artificially injected
1684 // under return address to keep them discoverable by GC that can occur during 1682 // under return address to keep them discoverable by GC that can occur during
1685 // materialization phase. 1683 // materialization phase.
1686 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) { 1684 DEFINE_RUNTIME_ENTRY(DeoptimizeMaterialize, 0) {
(...skipping 72 matching lines...) Expand 10 before | Expand all | Expand 10 after
1759 // Arg1: Value that is being stored. 1757 // Arg1: Value that is being stored.
1760 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) { 1758 DEFINE_RUNTIME_ENTRY(UpdateFieldCid, 2) {
1761 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count()); 1759 ASSERT(arguments.ArgCount() == kUpdateFieldCidRuntimeEntry.argument_count());
1762 const Field& field = Field::CheckedHandle(arguments.ArgAt(0)); 1760 const Field& field = Field::CheckedHandle(arguments.ArgAt(0));
1763 const Object& value = Object::Handle(arguments.ArgAt(1)); 1761 const Object& value = Object::Handle(arguments.ArgAt(1));
1764 1762
1765 field.UpdateCid(Class::Handle(value.clazz()).id()); 1763 field.UpdateCid(Class::Handle(value.clazz()).id());
1766 } 1764 }
1767 1765
1768 } // namespace dart 1766 } // namespace dart
OLDNEW
« no previous file with comments | « no previous file | runtime/vm/deopt_instructions.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698