| 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); |
| 1499 // The construct frame could become topmost only if we inlined a constructor |
| 1500 // call which does a tail call (otherwise the tail callee's frame would be |
| 1501 // the topmost one). So it could only be the LAZY case. |
| 1502 CHECK(!is_topmost || bailout_type_ == LAZY); |
| 1496 int input_index = 0; | 1503 int input_index = 0; |
| 1497 | 1504 |
| 1498 Builtins* builtins = isolate_->builtins(); | 1505 Builtins* builtins = isolate_->builtins(); |
| 1499 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); | 1506 Code* construct_stub = builtins->builtin(Builtins::kJSConstructStubGeneric); |
| 1500 unsigned height = translated_frame->height(); | 1507 unsigned height = translated_frame->height(); |
| 1501 unsigned height_in_bytes = height * kPointerSize; | 1508 unsigned height_in_bytes = height * kPointerSize; |
| 1509 |
| 1510 // If the construct frame appears to be topmost we should ensure that the |
| 1511 // value of result register is preserved during continuation execution. |
| 1512 // We do this here by "pushing" the result of the constructor function to the |
| 1513 // top of the reconstructed stack and then using the |
| 1514 // FullCodeGenerator::TOS_REG machinery. |
| 1515 if (is_topmost) { |
| 1516 height_in_bytes += kPointerSize; |
| 1517 } |
| 1518 |
| 1502 // Skip function. | 1519 // Skip function. |
| 1503 value_iterator++; | 1520 value_iterator++; |
| 1504 input_index++; | 1521 input_index++; |
| 1505 if (trace_scope_ != NULL) { | 1522 if (trace_scope_ != NULL) { |
| 1506 PrintF(trace_scope_->file(), | 1523 PrintF(trace_scope_->file(), |
| 1507 " translating construct stub => height=%d\n", height_in_bytes); | 1524 " translating construct stub => height=%d\n", height_in_bytes); |
| 1508 } | 1525 } |
| 1509 | 1526 |
| 1510 unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize; | 1527 unsigned fixed_frame_size = ConstructFrameConstants::kFixedFrameSize; |
| 1511 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 1528 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
| 1512 | 1529 |
| 1513 // Allocate and store the output frame description. | 1530 // Allocate and store the output frame description. |
| 1514 FrameDescription* output_frame = | 1531 FrameDescription* output_frame = |
| 1515 new (output_frame_size) FrameDescription(output_frame_size); | 1532 new (output_frame_size) FrameDescription(output_frame_size); |
| 1516 output_frame->SetFrameType(StackFrame::CONSTRUCT); | 1533 output_frame->SetFrameType(StackFrame::CONSTRUCT); |
| 1517 | 1534 |
| 1518 // Construct stub can not be topmost or bottommost. | 1535 // Construct stub can not be topmost. |
| 1519 DCHECK(frame_index > 0 && frame_index < output_count_ - 1); | 1536 DCHECK(frame_index > 0 && frame_index < output_count_); |
| 1520 DCHECK(output_[frame_index] == NULL); | 1537 DCHECK(output_[frame_index] == NULL); |
| 1521 output_[frame_index] = output_frame; | 1538 output_[frame_index] = output_frame; |
| 1522 | 1539 |
| 1523 // The top address of the frame is computed from the previous frame's top and | 1540 // The top address of the frame is computed from the previous frame's top and |
| 1524 // this frame's size. | 1541 // this frame's size. |
| 1525 intptr_t top_address; | 1542 intptr_t top_address; |
| 1526 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 1543 top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
| 1527 output_frame->SetTop(top_address); | 1544 output_frame->SetTop(top_address); |
| 1528 | 1545 |
| 1529 // Compute the incoming parameter translation. | 1546 // Compute the incoming parameter translation. |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1544 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); | 1561 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); |
| 1545 output_frame->SetCallerPc(output_offset, callers_pc); | 1562 output_frame->SetCallerPc(output_offset, callers_pc); |
| 1546 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n"); | 1563 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n"); |
| 1547 | 1564 |
| 1548 // Read caller's FP from the previous frame, and set this frame's FP. | 1565 // Read caller's FP from the previous frame, and set this frame's FP. |
| 1549 output_offset -= kFPOnStackSize; | 1566 output_offset -= kFPOnStackSize; |
| 1550 intptr_t value = output_[frame_index - 1]->GetFp(); | 1567 intptr_t value = output_[frame_index - 1]->GetFp(); |
| 1551 output_frame->SetCallerFp(output_offset, value); | 1568 output_frame->SetCallerFp(output_offset, value); |
| 1552 intptr_t fp_value = top_address + output_offset; | 1569 intptr_t fp_value = top_address + output_offset; |
| 1553 output_frame->SetFp(fp_value); | 1570 output_frame->SetFp(fp_value); |
| 1571 if (is_topmost) { |
| 1572 Register fp_reg = JavaScriptFrame::fp_register(); |
| 1573 output_frame->SetRegister(fp_reg.code(), fp_value); |
| 1574 } |
| 1554 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); | 1575 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); |
| 1555 | 1576 |
| 1556 if (FLAG_enable_embedded_constant_pool) { | 1577 if (FLAG_enable_embedded_constant_pool) { |
| 1557 // Read the caller's constant pool from the previous frame. | 1578 // Read the caller's constant pool from the previous frame. |
| 1558 output_offset -= kPointerSize; | 1579 output_offset -= kPointerSize; |
| 1559 value = output_[frame_index - 1]->GetConstantPool(); | 1580 value = output_[frame_index - 1]->GetConstantPool(); |
| 1560 output_frame->SetCallerConstantPool(output_offset, value); | 1581 output_frame->SetCallerConstantPool(output_offset, value); |
| 1561 DebugPrintOutputSlot(value, frame_index, output_offset, | 1582 DebugPrintOutputSlot(value, frame_index, output_offset, |
| 1562 "caller's constant_pool\n"); | 1583 "caller's constant_pool\n"); |
| 1563 } | 1584 } |
| 1564 | 1585 |
| 1565 // A marker value is used to mark the frame. | 1586 // A marker value is used to mark the frame. |
| 1566 output_offset -= kPointerSize; | 1587 output_offset -= kPointerSize; |
| 1567 value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT)); | 1588 value = reinterpret_cast<intptr_t>(Smi::FromInt(StackFrame::CONSTRUCT)); |
| 1568 output_frame->SetFrameSlot(output_offset, value); | 1589 output_frame->SetFrameSlot(output_offset, value); |
| 1569 DebugPrintOutputSlot(value, frame_index, output_offset, | 1590 DebugPrintOutputSlot(value, frame_index, output_offset, |
| 1570 "typed frame marker\n"); | 1591 "typed frame marker\n"); |
| 1571 | 1592 |
| 1572 // The context can be gotten from the previous frame. | 1593 // The context can be gotten from the previous frame. |
| 1573 output_offset -= kPointerSize; | 1594 output_offset -= kPointerSize; |
| 1574 value = output_[frame_index - 1]->GetContext(); | 1595 value = output_[frame_index - 1]->GetContext(); |
| 1575 output_frame->SetFrameSlot(output_offset, value); | 1596 output_frame->SetFrameSlot(output_offset, value); |
| 1597 if (is_topmost) { |
| 1598 Register context_reg = JavaScriptFrame::context_register(); |
| 1599 output_frame->SetRegister(context_reg.code(), value); |
| 1600 } |
| 1576 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n"); | 1601 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n"); |
| 1577 | 1602 |
| 1578 // The allocation site. | 1603 // The allocation site. |
| 1579 output_offset -= kPointerSize; | 1604 output_offset -= kPointerSize; |
| 1580 value = reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value()); | 1605 value = reinterpret_cast<intptr_t>(isolate_->heap()->undefined_value()); |
| 1581 output_frame->SetFrameSlot(output_offset, value); | 1606 output_frame->SetFrameSlot(output_offset, value); |
| 1582 DebugPrintOutputSlot(value, frame_index, output_offset, "allocation site\n"); | 1607 DebugPrintOutputSlot(value, frame_index, output_offset, "allocation site\n"); |
| 1583 | 1608 |
| 1584 // Number of incoming arguments. | 1609 // Number of incoming arguments. |
| 1585 output_offset -= kPointerSize; | 1610 output_offset -= kPointerSize; |
| 1586 value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1)); | 1611 value = reinterpret_cast<intptr_t>(Smi::FromInt(height - 1)); |
| 1587 output_frame->SetFrameSlot(output_offset, value); | 1612 output_frame->SetFrameSlot(output_offset, value); |
| 1588 DebugPrintOutputSlot(value, frame_index, output_offset, "argc "); | 1613 DebugPrintOutputSlot(value, frame_index, output_offset, "argc "); |
| 1589 if (trace_scope_ != nullptr) { | 1614 if (trace_scope_ != nullptr) { |
| 1590 PrintF(trace_scope_->file(), "(%d)\n", height - 1); | 1615 PrintF(trace_scope_->file(), "(%d)\n", height - 1); |
| 1591 } | 1616 } |
| 1592 | 1617 |
| 1593 // The newly allocated object was passed as receiver in the artificial | 1618 // The newly allocated object was passed as receiver in the artificial |
| 1594 // constructor stub environment created by HEnvironment::CopyForInlining(). | 1619 // constructor stub environment created by HEnvironment::CopyForInlining(). |
| 1595 output_offset -= kPointerSize; | 1620 output_offset -= kPointerSize; |
| 1596 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); | 1621 value = output_frame->GetFrameSlot(output_frame_size - kPointerSize); |
| 1597 output_frame->SetFrameSlot(output_offset, value); | 1622 output_frame->SetFrameSlot(output_offset, value); |
| 1598 DebugPrintOutputSlot(value, frame_index, output_offset, | 1623 DebugPrintOutputSlot(value, frame_index, output_offset, |
| 1599 "allocated receiver\n"); | 1624 "allocated receiver\n"); |
| 1600 | 1625 |
| 1626 if (is_topmost) { |
| 1627 // Ensure the result is restored back when we return to the stub. |
| 1628 output_offset -= kPointerSize; |
| 1629 Register result_reg = FullCodeGenerator::result_register(); |
| 1630 value = input_->GetRegister(result_reg.code()); |
| 1631 output_frame->SetFrameSlot(output_offset, value); |
| 1632 DebugPrintOutputSlot(value, frame_index, output_offset, |
| 1633 "constructor result\n"); |
| 1634 |
| 1635 output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG)); |
| 1636 } |
| 1637 |
| 1601 CHECK_EQ(0u, output_offset); | 1638 CHECK_EQ(0u, output_offset); |
| 1602 | 1639 |
| 1603 intptr_t pc = reinterpret_cast<intptr_t>( | 1640 intptr_t pc = reinterpret_cast<intptr_t>( |
| 1604 construct_stub->instruction_start() + | 1641 construct_stub->instruction_start() + |
| 1605 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); | 1642 isolate_->heap()->construct_stub_deopt_pc_offset()->value()); |
| 1606 output_frame->SetPc(pc); | 1643 output_frame->SetPc(pc); |
| 1607 if (FLAG_enable_embedded_constant_pool) { | 1644 if (FLAG_enable_embedded_constant_pool) { |
| 1608 intptr_t constant_pool_value = | 1645 intptr_t constant_pool_value = |
| 1609 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); | 1646 reinterpret_cast<intptr_t>(construct_stub->constant_pool()); |
| 1610 output_frame->SetConstantPool(constant_pool_value); | 1647 output_frame->SetConstantPool(constant_pool_value); |
| 1648 if (is_topmost) { |
| 1649 Register constant_pool_reg = |
| 1650 JavaScriptFrame::constant_pool_pointer_register(); |
| 1651 output_frame->SetRegister(constant_pool_reg.code(), fp_value); |
| 1652 } |
| 1653 } |
| 1654 |
| 1655 // Set the continuation for the topmost frame. |
| 1656 if (is_topmost) { |
| 1657 Builtins* builtins = isolate_->builtins(); |
| 1658 DCHECK_EQ(LAZY, bailout_type_); |
| 1659 Code* continuation = builtins->builtin(Builtins::kNotifyLazyDeoptimized); |
| 1660 output_frame->SetContinuation( |
| 1661 reinterpret_cast<intptr_t>(continuation->entry())); |
| 1611 } | 1662 } |
| 1612 } | 1663 } |
| 1613 | 1664 |
| 1614 void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame, | 1665 void Deoptimizer::DoComputeAccessorStubFrame(TranslatedFrame* translated_frame, |
| 1615 int frame_index, | 1666 int frame_index, |
| 1616 bool is_setter_stub_frame) { | 1667 bool is_setter_stub_frame) { |
| 1617 TranslatedFrame::iterator value_iterator = translated_frame->begin(); | 1668 TranslatedFrame::iterator value_iterator = translated_frame->begin(); |
| 1669 bool is_topmost = (output_count_ - 1 == frame_index); |
| 1670 // The accessor frame could become topmost only if we inlined an accessor |
| 1671 // call which does a tail call (otherwise the tail callee's frame would be |
| 1672 // the topmost one). So it could only be the LAZY case. |
| 1673 CHECK(!is_topmost || bailout_type_ == LAZY); |
| 1618 int input_index = 0; | 1674 int input_index = 0; |
| 1619 | 1675 |
| 1620 // Skip accessor. | 1676 // Skip accessor. |
| 1621 value_iterator++; | 1677 value_iterator++; |
| 1622 input_index++; | 1678 input_index++; |
| 1623 // The receiver (and the implicit return value, if any) are expected in | 1679 // 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 | 1680 // 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. | 1681 // frame. This means that we have to use a height of 0. |
| 1626 unsigned height = 0; | 1682 unsigned height = 0; |
| 1627 unsigned height_in_bytes = height * kPointerSize; | 1683 unsigned height_in_bytes = height * kPointerSize; |
| 1684 |
| 1685 // If the accessor frame appears to be topmost we should ensure that the |
| 1686 // value of result register is preserved during continuation execution. |
| 1687 // We do this here by "pushing" the result of the accessor function to the |
| 1688 // top of the reconstructed stack and then using the |
| 1689 // FullCodeGenerator::TOS_REG machinery. |
| 1690 // We don't need to restore the result in case of a setter call because we |
| 1691 // have to return the stored value but not the result of the setter function. |
| 1692 bool should_preserve_result = is_topmost && !is_setter_stub_frame; |
| 1693 if (should_preserve_result) { |
| 1694 height_in_bytes += kPointerSize; |
| 1695 } |
| 1696 |
| 1628 const char* kind = is_setter_stub_frame ? "setter" : "getter"; | 1697 const char* kind = is_setter_stub_frame ? "setter" : "getter"; |
| 1629 if (trace_scope_ != NULL) { | 1698 if (trace_scope_ != NULL) { |
| 1630 PrintF(trace_scope_->file(), | 1699 PrintF(trace_scope_->file(), |
| 1631 " translating %s stub => height=%u\n", kind, height_in_bytes); | 1700 " translating %s stub => height=%u\n", kind, height_in_bytes); |
| 1632 } | 1701 } |
| 1633 | 1702 |
| 1634 // We need 1 stack entry for the return address and enough entries for the | 1703 // 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 | 1704 // StackFrame::INTERNAL (FP, frame type, context, code object and constant |
| 1636 // pool (if enabled)- see MacroAssembler::EnterFrame). | 1705 // pool (if enabled)- see MacroAssembler::EnterFrame). |
| 1637 // For a setter stub frame we need one additional entry for the implicit | 1706 // For a setter stub frame we need one additional entry for the implicit |
| 1638 // return value, see StoreStubCompiler::CompileStoreViaSetter. | 1707 // return value, see StoreStubCompiler::CompileStoreViaSetter. |
| 1639 unsigned fixed_frame_entries = | 1708 unsigned fixed_frame_entries = |
| 1640 (StandardFrameConstants::kFixedFrameSize / kPointerSize) + 1 + | 1709 (StandardFrameConstants::kFixedFrameSize / kPointerSize) + 1 + |
| 1641 (is_setter_stub_frame ? 1 : 0); | 1710 (is_setter_stub_frame ? 1 : 0); |
| 1642 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize; | 1711 unsigned fixed_frame_size = fixed_frame_entries * kPointerSize; |
| 1643 unsigned output_frame_size = height_in_bytes + fixed_frame_size; | 1712 unsigned output_frame_size = height_in_bytes + fixed_frame_size; |
| 1644 | 1713 |
| 1645 // Allocate and store the output frame description. | 1714 // Allocate and store the output frame description. |
| 1646 FrameDescription* output_frame = | 1715 FrameDescription* output_frame = |
| 1647 new (output_frame_size) FrameDescription(output_frame_size); | 1716 new (output_frame_size) FrameDescription(output_frame_size); |
| 1648 output_frame->SetFrameType(StackFrame::INTERNAL); | 1717 output_frame->SetFrameType(StackFrame::INTERNAL); |
| 1649 | 1718 |
| 1650 // A frame for an accessor stub can not be the topmost or bottommost one. | 1719 // A frame for an accessor stub can not be bottommost. |
| 1651 CHECK(frame_index > 0 && frame_index < output_count_ - 1); | 1720 CHECK(frame_index > 0 && frame_index < output_count_); |
| 1652 CHECK_NULL(output_[frame_index]); | 1721 CHECK_NULL(output_[frame_index]); |
| 1653 output_[frame_index] = output_frame; | 1722 output_[frame_index] = output_frame; |
| 1654 | 1723 |
| 1655 // The top address of the frame is computed from the previous frame's top and | 1724 // The top address of the frame is computed from the previous frame's top and |
| 1656 // this frame's size. | 1725 // this frame's size. |
| 1657 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size; | 1726 intptr_t top_address = output_[frame_index - 1]->GetTop() - output_frame_size; |
| 1658 output_frame->SetTop(top_address); | 1727 output_frame->SetTop(top_address); |
| 1659 | 1728 |
| 1660 unsigned output_offset = output_frame_size; | 1729 unsigned output_offset = output_frame_size; |
| 1661 | 1730 |
| 1662 // Read caller's PC from the previous frame. | 1731 // Read caller's PC from the previous frame. |
| 1663 output_offset -= kPCOnStackSize; | 1732 output_offset -= kPCOnStackSize; |
| 1664 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); | 1733 intptr_t callers_pc = output_[frame_index - 1]->GetPc(); |
| 1665 output_frame->SetCallerPc(output_offset, callers_pc); | 1734 output_frame->SetCallerPc(output_offset, callers_pc); |
| 1666 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n"); | 1735 DebugPrintOutputSlot(callers_pc, frame_index, output_offset, "caller's pc\n"); |
| 1667 | 1736 |
| 1668 // Read caller's FP from the previous frame, and set this frame's FP. | 1737 // Read caller's FP from the previous frame, and set this frame's FP. |
| 1669 output_offset -= kFPOnStackSize; | 1738 output_offset -= kFPOnStackSize; |
| 1670 intptr_t value = output_[frame_index - 1]->GetFp(); | 1739 intptr_t value = output_[frame_index - 1]->GetFp(); |
| 1671 output_frame->SetCallerFp(output_offset, value); | 1740 output_frame->SetCallerFp(output_offset, value); |
| 1672 intptr_t fp_value = top_address + output_offset; | 1741 intptr_t fp_value = top_address + output_offset; |
| 1673 output_frame->SetFp(fp_value); | 1742 output_frame->SetFp(fp_value); |
| 1743 if (is_topmost) { |
| 1744 Register fp_reg = JavaScriptFrame::fp_register(); |
| 1745 output_frame->SetRegister(fp_reg.code(), fp_value); |
| 1746 } |
| 1674 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); | 1747 DebugPrintOutputSlot(value, frame_index, output_offset, "caller's fp\n"); |
| 1675 | 1748 |
| 1676 if (FLAG_enable_embedded_constant_pool) { | 1749 if (FLAG_enable_embedded_constant_pool) { |
| 1677 // Read the caller's constant pool from the previous frame. | 1750 // Read the caller's constant pool from the previous frame. |
| 1678 output_offset -= kPointerSize; | 1751 output_offset -= kPointerSize; |
| 1679 value = output_[frame_index - 1]->GetConstantPool(); | 1752 value = output_[frame_index - 1]->GetConstantPool(); |
| 1680 output_frame->SetCallerConstantPool(output_offset, value); | 1753 output_frame->SetCallerConstantPool(output_offset, value); |
| 1681 DebugPrintOutputSlot(value, frame_index, output_offset, | 1754 DebugPrintOutputSlot(value, frame_index, output_offset, |
| 1682 "caller's constant_pool\n"); | 1755 "caller's constant_pool\n"); |
| 1683 } | 1756 } |
| (...skipping 14 matching lines...) Expand all Loading... |
| 1698 Builtins::kLoadIC_Getter_ForDeopt; | 1771 Builtins::kLoadIC_Getter_ForDeopt; |
| 1699 Code* accessor_stub = isolate_->builtins()->builtin(name); | 1772 Code* accessor_stub = isolate_->builtins()->builtin(name); |
| 1700 value = reinterpret_cast<intptr_t>(accessor_stub); | 1773 value = reinterpret_cast<intptr_t>(accessor_stub); |
| 1701 output_frame->SetFrameSlot(output_offset, value); | 1774 output_frame->SetFrameSlot(output_offset, value); |
| 1702 DebugPrintOutputSlot(value, frame_index, output_offset, "code object\n"); | 1775 DebugPrintOutputSlot(value, frame_index, output_offset, "code object\n"); |
| 1703 | 1776 |
| 1704 // The context can be gotten from the previous frame. | 1777 // The context can be gotten from the previous frame. |
| 1705 output_offset -= kPointerSize; | 1778 output_offset -= kPointerSize; |
| 1706 value = output_[frame_index - 1]->GetContext(); | 1779 value = output_[frame_index - 1]->GetContext(); |
| 1707 output_frame->SetFrameSlot(output_offset, value); | 1780 output_frame->SetFrameSlot(output_offset, value); |
| 1781 if (is_topmost) { |
| 1782 Register context_reg = JavaScriptFrame::context_register(); |
| 1783 output_frame->SetRegister(context_reg.code(), value); |
| 1784 } |
| 1708 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n"); | 1785 DebugPrintOutputSlot(value, frame_index, output_offset, "context\n"); |
| 1709 | 1786 |
| 1710 // Skip receiver. | 1787 // Skip receiver. |
| 1711 value_iterator++; | 1788 value_iterator++; |
| 1712 input_index++; | 1789 input_index++; |
| 1713 | 1790 |
| 1714 if (is_setter_stub_frame) { | 1791 if (is_setter_stub_frame) { |
| 1715 // The implicit return value was part of the artificial setter stub | 1792 // The implicit return value was part of the artificial setter stub |
| 1716 // environment. | 1793 // environment. |
| 1717 output_offset -= kPointerSize; | 1794 output_offset -= kPointerSize; |
| 1718 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, | 1795 WriteTranslatedValueToOutput(&value_iterator, &input_index, frame_index, |
| 1719 output_offset); | 1796 output_offset); |
| 1720 } | 1797 } |
| 1721 | 1798 |
| 1799 if (should_preserve_result) { |
| 1800 // Ensure the result is restored back when we return to the stub. |
| 1801 output_offset -= kPointerSize; |
| 1802 Register result_reg = FullCodeGenerator::result_register(); |
| 1803 value = input_->GetRegister(result_reg.code()); |
| 1804 output_frame->SetFrameSlot(output_offset, value); |
| 1805 DebugPrintOutputSlot(value, frame_index, output_offset, |
| 1806 "accessor result\n"); |
| 1807 |
| 1808 output_frame->SetState(Smi::FromInt(FullCodeGenerator::TOS_REG)); |
| 1809 } else { |
| 1810 output_frame->SetState(Smi::FromInt(FullCodeGenerator::NO_REGISTERS)); |
| 1811 } |
| 1812 |
| 1722 CHECK_EQ(0u, output_offset); | 1813 CHECK_EQ(0u, output_offset); |
| 1723 | 1814 |
| 1724 Smi* offset = is_setter_stub_frame ? | 1815 Smi* offset = is_setter_stub_frame ? |
| 1725 isolate_->heap()->setter_stub_deopt_pc_offset() : | 1816 isolate_->heap()->setter_stub_deopt_pc_offset() : |
| 1726 isolate_->heap()->getter_stub_deopt_pc_offset(); | 1817 isolate_->heap()->getter_stub_deopt_pc_offset(); |
| 1727 intptr_t pc = reinterpret_cast<intptr_t>( | 1818 intptr_t pc = reinterpret_cast<intptr_t>( |
| 1728 accessor_stub->instruction_start() + offset->value()); | 1819 accessor_stub->instruction_start() + offset->value()); |
| 1729 output_frame->SetPc(pc); | 1820 output_frame->SetPc(pc); |
| 1730 if (FLAG_enable_embedded_constant_pool) { | 1821 if (FLAG_enable_embedded_constant_pool) { |
| 1731 intptr_t constant_pool_value = | 1822 intptr_t constant_pool_value = |
| 1732 reinterpret_cast<intptr_t>(accessor_stub->constant_pool()); | 1823 reinterpret_cast<intptr_t>(accessor_stub->constant_pool()); |
| 1733 output_frame->SetConstantPool(constant_pool_value); | 1824 output_frame->SetConstantPool(constant_pool_value); |
| 1825 if (is_topmost) { |
| 1826 Register constant_pool_reg = |
| 1827 JavaScriptFrame::constant_pool_pointer_register(); |
| 1828 output_frame->SetRegister(constant_pool_reg.code(), fp_value); |
| 1829 } |
| 1830 } |
| 1831 |
| 1832 // Set the continuation for the topmost frame. |
| 1833 if (is_topmost) { |
| 1834 Builtins* builtins = isolate_->builtins(); |
| 1835 DCHECK_EQ(LAZY, bailout_type_); |
| 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 |