| OLD | NEW |
| 1 // Copyright 2015 the V8 project authors. All rights reserved. | 1 // Copyright 2015 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/compiler/bytecode-graph-builder.h" | 5 #include "src/compiler/bytecode-graph-builder.h" |
| 6 | 6 |
| 7 #include "src/ast/ast.h" | 7 #include "src/ast/ast.h" |
| 8 #include "src/ast/scopes.h" | 8 #include "src/ast/scopes.h" |
| 9 #include "src/compiler/access-builder.h" | 9 #include "src/compiler/access-builder.h" |
| 10 #include "src/compiler/compiler-source-position-table.h" | 10 #include "src/compiler/compiler-source-position-table.h" |
| (...skipping 1565 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1576 interpreter::Register first_return = | 1576 interpreter::Register first_return = |
| 1577 bytecode_iterator().GetRegisterOperand(3); | 1577 bytecode_iterator().GetRegisterOperand(3); |
| 1578 | 1578 |
| 1579 // Create node to perform the runtime call. | 1579 // Create node to perform the runtime call. |
| 1580 const Operator* call = javascript()->CallRuntime(functionId, reg_count); | 1580 const Operator* call = javascript()->CallRuntime(functionId, reg_count); |
| 1581 Node* return_pair = ProcessCallRuntimeArguments(call, receiver, reg_count); | 1581 Node* return_pair = ProcessCallRuntimeArguments(call, receiver, reg_count); |
| 1582 environment()->BindRegistersToProjections(first_return, return_pair, | 1582 environment()->BindRegistersToProjections(first_return, return_pair, |
| 1583 Environment::kAttachFrameState); | 1583 Environment::kAttachFrameState); |
| 1584 } | 1584 } |
| 1585 | 1585 |
| 1586 Node* BytecodeGraphBuilder::ProcessConstructWithSpreadArguments( | 1586 Node* const* BytecodeGraphBuilder::GetConstructArgumentsFromRegister( |
| 1587 const Operator* op, Node* callee, Node* new_target, | 1587 Node* target, Node* new_target, interpreter::Register first_arg, |
| 1588 interpreter::Register receiver, size_t reg_count) { | 1588 int arg_count) { |
| 1589 int arg_count = static_cast<int>(reg_count); | |
| 1590 // arity is args + callee and new target. | 1589 // arity is args + callee and new target. |
| 1591 int arity = arg_count + 2; | 1590 int arity = arg_count + 2; |
| 1592 Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity)); | 1591 Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity)); |
| 1593 all[0] = callee; | 1592 all[0] = target; |
| 1594 int first_arg_index = receiver.index(); | 1593 int first_arg_index = first_arg.index(); |
| 1595 for (int i = 0; i < arg_count; ++i) { | 1594 for (int i = 0; i < arg_count; ++i) { |
| 1596 all[1 + i] = environment()->LookupRegister( | 1595 all[1 + i] = environment()->LookupRegister( |
| 1597 interpreter::Register(first_arg_index + i)); | 1596 interpreter::Register(first_arg_index + i)); |
| 1598 } | 1597 } |
| 1599 all[arity - 1] = new_target; | 1598 all[arity - 1] = new_target; |
| 1600 Node* value = MakeNode(op, arity, all, false); | 1599 return all; |
| 1601 return value; | 1600 } |
| 1601 |
| 1602 Node* BytecodeGraphBuilder::ProcessConstructArguments(const Operator* op, |
| 1603 Node* const* args, |
| 1604 int arg_count) { |
| 1605 return MakeNode(op, arg_count, args, false); |
| 1606 } |
| 1607 |
| 1608 void BytecodeGraphBuilder::VisitConstruct() { |
| 1609 PrepareEagerCheckpoint(); |
| 1610 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); |
| 1611 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); |
| 1612 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); |
| 1613 // Slot index of 0 is used indicate no feedback slot is available. Assert |
| 1614 // the assumption that slot index 0 is never a valid feedback slot. |
| 1615 STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0); |
| 1616 int const slot_id = bytecode_iterator().GetIndexOperand(3); |
| 1617 VectorSlotPair feedback = CreateVectorSlotPair(slot_id); |
| 1618 |
| 1619 Node* new_target = environment()->LookupAccumulator(); |
| 1620 Node* callee = environment()->LookupRegister(callee_reg); |
| 1621 |
| 1622 CallFrequency frequency = ComputeCallFrequency(slot_id); |
| 1623 const Operator* op = javascript()->Construct( |
| 1624 static_cast<uint32_t>(reg_count + 2), frequency, feedback); |
| 1625 int arg_count = static_cast<int>(reg_count); |
| 1626 Node* const* args = GetConstructArgumentsFromRegister(callee, new_target, |
| 1627 first_reg, arg_count); |
| 1628 Node* node = nullptr; |
| 1629 if (Node* simplified = TryBuildSimplifiedConstruct( |
| 1630 op, args, static_cast<int>(arg_count), feedback.slot())) { |
| 1631 if (environment() == nullptr) return; |
| 1632 node = simplified; |
| 1633 } else { |
| 1634 node = ProcessConstructArguments(op, args, 2 + arg_count); |
| 1635 } |
| 1636 environment()->BindAccumulator(node, Environment::kAttachFrameState); |
| 1602 } | 1637 } |
| 1603 | 1638 |
| 1604 void BytecodeGraphBuilder::VisitConstructWithSpread() { | 1639 void BytecodeGraphBuilder::VisitConstructWithSpread() { |
| 1605 PrepareEagerCheckpoint(); | 1640 PrepareEagerCheckpoint(); |
| 1606 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); | 1641 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); |
| 1607 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); | 1642 interpreter::Register first_reg = bytecode_iterator().GetRegisterOperand(1); |
| 1608 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); | 1643 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); |
| 1609 | 1644 |
| 1610 Node* new_target = environment()->LookupAccumulator(); | 1645 Node* new_target = environment()->LookupAccumulator(); |
| 1611 Node* callee = environment()->LookupRegister(callee_reg); | 1646 Node* callee = environment()->LookupRegister(callee_reg); |
| 1612 | 1647 |
| 1613 const Operator* op = | 1648 const Operator* op = |
| 1614 javascript()->ConstructWithSpread(static_cast<uint32_t>(reg_count + 2)); | 1649 javascript()->ConstructWithSpread(static_cast<uint32_t>(reg_count + 2)); |
| 1615 Node* value = ProcessConstructWithSpreadArguments(op, callee, new_target, | 1650 int arg_count = static_cast<int>(reg_count); |
| 1616 receiver, reg_count); | 1651 Node* const* args = GetConstructArgumentsFromRegister(callee, new_target, |
| 1652 first_reg, arg_count); |
| 1653 Node* value = ProcessConstructArguments(op, args, 2 + arg_count); |
| 1617 environment()->BindAccumulator(value, Environment::kAttachFrameState); | 1654 environment()->BindAccumulator(value, Environment::kAttachFrameState); |
| 1618 } | 1655 } |
| 1619 | 1656 |
| 1620 void BytecodeGraphBuilder::VisitInvokeIntrinsic() { | 1657 void BytecodeGraphBuilder::VisitInvokeIntrinsic() { |
| 1621 PrepareEagerCheckpoint(); | 1658 PrepareEagerCheckpoint(); |
| 1622 Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0); | 1659 Runtime::FunctionId functionId = bytecode_iterator().GetIntrinsicIdOperand(0); |
| 1623 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); | 1660 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); |
| 1624 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); | 1661 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); |
| 1625 | 1662 |
| 1626 // Create node to perform the runtime call. Turbofan will take care of the | 1663 // Create node to perform the runtime call. Turbofan will take care of the |
| 1627 // lowering. | 1664 // lowering. |
| 1628 const Operator* call = javascript()->CallRuntime(functionId, reg_count); | 1665 const Operator* call = javascript()->CallRuntime(functionId, reg_count); |
| 1629 Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); | 1666 Node* value = ProcessCallRuntimeArguments(call, receiver, reg_count); |
| 1630 environment()->BindAccumulator(value, Environment::kAttachFrameState); | 1667 environment()->BindAccumulator(value, Environment::kAttachFrameState); |
| 1631 } | 1668 } |
| 1632 | 1669 |
| 1633 Node* BytecodeGraphBuilder::ProcessConstructArguments( | |
| 1634 const Operator* call_new_op, Node* callee, Node* new_target, | |
| 1635 interpreter::Register receiver, size_t reg_count) { | |
| 1636 int arg_count = static_cast<int>(reg_count); | |
| 1637 // arity is args + callee and new target. | |
| 1638 int arity = arg_count + 2; | |
| 1639 Node** all = local_zone()->NewArray<Node*>(static_cast<size_t>(arity)); | |
| 1640 all[0] = callee; | |
| 1641 int first_arg_index = receiver.index(); | |
| 1642 for (int i = 0; i < arg_count; ++i) { | |
| 1643 all[1 + i] = environment()->LookupRegister( | |
| 1644 interpreter::Register(first_arg_index + i)); | |
| 1645 } | |
| 1646 all[arity - 1] = new_target; | |
| 1647 Node* value = MakeNode(call_new_op, arity, all, false); | |
| 1648 return value; | |
| 1649 } | |
| 1650 | |
| 1651 void BytecodeGraphBuilder::VisitConstruct() { | |
| 1652 PrepareEagerCheckpoint(); | |
| 1653 interpreter::Register callee_reg = bytecode_iterator().GetRegisterOperand(0); | |
| 1654 interpreter::Register receiver = bytecode_iterator().GetRegisterOperand(1); | |
| 1655 size_t reg_count = bytecode_iterator().GetRegisterCountOperand(2); | |
| 1656 // Slot index of 0 is used indicate no feedback slot is available. Assert | |
| 1657 // the assumption that slot index 0 is never a valid feedback slot. | |
| 1658 STATIC_ASSERT(FeedbackVector::kReservedIndexCount > 0); | |
| 1659 int const slot_id = bytecode_iterator().GetIndexOperand(3); | |
| 1660 VectorSlotPair feedback = CreateVectorSlotPair(slot_id); | |
| 1661 | |
| 1662 Node* new_target = environment()->LookupAccumulator(); | |
| 1663 Node* callee = environment()->LookupRegister(callee_reg); | |
| 1664 | |
| 1665 CallFrequency frequency = ComputeCallFrequency(slot_id); | |
| 1666 const Operator* call = javascript()->Construct( | |
| 1667 static_cast<uint32_t>(reg_count + 2), frequency, feedback); | |
| 1668 Node* value = | |
| 1669 ProcessConstructArguments(call, callee, new_target, receiver, reg_count); | |
| 1670 environment()->BindAccumulator(value, Environment::kAttachFrameState); | |
| 1671 } | |
| 1672 | |
| 1673 void BytecodeGraphBuilder::VisitThrow() { | 1670 void BytecodeGraphBuilder::VisitThrow() { |
| 1674 BuildLoopExitsForFunctionExit(); | 1671 BuildLoopExitsForFunctionExit(); |
| 1675 Node* value = environment()->LookupAccumulator(); | 1672 Node* value = environment()->LookupAccumulator(); |
| 1676 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); | 1673 Node* call = NewNode(javascript()->CallRuntime(Runtime::kThrow), value); |
| 1677 environment()->BindAccumulator(call, Environment::kAttachFrameState); | 1674 environment()->BindAccumulator(call, Environment::kAttachFrameState); |
| 1678 Node* control = NewNode(common()->Throw()); | 1675 Node* control = NewNode(common()->Throw()); |
| 1679 MergeControlToLeaveFunction(control); | 1676 MergeControlToLeaveFunction(control); |
| 1680 } | 1677 } |
| 1681 | 1678 |
| 1682 void BytecodeGraphBuilder::VisitReThrow() { | 1679 void BytecodeGraphBuilder::VisitReThrow() { |
| (...skipping 1003 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2686 Node* control = environment()->GetControlDependency(); | 2683 Node* control = environment()->GetControlDependency(); |
| 2687 Reduction early_reduction = type_hint_lowering().ReduceCallOperation( | 2684 Reduction early_reduction = type_hint_lowering().ReduceCallOperation( |
| 2688 op, args, arg_count, effect, control, slot); | 2685 op, args, arg_count, effect, control, slot); |
| 2689 if (early_reduction.Changed()) { | 2686 if (early_reduction.Changed()) { |
| 2690 ApplyEarlyReduction(early_reduction); | 2687 ApplyEarlyReduction(early_reduction); |
| 2691 return early_reduction.replacement(); | 2688 return early_reduction.replacement(); |
| 2692 } | 2689 } |
| 2693 return nullptr; | 2690 return nullptr; |
| 2694 } | 2691 } |
| 2695 | 2692 |
| 2693 Node* BytecodeGraphBuilder::TryBuildSimplifiedConstruct(const Operator* op, |
| 2694 Node* const* args, |
| 2695 int arg_count, |
| 2696 FeedbackSlot slot) { |
| 2697 // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being |
| 2698 // pruned from the graph by a soft-deopt. It can happen that a CallIC that |
| 2699 // control-dominates the OSR entry is still in "uninitialized" state. |
| 2700 if (!osr_ast_id_.IsNone()) return nullptr; |
| 2701 Node* effect = environment()->GetEffectDependency(); |
| 2702 Node* control = environment()->GetControlDependency(); |
| 2703 Reduction early_reduction = type_hint_lowering().ReduceConstructOperation( |
| 2704 op, args, arg_count, effect, control, slot); |
| 2705 if (early_reduction.Changed()) { |
| 2706 ApplyEarlyReduction(early_reduction); |
| 2707 return early_reduction.replacement(); |
| 2708 } |
| 2709 return nullptr; |
| 2710 } |
| 2711 |
| 2696 Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op, | 2712 Node* BytecodeGraphBuilder::TryBuildSimplifiedLoadNamed(const Operator* op, |
| 2697 Node* receiver, | 2713 Node* receiver, |
| 2698 FeedbackSlot slot) { | 2714 FeedbackSlot slot) { |
| 2699 // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being | 2715 // TODO(mstarzinger,6112): This is a workaround for OSR loop entries being |
| 2700 // pruned from the graph by a soft-deopt. It can happen that a LoadIC that | 2716 // pruned from the graph by a soft-deopt. It can happen that a LoadIC that |
| 2701 // control-dominates the OSR entry is still in "uninitialized" state. | 2717 // control-dominates the OSR entry is still in "uninitialized" state. |
| 2702 if (bytecode_analysis()->HasOSREntryPoint()) return nullptr; | 2718 if (bytecode_analysis()->HasOSREntryPoint()) return nullptr; |
| 2703 Node* effect = environment()->GetEffectDependency(); | 2719 Node* effect = environment()->GetEffectDependency(); |
| 2704 Node* control = environment()->GetControlDependency(); | 2720 Node* control = environment()->GetControlDependency(); |
| 2705 Reduction early_reduction = type_hint_lowering().ReduceLoadNamedOperation( | 2721 Reduction early_reduction = type_hint_lowering().ReduceLoadNamedOperation( |
| (...skipping 273 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 2979 it->source_position().ScriptOffset(), start_position_.InliningId())); | 2995 it->source_position().ScriptOffset(), start_position_.InliningId())); |
| 2980 it->Advance(); | 2996 it->Advance(); |
| 2981 } else { | 2997 } else { |
| 2982 DCHECK_GT(it->code_offset(), offset); | 2998 DCHECK_GT(it->code_offset(), offset); |
| 2983 } | 2999 } |
| 2984 } | 3000 } |
| 2985 | 3001 |
| 2986 } // namespace compiler | 3002 } // namespace compiler |
| 2987 } // namespace internal | 3003 } // namespace internal |
| 2988 } // namespace v8 | 3004 } // namespace v8 |
| OLD | NEW |