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