Skip to content

Commit

Permalink
Update graph processing to work with previously supported versions of…
Browse files Browse the repository at this point in the history
… GraalVM as well as GraalVM 24.0.0.

GraalVM renamed packages after merging with the OpenJDK project. The node search and match done by Seafoam is intentionally conservative in order to avoid accidentally matching nodes from a guest language. Consequently, the old logic would not work with the new package names. Now both are supported.

Additionally, the Truffle pass tests now run against each of the pre-generated GraalVM version graphs, instead of one hard-coded version.
  • Loading branch information
nirvdrum committed Mar 21, 2024
1 parent bc39bfb commit 411efa6
Show file tree
Hide file tree
Showing 7 changed files with 180 additions and 101 deletions.
9 changes: 5 additions & 4 deletions lib/seafoam/commands.rb
Original file line number Diff line number Diff line change
Expand Up @@ -394,19 +394,20 @@ def describe(name, formatter_module, *args)
description.node_counts[simple_node_class] += 1

case node_class
when "org.graalvm.compiler.nodes.IfNode"
when "org.graalvm.compiler.nodes.IfNode", "jdk.graal.compiler.nodes.IfNode"
description.branches = true
when "org.graalvm.compiler.nodes.LoopBeginNode"
when "org.graalvm.compiler.nodes.LoopBeginNode", "jdk.graal.compiler.nodes.LoopBeginNode"
description.loops = true
when "org.graalvm.compiler.nodes.InvokeNode", "org.graalvm.compiler.nodes.InvokeWithExceptionNode"
when "org.graalvm.compiler.nodes.InvokeNode", "org.graalvm.compiler.nodes.InvokeWithExceptionNode",
"jdk.graal.compiler.nodes.InvokeNode", "jdk.graal.compiler.nodes.InvokeWithExceptionNode"
description.calls = true
end
elsif node.props[:synthetic_class]
description.node_counts["*" + node.props[:synthetic_class]] += 1
end

description.deopts = graph.nodes[0].outputs.map(&:to)
.all? { |t| t.node_class == "org.graalvm.compiler.nodes.DeoptimizeNode" }
.all? { |t| t.node_class.end_with?(".compiler.nodes.DeoptimizeNode") }
end

formatter = formatter_module::DescribeFormatter.new(graph, description)
Expand Down
2 changes: 2 additions & 0 deletions lib/seafoam/graal/pi.rb
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ def follow_pi_object(node)
PI_NODES = [
"org.graalvm.compiler.nodes.PiNode",
"org.graalvm.compiler.nodes.PiArrayNode",
"jdk.graal.compiler.nodes.PiNode",
"jdk.graal.compiler.nodes.PiArrayNode",
]
end
end
Expand Down
2 changes: 1 addition & 1 deletion lib/seafoam/graph.rb
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ def initialize(id, props = nil)
end

def node_class
@props.dig(:node_class, :node_class)
@props.dig(:node_class, :node_class) || ""
end

# All edges - input and output.
Expand Down
91 changes: 73 additions & 18 deletions lib/seafoam/passes/graal.rb
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ def apply_nodes(graph)
# For constant nodes, the rawvalue is a truncated version of the
# actual value, which is fully qualified. Instead, produce a simple
# version of the value and don't truncate it.
if node_class == "org.graalvm.compiler.nodes.ConstantNode"
if node_class.end_with?(".compiler.nodes.ConstantNode")
if node.props["value"] =~ /Object\[Instance<(\w+\.)+(\w*)>\]/
node.props["rawvalue"] = "instance:#{Regexp.last_match(2)}"
end
Expand All @@ -59,63 +59,63 @@ def apply_nodes(graph)
end

# The template for InvokeNode could be simpler.
if node_class == "org.graalvm.compiler.nodes.InvokeNode"
if node_class.end_with?(".compiler.nodes.InvokeNode")
name_template = "Call {p#targetMethod/s}"
end

# The template for InvokeWithExceptionNode could be simpler.
if node_class == "org.graalvm.compiler.nodes.InvokeWithExceptionNode"
if node_class.end_with?(".compiler.nodes.InvokeWithExceptionNode")
name_template = "Call {p#targetMethod/s} !"
end

