OLD | NEW |
1 // Copyright 2013 the V8 project authors. All rights reserved. | 1 // Copyright 2013 the V8 project authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "src/deoptimizer.h" | 5 #include "src/deoptimizer.h" |
6 | 6 |
7 #include "src/accessors.h" | 7 #include "src/accessors.h" |
8 #include "src/ast/prettyprinter.h" | 8 #include "src/ast/prettyprinter.h" |
9 #include "src/codegen.h" | 9 #include "src/codegen.h" |
10 #include "src/disasm.h" | 10 #include "src/disasm.h" |
(...skipping 948 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
959 value = output_[frame_index - 1]->GetConstantPool(); | 959 value = output_[frame_index - 1]->GetConstantPool(); |
960 } | 960 } |
961 output_frame->SetCallerConstantPool(output_offset, value); | 961 output_frame->SetCallerConstantPool(output_offset, value); |
962 DebugPrintOutputSlot(value, frame_index, output_offset, | 962 DebugPrintOutputSlot(value, frame_index, output_offset, |
963 "caller's constant_pool\n"); | 963 "caller's constant_pool\n"); |
964 } | 964 } |
965 | 965 |
966 // For the bottommost output frame the context can be gotten from the input | 966 // For the bottommost output frame the context can be gotten from the input |
967 // frame. For all subsequent output frames it can be gotten from the function | 967 // frame. For all subsequent output frames it can be gotten from the function |
968 // so long as we don't inline functions that need local contexts. | 968 // so long as we don't inline functions that need local contexts. |
969 Register context_reg = JavaScriptFrame::context_register(); | |
970 output_offset -= kPointerSize; | 969 output_offset -= kPointerSize; |
971 | 970 |
972 TranslatedFrame::iterator context_pos = value_iterator; | 971 TranslatedFrame::iterator context_pos = value_iterator; |
973 int context_input_index = input_index; | 972 int context_input_index = input_index; |
974 // When deoptimizing into a catch block, we need to take the context | 973 // When deoptimizing into a catch block, we need to take the context |
975 // from just above the top of the operand stack (we push the context | 974 // from just above the top of the operand stack (we push the context |
976 // at the entry of the try block). | 975 // at the entry of the try block). |
977 if (goto_catch_handler) { | 976 if (goto_catch_handler) { |
978 for (unsigned i = 0; i < height + 1; ++i) { | 977 for (unsigned i = 0; i < height + 1; ++i) { |
979 context_pos++; | 978 context_pos++; |
980 context_input_index++; | 979 context_input_index++; |
981 } | 980 } |
982 } | 981 } |
983 // Read the context from the translations. | 982 // Read the context from the translations. |
984 Object* context = context_pos->GetRawValue(); | 983 Object* context = context_pos->GetRawValue(); |
985 if (context == isolate_->heap()->undefined_value()) { | 984 if (context == isolate_->heap()->undefined_value()) { |
986 // If the context was optimized away, just use the context from | 985 // If the context was optimized away, just use the context from |
987 // the activation. This should only apply to Crankshaft code. | 986 // the activation. This should only apply to Crankshaft code. |
988 CHECK(!compiled_code_->is_turbofanned()); | 987 CHECK(!compiled_code_->is_turbofanned()); |
989 context = is_bottommost ? reinterpret_cast<Object*>(input_frame_context_) | 988 context = is_bottommost ? reinterpret_cast<Object*>(input_frame_context_) |
990 : function->context(); | 989 : function->context(); |
991 } | 990 } |
992 value = reinterpret_cast<intptr_t>(context); | 991 value = reinterpret_cast<intptr_t>(context); |
993 output_frame->SetContext(value); | 992 output_frame->SetContext(value); |
994 if (is_topmost) output_frame->SetRegister(context_reg.code(), value); | 993 if (is_topmost) { |
| 994 Register context_reg = JavaScriptFrame::context_register(); |
| 995 output_frame->SetRegister(context_reg.code(), value); |
| 996 } |
995 WriteValueToOutput(context, context_input_index, frame_index, output_offset, | 997 WriteValueToOutput(context, context_input_index, frame_index, output_offset, |
996 "context "); | 998 "context "); |
997 if (context == isolate_->heap()->arguments_marker()) { | 999 if (context == isolate_->heap()->arguments_marker()) { |
998 Address output_address = | 1000 Address output_address = |
999 reinterpret_cast<Address>(output_[frame_index]->GetTop()) + | 1001 reinterpret_cast<Address>(output_[frame_index]->GetTop()) + |
1000 output_offset; | 1002 output_offset; |
1001 values_to_materialize_.push_back({output_address, context_pos}); | 1003 values_to_materialize_.push_back({output_address, context_pos}); |
1002 } | 1004 } |
1003 value_iterator++; | 1005 value_iterator++; |
1004 input_index++; | 1006 input_index++; |
(...skipping 479 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
1484 new_caller_frame_top); | 1486 new_caller_frame_top); |
1485 } | 1487 } |
1486 caller_frame_top_ = new_caller_frame_top; | 1488 caller_frame_top_ = new_caller_frame_top; |
1487 caller_fp_ = adaptor_caller_fp; | 1489 caller_fp_ = adaptor_caller_fp; |
1488 caller_pc_ = adaptor_caller_pc; | 1490 caller_pc_ = adaptor_caller_pc; |
1489 } | 1491 } |
1490 | 1492 |
1491 void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame, | 1493 void Deoptimizer::DoComputeConstructStubFrame(TranslatedFrame* translated_frame, |
1492 int frame_index) { | 1494 int frame_index) { |
1493 TranslatedFrame::iterator value_iterator = translated_frame->begin(); | 1495 TranslatedFrame::iterator value_iterator = translated_frame->begin(); |
| 1496 bool is_topmost = (output_count_ - 1 == frame_index); |
| 1497 // The construct frame could become topmost only if we inlined a constructor |
| 1498 // call which does a tail call (otherwise the tail callee's frame would be |
| 1499 // the topmost one). So it could only be the LAZY case. |
| 1500 CHECK(!is_topmost || bailout_type_ == LAZY); |
1494 int input_index = 0; | 1501 int input_index = 0; |
1495 | 1502 |
1496 Builtins* builtins = isolate_->builtins(); | 1503 Builtins* builtins = isolate_->builtins(); |
1497 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); | 1504 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); |
1498 unsigned height = translated_frame->height(); | 1505 unsigned height = translated_frame->height(); |
1499 unsigned height_in_bytes = height * kPointerSize; | 1506 unsigned height_in_bytes = height * kPointerSize; |
| 1507 |
| 1508 // If the construct frame appears to be topmost we should ensure that the |
| 1509 // value of result register is preserved during continuation execution. |
| 1510 // We do this here by "pushing" the result of the constructor function to the |
| 1511 // top of the reconstructed stack and then using the |
| 1512 // FullCodeGenerator::TOS_REG machinery. |
| 1513 if (is_topmost) { |
| 1514 height_in_bytes += kPointerSize; |
| 1515 } |
| 1516 |
1500 // Skip function. | 1517 // Skip function. |
1501 value_iterator++; | 1518 value_iterator++; |
1502 input_index++; | 1519 input_index++; |
1503 if (trace_scope_ != NULL) { | 1520 if (trace_scope_ != NULL) { |
1504 PrintF(trace_scope_->file(), | 1521 PrintF(trace_scope_->file(), |
1505 " translating construct stub => height=%d\n", height_in_bytes); | 1522 " translating construct stub => height=%d\n", height_in_bytes); |
1506 } | 1523 } |
1507 | 1524 |
1508 unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize; | 1525 unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize; |
1509 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 1526 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
1510 | 1527 |
1511 // Allocate and store the output frame description. | 1528 // Allocate and store the output frame description. |
1512 FrameDescription* output_frame = | 1529 FrameDescription* output_frame = |
1513 new (output_frame_size) FrameDescription(output_frame_size); | 1530 new (output_frame_size) FrameDescription(output_frame_size); |
1514 output_frame->SetFrameType(StackFrame::CONSTRUCT); | 1531 output_frame->SetFrameType(StackFrame::CONSTRUCT); |
1515 | 1532 |
1516 // Construct stub can not be topmost or bottommost. | 1533 // Construct stub can not be topmost. |
1517 DCHECK(frame_index > 0 && frame_index < output_count_ - 1); | 1534 DCHECK(frame_index > 0 && frame_index < output_count_); |
1518 DCHECK(output_[frame_index] == NULL); | 1535 DCHECK(output_[frame_index] == NULL); |
1519 output_[frame_index] = output_frame; | 1536 output_[frame_index] = output_frame; |
1520 | 1537 |
1521 // The top address of the frame is computed from the previous frame's top and | 1538 // The top address of the frame is computed from the previous frame's top and |
1522 // this frame's size. | 1539 // this frame's size. |
1523 intptr_t top_address; | 1540 intptr_t top_address; |
1524 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 1541 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
1525 output_frame->SetTop(top_address); | 1542 output_frame->SetTop(top_address); |
1526 | 1543 |
1527 // Compute the incoming parameter translation. | 1544 // Compute the incoming parameter translation. |
(...skipping 14 matching lines...) Expand all Loading... |
1542 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); | 1559 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); |
1543 output_frame->SetCallerPc(output_offset, callers_pc); | 1560 output_frame->SetCallerPc(output_offset, callers_pc); |
1544 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n"); | 1561 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n"); |
1545 | 1562 |
1546 // Read caller's FP from the previous frame, and set this frame's FP. | 1563 // Read caller's FP from the previous frame, and set this frame's FP. |
1547 output_offset -= kFPOnStackSize; | 1564 output_offset -= kFPOnStackSize; |
1548 intptr_t value = output_[frame_index - 1]->GetFp(); | 1565 intptr_t value = output_[frame_index - 1]->GetFp(); |
1549 output_frame->SetCallerFp(output_offset, value); | 1566 output_frame->SetCallerFp(output_offset, value); |
1550 intptr_t fp_value = top_address + output_offset; | 1567 intptr_t fp_value = top_address + output_offset; |
1551 output_frame->SetFp(fp_value); | 1568 output_frame->SetFp(fp_value); |
| 1569 if (is_topmost) { |
| 1570 Register fp_reg = JavaScriptFrame::fp_register(); |
| 1571 output_frame->SetRegister(fp_reg.code(), fp_value); |
| 1572 } |
1552 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); | 1573 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); |
1553 | 1574 |
1554 if (FLAG_enable_embedded_constant_pool) { | 1575 if (FLAG_enable_embedded_constant_pool) { |
1555 // Read the caller's constant pool from the previous frame. | 1576 // Read the caller's constant pool from the previous frame. |
1556 output_offset -= kPointerSize; | 1577 output_offset -= kPointerSize; |
1557 value = output_[frame_index - 1]->GetConstantPool(); | 1578 value = output_[frame_index - 1]->GetConstantPool(); |
1558 output_frame->SetCallerConstantPool(output_offset, value); | 1579 output_frame->SetCallerConstantPool(output_offset, value); |
1559 DebugPrintOutputSlot(value, frame_index, output_offset, | 1580 DebugPrintOutputSlot(value, frame_index, output_offset, |
1560 "caller's constant_pool\n"); | 1581 "caller's constant_pool\n"); |
1561 } | 1582 } |
1562 | 1583 |
1563 // A marker value is used to mark the frame. | 1584 // A marker value is used to mark the frame. |
1564 output_offset -= kPointerSize; | 1585 output_offset -= kPointerSize; |
1565 value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT)); | 1586 value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT)); |
1566 output_frame->SetFrameSlot(output_offset, value); | 1587 output_frame->SetFrameSlot(output_offset, value); |
1567 DebugPrintOutputSlot(value, frame_index, output_offset, | 1588 DebugPrintOutputSlot(value, frame_index, output_offset, |
1568 "typed frame marker\n"); | 1589 "typed frame marker\n"); |
1569 | 1590 |
1570 // The context can be gotten from the previous frame. | 1591 // The context can be gotten from the previous frame. |
1571 output_offset -= kPointerSize; | 1592 output_offset -= kPointerSize; |
1572 value = output_[frame_index - 1]->GetContext(); | 1593 value = output_[frame_index - 1]->GetContext(); |
1573 output_frame->SetFrameSlot(output_offset, value); | 1594 output_frame->SetFrameSlot(output_offset, value); |
| 1595 if (is_topmost) { |
| 1596 Register context_reg = JavaScriptFrame::context_register(); |
| 1597 output_frame->SetRegister(context_reg.code(), value); |
| 1598 } |
1574 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n"); | 1599 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n"); |
1575 | 1600 |
1576 // The allocation site. | 1601 // The allocation site. |
1577 output_offset -= kPointerSize; | 1602 output_offset -= kPointerSize; |
1578 value = reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value()); | 1603 value = reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value()); |
1579 output_frame->SetFrameSlot(output_offset, value); | 1604 output_frame->SetFrameSlot(output_offset, value); |
1580 DebugPrintOutputSlot(value, frame_index, output_offset, "allocation site\n"); | 1605 DebugPrintOutputSlot(value, frame_index, output_offset, "allocation site\n"); |
1581 | 1606 |
1582 // Number of incoming arguments. | 1607 // Number of incoming arguments. |
1583 output_offset -= kPointerSize; | 1608 output_offset -= kPointerSize; |
1584 value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1)); | 1609 value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1)); |
1585 output_frame->SetFrameSlot(output_offset, value); | 1610 output_frame->SetFrameSlot(output_offset, value); |
1586 DebugPrintOutputSlot(value, frame_index, output_offset, "argc "); | 1611 DebugPrintOutputSlot(value, frame_index, output_offset, "argc "); |
1587 if (trace_scope_ != nullptr) { | 1612 if (trace_scope_ != nullptr) { |
1588 PrintF(trace_scope_->file(), "(%d)\n", height - 1); | 1613 PrintF(trace_scope_->file(), "(%d)\n", height - 1); |
1589 } | 1614 } |
1590 | 1615 |
1591 // The newly allocated object was passed as receiver in the artificial | 1616 // The newly allocated object was passed as receiver in the artificial |
1592 // constructor stub environment created by HEnvironment::CopyForInlining(). | 1617 // constructor stub environment created by HEnvironment::CopyForInlining(). |
1593 output_offset -= kPointerSize; | 1618 output_offset -= kPointerSize; |
1594 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); | 1619 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); |
1595 output_frame->SetFrameSlot(output_offset, value); | 1620 output_frame->SetFrameSlot(output_offset, value); |
1596 DebugPrintOutputSlot(value, frame_index, output_offset, | 1621 DebugPrintOutputSlot(value, frame_index, output_offset, |
1597 "allocated receiver\n"); | 1622 "allocated receiver\n"); |
1598 | 1623 |
| 1624 if (is_topmost) { |
| 1625 // Ensure the result is restored back when we return to the stub. |
| 1626 output_offset -= kPointerSize; |
| 1627 Register result_reg = FullCodeGenerator::result_register(); |
| 1628 value = input_->GetRegister(result_reg.code()); |
| 1629 output_frame->SetFrameSlot(output_offset, value); |
| 1630 DebugPrintOutputSlot(value, frame_index, output_offset, |
| 1631 "constructor result\n"); |
| 1632 |
| 1633 output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG)); |
| 1634 } |
| 1635 |
1599 CHECK_EQ(0u, output_offset); | 1636 CHECK_EQ(0u, output_offset); |
1600 | 1637 |
1601 intptr_t pc = reinterpret_cast<intptr_t>( | 1638 intptr_t pc = reinterpret_cast<intptr_t>( |
1602 construct_stub->instruction_start() + | 1639 construct_stub->instruction_start() + |
1603 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); | 1640 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); |
1604 output_frame->SetPc(pc); | 1641 output_frame->SetPc(pc); |
1605 if (FLAG_enable_embedded_constant_pool) { | 1642 if (FLAG_enable_embedded_constant_pool) { |
1606 intptr_t constant_pool_value = | 1643 intptr_t constant_pool_value = |
1607 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); | 1644 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); |
1608 output_frame->SetConstantPool(constant_pool_value); | 1645 output_frame->SetConstantPool(constant_pool_value); |
| 1646 if (is_topmost) { |
| 1647 Register constant_pool_reg = |
| 1648 JavaScriptFrame::constant_pool_pointer_register(); |
| 1649 output_frame->SetRegister(constant_pool_reg.code(), fp_value); |
| 1650 } |
| 1651 } |
| 1652 |
| 1653 // Set the continuation for the topmost frame. |
| 1654 if (is_topmost) { |
| 1655 Builtins* builtins = isolate_->builtins(); |
| 1656 DCHECK_EQ(LAZY, bailout_type_); |
| 1657 Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
| 1658 output_frame->SetContinuation( |
| 1659 reinterpret_cast<intptr_t>(continuation->entry())); |
1609 } | 1660 } |
1610 } | 1661 } |
1611 | 1662 |
1612 void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame, | 1663 void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame, |
1613 int frame_index, | 1664 int frame_index, |
1614 bool is_setter_stub_frame) { | 1665 bool is_setter_stub_frame) { |
1615 TranslatedFrame::iterator value_iterator = translated_frame->begin(); | 1666 TranslatedFrame::iterator value_iterator = translated_frame->begin(); |
| 1667 bool is_topmost = (output_count_ - 1 == frame_index); |
| 1668 // The accessor frame could become topmost only if we inlined an accessor |
| 1669 // call which does a tail call (otherwise the tail callee's frame would be |
| 1670 // the topmost one). So it could only be the LAZY case. |
| 1671 CHECK(!is_topmost || bailout_type_ == LAZY); |
1616 int input_index = 0; | 1672 int input_index = 0; |
1617 | 1673 |
1618 // Skip accessor. | 1674 // Skip accessor. |
1619 value_iterator++; | 1675 value_iterator++; |
1620 input_index++; | 1676 input_index++; |
1621 // The receiver (and the implicit return value, if any) are expected in | 1677 // The receiver (and the implicit return value, if any) are expected in |
1622 // registers by the LoadIC/StoreIC, so they don't belong to the output stack | 1678 // registers by the LoadIC/StoreIC, so they don't belong to the output stack |
1623 // frame. This means that we have to use a height of 0. | 1679 // frame. This means that we have to use a height of 0. |
1624 unsigned height = 0; | 1680 unsigned height = 0; |
1625 unsigned height_in_bytes = height * kPointerSize; | 1681 unsigned height_in_bytes = height * kPointerSize; |
| 1682 |
| 1683 // If the accessor frame appears to be topmost we should ensure that the |
| 1684 // value of result register is preserved during continuation execution. |
| 1685 // We do this here by "pushing" the result of the accessor function to the |
| 1686 // top of the reconstructed stack and then using the |
| 1687 // FullCodeGenerator::TOS_REG machinery. |
| 1688 // We don't need to restore the result in case of a setter call because we |
| 1689 // have to return the stored value but not the result of the setter function. |
| 1690 bool should_preserve_result = is_topmost && !is_setter_stub_frame; |
| 1691 if (should_preserve_result) { |
| 1692 height_in_bytes += kPointerSize; |
| 1693 } |
| 1694 |
1626 const char* kind = is_setter_stub_frame ? "setter" : "getter"; | 1695 const char* kind = is_setter_stub_frame ? "setter" : "getter"; |
1627 if (trace_scope_ != NULL) { | 1696 if (trace_scope_ != NULL) { |
1628 PrintF(trace_scope_->file(), | 1697 PrintF(trace_scope_->file(), |
1629 " translating %s stub => height=%u\n", kind, height_in_bytes); | 1698 " translating %s stub => height=%u\n", kind, height_in_bytes); |
1630 } | 1699 } |
1631 | 1700 |
1632 // We need 1 stack entry for the return address and enough entries for the | 1701 // We need 1 stack entry for the return address and enough entries for the |
1633 // StackFrame::INTERNAL (FP, frame type, context, code object and constant | 1702 // StackFrame::INTERNAL (FP, frame type, context, code object and constant |
1634 // pool (if enabled)- see MacroAssembler::EnterFrame). | 1703 // pool (if enabled)- see MacroAssembler::EnterFrame). |
1635 // For a setter stub frame we need one additional entry for the implicit | 1704 // For a setter stub frame we need one additional entry for the implicit |
1636 // return value, see StoreStubCompiler::CompileStoreViaSetter. | 1705 // return value, see StoreStubCompiler::CompileStoreViaSetter. |
1637 unsigned fixed_frame_entries = | 1706 unsigned fixed_frame_entries = |
1638 (StandardFrameConstants::kFixedFrameSize / kPointerSize) + 1 + | 1707 (StandardFrameConstants::kFixedFrameSize / kPointerSize) + 1 + |
1639 (is_setter_stub_frame ? 1 : 0); | 1708 (is_setter_stub_frame ? 1 : 0); |
1640 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize; | 1709 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize; |
1641 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 1710 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
1642 | 1711 |
1643 // Allocate and store the output frame description. | 1712 // Allocate and store the output frame description. |
1644 FrameDescription* output_frame = | 1713 FrameDescription* output_frame = |
1645 new (output_frame_size) FrameDescription(output_frame_size); | 1714 new (output_frame_size) FrameDescription(output_frame_size); |
1646 output_frame->SetFrameType(StackFrame::INTERNAL); | 1715 output_frame->SetFrameType(StackFrame::INTERNAL); |
1647 | 1716 |
1648 // A frame for an accessor stub can not be the topmost or bottommost one. | 1717 // A frame for an accessor stub can not be bottommost. |
1649 CHECK(frame_index > 0 && frame_index < output_count_ - 1); | 1718 CHECK(frame_index > 0 && frame_index < output_count_); |
1650 CHECK_NULL(output_[frame_index]); | 1719 CHECK_NULL(output_[frame_index]); |
1651 output_[frame_index] = output_frame; | 1720 output_[frame_index] = output_frame; |
1652 | 1721 |
1653 // The top address of the frame is computed from the previous frame's top and | 1722 // The top address of the frame is computed from the previous frame's top and |
1654 // this frame's size. | 1723 // this frame's size. |
1655 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 1724 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
1656 output_frame->SetTop(top_address); | 1725 output_frame->SetTop(top_address); |
1657 | 1726 |
1658 unsigned output_offset = output_frame_size; | 1727 unsigned output_offset = output_frame_size; |
1659 | 1728 |
1660 // Read caller's PC from the previous frame. | 1729 // Read caller's PC from the previous frame. |
1661 output_offset -= kPCOnStackSize; | 1730 output_offset -= kPCOnStackSize; |
1662 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); | 1731 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); |
1663 output_frame->SetCallerPc(output_offset, callers_pc); | 1732 output_frame->SetCallerPc(output_offset, callers_pc); |
1664 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n"); | 1733 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n"); |
1665 | 1734 |
1666 // Read caller's FP from the previous frame, and set this frame's FP. | 1735 // Read caller's FP from the previous frame, and set this frame's FP. |
1667 output_offset -= kFPOnStackSize; | 1736 output_offset -= kFPOnStackSize; |
1668 intptr_t value = output_[frame_index - 1]->GetFp(); | 1737 intptr_t value = output_[frame_index - 1]->GetFp(); |
1669 output_frame->SetCallerFp(output_offset, value); | 1738 output_frame->SetCallerFp(output_offset, value); |
1670 intptr_t fp_value = top_address + output_offset; | 1739 intptr_t fp_value = top_address + output_offset; |
1671 output_frame->SetFp(fp_value); | 1740 output_frame->SetFp(fp_value); |
| 1741 if (is_topmost) { |
| 1742 Register fp_reg = JavaScriptFrame::fp_register(); |
| 1743 output_frame->SetRegister(fp_reg.code(), fp_value); |
| 1744 } |
1672 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); | 1745 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); |
1673 | 1746 |
1674 if (FLAG_enable_embedded_constant_pool) { | 1747 if (FLAG_enable_embedded_constant_pool) { |
1675 // Read the caller's constant pool from the previous frame. | 1748 // Read the caller's constant pool from the previous frame. |
1676 output_offset -= kPointerSize; | 1749 output_offset -= kPointerSize; |
1677 value = output_[frame_index - 1]->GetConstantPool(); | 1750 value = output_[frame_index - 1]->GetConstantPool(); |
1678 output_frame->SetCallerConstantPool(output_offset, value); | 1751 output_frame->SetCallerConstantPool(output_offset, value); |
1679 DebugPrintOutputSlot(value, frame_index, output_offset, | 1752 DebugPrintOutputSlot(value, frame_index, output_offset, |
1680 "caller's constant_pool\n"); | 1753 "caller's constant_pool\n"); |
1681 } | 1754 } |
(...skipping 14 matching lines...) Expand all Loading... |
1696 Builtins::kLoadIC_Getter_ForDeopt; | 1769 Builtins::kLoadIC_Getter_ForDeopt; |
1697 Code* accessor_stub = isolate_->builtins()->builtin(name); | 1770 Code* accessor_stub = isolate_->builtins()->builtin(name); |
1698 value = reinterpret_cast<intptr_t>(accessor_stub); | 1771 value = reinterpret_cast<intptr_t>(accessor_stub); |
1699 output_frame->SetFrameSlot(output_offset, value); | 1772 output_frame->SetFrameSlot(output_offset, value); |
1700 DebugPrintOutputSlot(value, frame_index, output_offset, "code object\n"); | 1773 DebugPrintOutputSlot(value, frame_index, output_offset, "code object\n"); |
1701 | 1774 |
1702 // The context can be gotten from the previous frame. | 1775 // The context can be gotten from the previous frame. |
1703 output_offset -= kPointerSize; | 1776 output_offset -= kPointerSize; |
1704 value = output_[frame_index - 1]->GetContext(); | 1777 value = output_[frame_index - 1]->GetContext(); |
1705 output_frame->SetFrameSlot(output_offset, value); | 1778 output_frame->SetFrameSlot(output_offset, value); |
| 1779 if (is_topmost) { |
| 1780 Register context_reg = JavaScriptFrame::context_register(); |
| 1781 output_frame->SetRegister(context_reg.code(), value); |
| 1782 } |
1706 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n"); | 1783 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n"); |
1707 | 1784 |
1708 // Skip receiver. | 1785 // Skip receiver. |
1709 value_iterator++; | 1786 value_iterator++; |
1710 input_index++; | 1787 input_index++; |
1711 | 1788 |
1712 if (is_setter_stub_frame) { | 1789 if (is_setter_stub_frame) { |
1713 // The implicit return value was part of the artificial setter stub | 1790 // The implicit return value was part of the artificial setter stub |
1714 // environment. | 1791 // environment. |
1715 output_offset -= kPointerSize; | 1792 output_offset -= kPointerSize; |
1716 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, | 1793 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, |
1717 output_offset); | 1794 output_offset); |
1718 } | 1795 } |
1719 | 1796 |
| 1797 if (should_preserve_result) { |
| 1798 // Ensure the result is restored back when we return to the stub. |
| 1799 output_offset -= kPointerSize; |
| 1800 Register result_reg = FullCodeGenerator::result_register(); |
| 1801 value = input_->GetRegister(result_reg.code()); |
| 1802 output_frame->SetFrameSlot(output_offset, value); |
| 1803 DebugPrintOutputSlot(value, frame_index, output_offset, |
| 1804 "accessor result\n"); |
| 1805 |
| 1806 output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG)); |
| 1807 } else { |
| 1808 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); |
| 1809 } |
| 1810 |
1720 CHECK_EQ(0u, output_offset); | 1811 CHECK_EQ(0u, output_offset); |
1721 | 1812 |
1722 Smi* offset = is_setter_stub_frame ? | 1813 Smi* offset = is_setter_stub_frame ? |
1723 isolate_->heap()->setter_stub_deopt_pc_offset() : | 1814 isolate_->heap()->setter_stub_deopt_pc_offset() : |
1724 isolate_->heap()->getter_stub_deopt_pc_offset(); | 1815 isolate_->heap()->getter_stub_deopt_pc_offset(); |
1725 intptr_t pc = reinterpret_cast<intptr_t>( | 1816 intptr_t pc = reinterpret_cast<intptr_t>( |
1726 accessor_stub->instruction_start() + offset->value()); | 1817 accessor_stub->instruction_start() + offset->value()); |
1727 output_frame->SetPc(pc); | 1818 output_frame->SetPc(pc); |
1728 if (FLAG_enable_embedded_constant_pool) { | 1819 if (FLAG_enable_embedded_constant_pool) { |
1729 intptr_t constant_pool_value = | 1820 intptr_t constant_pool_value = |
1730 reinterpret_cast<intptr_t>(accessor_stub->constant_pool()); | 1821 reinterpret_cast<intptr_t>(accessor_stub->constant_pool()); |
1731 output_frame->SetConstantPool(constant_pool_value); | 1822 output_frame->SetConstantPool(constant_pool_value); |
| 1823 if (is_topmost) { |
| 1824 Register constant_pool_reg = |
| 1825 JavaScriptFrame::constant_pool_pointer_register(); |
| 1826 output_frame->SetRegister(constant_pool_reg.code(), fp_value); |
| 1827 } |
| 1828 } |
| 1829 |
| 1830 // Set the continuation for the topmost frame. |
| 1831 if (is_topmost) { |
| 1832 Builtins* builtins = isolate_->builtins(); |
| 1833 DCHECK_EQ(LAZY, bailout_type_); |
| 1834 Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
| 1835 output_frame->SetContinuation( |
| 1836 reinterpret_cast<intptr_t>(continuation->entry())); |
1732 } | 1837 } |
1733 } | 1838 } |
1734 | 1839 |
1735 void Deoptimizer::DoComputeCompiledStubFrame(TranslatedFrame* translated_frame, | 1840 void Deoptimizer::DoComputeCompiledStubFrame(TranslatedFrame* translated_frame, |
1736 int frame_index) { | 1841 int frame_index) { |
1737 // | 1842 // |
1738 // FROM TO | 1843 // FROM TO |
1739 // | .... | | .... | | 1844 // | .... | | .... | |
1740 // +-------------------------+ +-------------------------+ | 1845 // +-------------------------+ +-------------------------+ |
1741 // | JSFunction continuation | | JSFunction continuation | | 1846 // | JSFunction continuation | | JSFunction continuation | |
(...skipping 2066 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
3808 CHECK(value_info->IsMaterializedObject()); | 3913 CHECK(value_info->IsMaterializedObject()); |
3809 | 3914 |
3810 value_info->value_ = | 3915 value_info->value_ = |
3811 Handle<Object>(previously_materialized_objects->get(i), isolate_); | 3916 Handle<Object>(previously_materialized_objects->get(i), isolate_); |
3812 } | 3917 } |
3813 } | 3918 } |
3814 } | 3919 } |
3815 | 3920 |
3816 } // namespace internal | 3921 } // namespace internal |
3817 } // namespace v8 | 3922 } // namespace v8 |
OLD | NEW |