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 |