# The template for CommitAllocationNode could be simpler.
if node_class == "org.graalvm.compiler.nodes.virtual.CommitAllocationNode"
if node_class.end_with?(".compiler.nodes.virtual.CommitAllocationNode")
name_template = "Alloc"
end

# The template for org.graalvm.compiler.nodes.virtual.VirtualArrayNode
# includes an ID that we don't normally need.
if node_class == "org.graalvm.compiler.nodes.virtual.VirtualArrayNode"
if node_class.end_with?(".compiler.nodes.virtual.VirtualArrayNode")
name_template = "VirtualArray {p#componentType/s}[{p#length}]"
end

# The template for LoadField could be simpler.
if node_class == "org.graalvm.compiler.nodes.java.LoadFieldNode"
if node_class.end_with?(".compiler.nodes.java.LoadFieldNode")
name_template = "LoadField {x#field}"
end

# The template for StoreField could be simpler.
if node_class == "org.graalvm.compiler.nodes.java.StoreFieldNode"
if node_class.end_with?(".compiler.nodes.java.StoreFieldNode")
name_template = "StoreField {x#field}"
end

# We want to see keys for IntegerSwitchNode.
if node_class == "org.graalvm.compiler.nodes.extended.IntegerSwitchNode"
if node_class.end_with?(".compiler.nodes.extended.IntegerSwitchNode")
name_template = "IntegerSwitch {p#keys}"
end

# Use a symbol for PiNode.
if node_class == "org.graalvm.compiler.nodes.PiNode"
if node_class.end_with?(".compiler.nodes.PiNode")
name_template = "π"
end

# Use a symbol for PiArrayNode.
if node_class == "org.graalvm.compiler.nodes.PiArrayNode"
if node_class.end_with?(".compiler.nodes.PiArrayNode")
name_template = "[π]"
end

# Use a symbol for PhiNode.
if node_class == "org.graalvm.compiler.nodes.ValuePhiNode"
if node_class.end_with?(".compiler.nodes.ValuePhiNode")
name_template = "ϕ"
end

# Better template for frame states.
if node_class == "org.graalvm.compiler.nodes.FrameState"
if node_class.end_with?(".compiler.nodes.FrameState")
name_template = "FrameState {x#state}"
end

# Show the stamp in an InstanceOfNode.
if node_class == "org.graalvm.compiler.nodes.java.InstanceOfNode"
if node_class.end_with?(".compiler.nodes.java.InstanceOfNode")
name_template = "InstanceOf {x#simpleStamp}"
end

