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

Side by Side Diff: src/deoptimizer.cc

Issue 1936043002: [es6] Properly handle the case when an inlined getter/setter/constructor does a tail call. (Closed) Base URL: https://chromium.googlesource.com/v8/v8.git@master
Patch Set: More comments added, continuations updated Created 4 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
OLDNEW
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
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
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
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
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
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
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698