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

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: Removed too much, fixing 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
« no previous file with comments | « src/crankshaft/x87/lithium-x87.cc ('k') | test/mjsunit/es6/tail-call.js » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright 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);
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
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
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
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
« no previous file with comments | « src/crankshaft/x87/lithium-x87.cc ('k') | test/mjsunit/es6/tail-call.js » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698