Expand Down Expand Up @@ -194,6 +194,49 @@ def apply_nodes(graph)
"org.graalvm.compiler.replacements.nodes.ReadRegisterNode" => "memory",
"org.graalvm.compiler.replacements.nodes.WriteRegisterNode" => "memory",
"org.graalvm.compiler.word.WordCastNode" => "memory",
"jdk.graal.compiler.nodes.BeginNode" => "control",
"jdk.graal.compiler.nodes.ConstantNode" => "input",
"jdk.graal.compiler.nodes.DeoptimizeNode" => "control",
"jdk.graal.compiler.nodes.EndNode" => "control",
"jdk.graal.compiler.nodes.extended.IntegerSwitchNode" => "control",
"jdk.graal.compiler.nodes.extended.UnsafeMemoryLoadNode" => "memory",
"jdk.graal.compiler.nodes.extended.UnsafeMemoryStoreNode" => "memory",
"jdk.graal.compiler.nodes.FixedGuardNode" => "guard",
"jdk.graal.compiler.nodes.FrameState" => "info",
"jdk.graal.compiler.nodes.GuardNode" => "guard",
"jdk.graal.compiler.nodes.IfNode" => "control",
"jdk.graal.compiler.nodes.InvokeNode" => "call",
"jdk.graal.compiler.nodes.InvokeWithExceptionNode" => "call",
"jdk.graal.compiler.nodes.java.ArrayLengthNode" => "memory",
"jdk.graal.compiler.nodes.java.LoadFieldNode" => "memory",
"jdk.graal.compiler.nodes.java.LoadIndexedNode" => "memory",
"jdk.graal.compiler.nodes.java.MonitorEnterNode" => "sync",
"jdk.graal.compiler.nodes.java.MonitorExitNode" => "sync",
"jdk.graal.compiler.nodes.java.NewArrayNode" => "alloc",
"jdk.graal.compiler.nodes.java.NewInstanceNode" => "alloc",
"jdk.graal.compiler.nodes.java.RawMonitorEnterNode" => "sync",
"jdk.graal.compiler.nodes.java.StoreFieldNode" => "memory",
"jdk.graal.compiler.nodes.java.StoreIndexedNode" => "memory",
"jdk.graal.compiler.nodes.KillingBeginNode" => "control",
"jdk.graal.compiler.nodes.LoopBeginNode" => "control",
"jdk.graal.compiler.nodes.LoopEndNode" => "control",
"jdk.graal.compiler.nodes.LoopExitNode" => "control",
"jdk.graal.compiler.nodes.memory.ReadNode" => "memory",
"jdk.graal.compiler.nodes.memory.WriteNode" => "memory",
"jdk.graal.compiler.nodes.MergeNode" => "control",
"jdk.graal.compiler.nodes.ParameterNode" => "input",
"jdk.graal.compiler.nodes.PrefetchAllocateNode" => "alloc",
"jdk.graal.compiler.nodes.ReturnNode" => "control",
"jdk.graal.compiler.nodes.StartNode" => "control",
"jdk.graal.compiler.nodes.UnwindNode" => "control",
"jdk.graal.compiler.nodes.virtual.AllocatedObjectNode" => "virtual",
"jdk.graal.compiler.nodes.virtual.CommitAllocationNode" => "alloc",
"jdk.graal.compiler.nodes.virtual.VirtualArrayNode" => "virtual",
"jdk.graal.compiler.nodes.VirtualObjectState" => "info",
"jdk.graal.compiler.replacements.nodes.ArrayEqualsNode" => "memory",
"jdk.graal.compiler.replacements.nodes.ReadRegisterNode" => "memory",
"jdk.graal.compiler.replacements.nodes.WriteRegisterNode" => "memory",
"jdk.graal.compiler.word.WordCastNode" => "memory",
}

# Render a Graal 'name template'.
Expand Down Expand Up @@ -234,7 +277,7 @@ def render_name_template(template, node)
# Annotate edges with their label and kind.
def apply_edges(graph)
graph.edges.each do |edge|
if edge.to.node_class == "org.graalvm.compiler.nodes.ValuePhiNode" && edge.props[:name] == "values"
if edge.to.node_class.end_with?(".compiler.nodes.ValuePhiNode") && edge.props[:name] == "values"
merge_node = edge.to.edges.find { |e| e.props[:name] == "merge" }.from
control_into_merge = ["ends", "loopBegin"]
merge_node_control_edges_in = merge_node.edges.select do |e|
Expand Down Expand Up @@ -282,11 +325,11 @@ def apply_edges(graph)
# (break) to the LoopBeginNode. Both are drawn reversed.
when "loopBegin"
case edge.to.node_class
when "org.graalvm.compiler.nodes.LoopEndNode"
when "org.graalvm.compiler.nodes.LoopEndNode", "jdk.graal.compiler.nodes.LoopEndNode"
# If it's from the LoopEnd then it's the control edge to follow.
edge.props[:kind] = "loop"
edge.props[:reverse] = true
when "org.graalvm.compiler.nodes.LoopExitNode"
when "org.graalvm.compiler.nodes.LoopExitNode", "jdk.graal.compiler.nodes.LoopExitNode"
# If it's from the LoopExit then it's just for information - it's
# not control flow to follow.
edge.props[:kind] = "info"
Expand Down Expand Up @@ -424,15 +467,27 @@ def hide_unused_nodes(graph)
TRIGGERS = ["HostedGraphBuilderPhase", "GraalCompiler", "TruffleCompiler", "SubstrateCompilation"]

# Simple input node classes that may be inlined.
SIMPLE_INPUTS = ["org.graalvm.compiler.nodes.ConstantNode", "org.graalvm.compiler.nodes.ParameterNode"]
SIMPLE_INPUTS = [
"org.graalvm.compiler.nodes.ConstantNode",
"org.graalvm.compiler.nodes.ParameterNode",
"jdk.graal.compiler.nodes.ConstantNode",
"jdk.graal.compiler.nodes.ParameterNode",
]

