[maglev] Add control node class for terminal nodes
Allow distinguishing control nodes that do and don't allow continued execution. Bug: v8:7700 Change-Id: Ifa13b64821484584929bd62a0d8585aee160c19e Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/3891255 Commit-Queue: Jakob Linke <jgruber@chromium.org> Auto-Submit: Leszek Swirski <leszeks@chromium.org> Reviewed-by: Jakob Linke <jgruber@chromium.org> Cr-Commit-Position: refs/heads/main@{#83143}
This commit is contained in:
parent
66b788de9f
commit
9438113d9a
@ -224,10 +224,13 @@ class CompactInterpreterFrameState;
|
||||
V(JumpToInlined) \
|
||||
V(JumpFromInlined)
|
||||
|
||||
#define TERMINAL_CONTROL_NODE_LIST(V) \
|
||||
V(Abort) \
|
||||
V(Return) \
|
||||
V(Deopt)
|
||||
|
||||
#define CONTROL_NODE_LIST(V) \
|
||||
V(Abort) \
|
||||
V(Return) \
|
||||
V(Deopt) \
|
||||
TERMINAL_CONTROL_NODE_LIST(V) \
|
||||
CONDITIONAL_CONTROL_NODE_LIST(V) \
|
||||
UNCONDITIONAL_CONTROL_NODE_LIST(V)
|
||||
|
||||
@ -282,6 +285,11 @@ static constexpr Opcode kLastUnconditionalControlNodeOpcode =
|
||||
static constexpr Opcode kFirstUnconditionalControlNodeOpcode =
|
||||
std::min({UNCONDITIONAL_CONTROL_NODE_LIST(V) kLastOpcode});
|
||||
|
||||
static constexpr Opcode kLastTerminalControlNodeOpcode =
|
||||
std::max({TERMINAL_CONTROL_NODE_LIST(V) kFirstOpcode});
|
||||
static constexpr Opcode kFirstTerminalControlNodeOpcode =
|
||||
std::min({TERMINAL_CONTROL_NODE_LIST(V) kLastOpcode});
|
||||
|
||||
static constexpr Opcode kFirstControlNodeOpcode =
|
||||
std::min({CONTROL_NODE_LIST(V) kLastOpcode});
|
||||
static constexpr Opcode kLastControlNodeOpcode =
|
||||
@ -313,6 +321,10 @@ constexpr bool IsUnconditionalControlNode(Opcode opcode) {
|
||||
return kFirstUnconditionalControlNodeOpcode <= opcode &&
|
||||
opcode <= kLastUnconditionalControlNodeOpcode;
|
||||
}
|
||||
constexpr bool IsTerminalControlNode(Opcode opcode) {
|
||||
return kFirstTerminalControlNodeOpcode <= opcode &&
|
||||
opcode <= kLastTerminalControlNodeOpcode;
|
||||
}
|
||||
|
||||
// Forward-declare NodeBase sub-hierarchies.
|
||||
class Node;
|
||||
@ -320,6 +332,7 @@ class ControlNode;
|
||||
class ConditionalControlNode;
|
||||
class BranchControlNode;
|
||||
class UnconditionalControlNode;
|
||||
class TerminalControlNode;
|
||||
class ValueNode;
|
||||
|
||||
enum class ValueRepresentation : uint8_t { kTagged, kInt32, kFloat64 };
|
||||
@ -1025,6 +1038,10 @@ template <>
|
||||
constexpr bool NodeBase::Is<UnconditionalControlNode>() const {
|
||||
return IsUnconditionalControlNode(opcode());
|
||||
}
|
||||
template <>
|
||||
constexpr bool NodeBase::Is<TerminalControlNode>() const {
|
||||
return IsTerminalControlNode(opcode());
|
||||
}
|
||||
|
||||
// The Node class hierarchy contains all non-control nodes.
|
||||
class Node : public NodeBase {
|
||||
@ -3518,10 +3535,9 @@ class ControlNode : public NodeBase {
|
||||
return next_post_dominating_hole_;
|
||||
}
|
||||
void set_next_post_dominating_hole(ControlNode* node) {
|
||||
DCHECK_IMPLIES(node != nullptr,
|
||||
node->Is<UnconditionalControlNode>() || node->Is<Abort>() ||
|
||||
node->Is<Return>() || node->Is<Deopt>() ||
|
||||
node->Is<Switch>());
|
||||
DCHECK_IMPLIES(node != nullptr, node->Is<UnconditionalControlNode>() ||
|
||||
node->Is<TerminalControlNode>() ||
|
||||
node->Is<Switch>());
|
||||
next_post_dominating_hole_ = node;
|
||||
}
|
||||
|
||||
@ -3599,6 +3615,26 @@ class BranchControlNode : public ConditionalControlNode {
|
||||
BasicBlockRef if_false_;
|
||||
};
|
||||
|
||||
class TerminalControlNode : public ControlNode {
|
||||
protected:
|
||||
explicit TerminalControlNode(uint64_t bitfield) : ControlNode(bitfield) {}
|
||||
};
|
||||
|
||||
template <class Derived>
|
||||
class TerminalControlNodeT : public TerminalControlNode {
|
||||
static_assert(IsTerminalControlNode(opcode_of<Derived>));
|
||||
|
||||
public:
|
||||
// Shadowing for static knowledge.
|
||||
constexpr Opcode opcode() const { return NodeBase::opcode_of<Derived>; }
|
||||
|
||||
protected:
|
||||
explicit TerminalControlNodeT(uint64_t bitfield)
|
||||
: TerminalControlNode(bitfield) {
|
||||
DCHECK_EQ(NodeBase::opcode(), opcode_of<Derived>);
|
||||
}
|
||||
};
|
||||
|
||||
template <size_t InputCount, class Derived>
|
||||
class BranchControlNodeT : public BranchControlNode {
|
||||
static_assert(IsBranchControlNode(opcode_of<Derived>));
|
||||
@ -3679,10 +3715,10 @@ class JumpFromInlined : public UnconditionalControlNodeT<JumpFromInlined> {
|
||||
DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS()
|
||||
};
|
||||
|
||||
class Abort : public ControlNode {
|
||||
class Abort : public TerminalControlNode {
|
||||
public:
|
||||
explicit Abort(uint64_t bitfield, AbortReason reason)
|
||||
: ControlNode(bitfield), reason_(reason) {
|
||||
: TerminalControlNode(bitfield), reason_(reason) {
|
||||
DCHECK_EQ(NodeBase::opcode(), opcode_of<Abort>);
|
||||
}
|
||||
|
||||
@ -3694,9 +3730,9 @@ class Abort : public ControlNode {
|
||||
const AbortReason reason_;
|
||||
};
|
||||
|
||||
class Return : public ControlNode {
|
||||
class Return : public TerminalControlNode {
|
||||
public:
|
||||
explicit Return(uint64_t bitfield) : ControlNode(bitfield) {
|
||||
explicit Return(uint64_t bitfield) : TerminalControlNode(bitfield) {
|
||||
DCHECK_EQ(NodeBase::opcode(), opcode_of<Return>);
|
||||
}
|
||||
|
||||
@ -3705,10 +3741,10 @@ class Return : public ControlNode {
|
||||
DECL_NODE_INTERFACE_WITH_EMPTY_PRINT_PARAMS()
|
||||
};
|
||||
|
||||
class Deopt : public ControlNode {
|
||||
class Deopt : public TerminalControlNode {
|
||||
public:
|
||||
explicit Deopt(uint64_t bitfield, DeoptimizeReason reason)
|
||||
: ControlNode(bitfield), reason_(reason) {
|
||||
: TerminalControlNode(bitfield), reason_(reason) {
|
||||
DCHECK_EQ(NodeBase::opcode(), opcode_of<Deopt>);
|
||||
}
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
#include "src/maglev/maglev-graph.h"
|
||||
#include "src/maglev/maglev-interpreter-frame-state.h"
|
||||
#include "src/maglev/maglev-ir-inl.h"
|
||||
#include "src/maglev/maglev-ir.h"
|
||||
#include "src/maglev/maglev-regalloc-data.h"
|
||||
|
||||
namespace v8 {
|
||||
@ -81,11 +82,10 @@ ControlNode* HighestPostDominatingHole(ControlNode* first,
|
||||
// Walk the highest branch to find where it goes.
|
||||
if (first->id() > second->id()) std::swap(first, second);
|
||||
|
||||
// If the first branch returns or jumps back, we've found highest
|
||||
// If the first branch terminates or jumps back, we've found highest
|
||||
// reachable control-node of the longest branch (the second control
|
||||
// node).
|
||||
if (first->Is<Return>() || first->Is<Deopt>() || first->Is<Abort>() ||
|
||||
first->Is<JumpLoop>()) {
|
||||
if (first->Is<TerminalControlNode>() || first->Is<JumpLoop>()) {
|
||||
return second;
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user