# Nodes just to maintain frame state.
FRAME_STATE_NODES = [
"org.graalvm.compiler.nodes.FrameState",
"org.graalvm.compiler.virtual.nodes.MaterializedObjectState",
"jdk.graal.compiler.nodes.FrameState",
"jdk.graal.compiler.virtual.nodes.MaterializedObjectState",
]

BEGIN_END_NODES = ["org.graalvm.compiler.nodes.BeginNode", "org.graalvm.compiler.nodes.EndNode"]
BEGIN_END_NODES = [
"org.graalvm.compiler.nodes.BeginNode",
"org.graalvm.compiler.nodes.EndNode",
"jdk.graal.compiler.nodes.BeginNode",
"jdk.graal.compiler.nodes.EndNode",
]
end
end
end
16 changes: 8 additions & 8 deletions lib/seafoam/passes/truffle.rb
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ def apply(graph)
# like a Graal parameter node.
def simplify_truffle_args(graph)
graph.nodes.dup.each_value do |node|
next unless node.node_class == "org.graalvm.compiler.nodes.java.LoadIndexedNode"
next unless node.node_class.end_with?(".compiler.nodes.java.LoadIndexedNode")

index_node = node.inputs.find { |edge| edge.props[:name] == "index" }.from
array_node = Graal::Pi.follow_pi_object(node.inputs.find { |edge| edge.props[:name] == "array" }.from)

next unless index_node.node_class == "org.graalvm.compiler.nodes.ConstantNode"
next unless array_node.node_class == "org.graalvm.compiler.nodes.ParameterNode"
next unless index_node.node_class.end_with?(".compiler.nodes.ConstantNode")
next unless array_node.node_class.end_with?(".compiler.nodes.ParameterNode")

node.props[:truffle_arg_load] = true

Expand Down Expand Up @@ -69,7 +69,7 @@ def simplify_truffle_args(graph)
# are constants that are null or 0.
def simplify_alloc(graph)
commit_allocation_nodes = graph.nodes.each_value.select do |node|
node.node_class == "org.graalvm.compiler.nodes.virtual.CommitAllocationNode"
node.node_class.end_with?(".compiler.nodes.virtual.CommitAllocationNode")
end

commit_allocation_nodes.each do |commit_allocation_node|
Expand All @@ -95,7 +95,7 @@ def simplify_alloc(graph)
class_name, values = m.captures
values = values.split(",").map(&:to_i)
virtual_node = graph.nodes[virtual_id]
if virtual_node.node_class == "org.graalvm.compiler.nodes.virtual.VirtualArrayNode"
if virtual_node.node_class.end_with?(".compiler.nodes.virtual.VirtualArrayNode")
label = "New #{class_name[0...-1]}#{virtual_node.props["length"]}]"
fields = values.size.times.to_a
else
Expand Down Expand Up @@ -132,7 +132,7 @@ def simplify_alloc(graph)
graph.create_edge(prev, new_node, control_flow_pred.props)

allocated_object_node = virtual_node.outputs.find do |output|
output.to.node_class == "org.graalvm.compiler.nodes.virtual.AllocatedObjectNode"
output.to.node_class.end_with?(".compiler.nodes.virtual.AllocatedObjectNode")
end
if allocated_object_node
allocated_object_node = allocated_object_node.to
Expand All @@ -147,7 +147,7 @@ def simplify_alloc(graph)
fields.zip(values) do |field, value_id|
value_node = virtual_to_object[value_id]&.first || graph.nodes[value_id]
if @options[:hide_null_fields] &&
(value_node.node_class == "org.graalvm.compiler.nodes.ConstantNode") &&
value_node.node_class.end_with?(".compiler.nodes.ConstantNode") &&
["Object[null]", "0"].include?(value_node.props["rawvalue"])
value_node.props[:hidden] = true
else
Expand All @@ -168,7 +168,7 @@ def simplify_alloc(graph)
# Hide reachability fences - they're just really boring.
def hide_reachability_fences(graph)
graph.nodes.each_value do |node|
next unless node.node_class == "org.graalvm.compiler.nodes.java.ReachabilityFenceNode"
next unless node.node_class.end_with?(".compiler.nodes.java.ReachabilityFenceNode")

pred = node.inputs.find { |edge| edge.props[:name] == "next" }
succ = node.outputs.find { |edge| edge.props[:name] == "next" }
Expand Down
Loading

0 comments on commit 411efa6

Please sign in to comment.