public class GraphEncoder extends Object
StructuredGraph
to a compact byte[] array. All nodes of the graph and edges
between the nodes are encoded. Primitive data fields of nodes are stored in the byte[] array.
Object data fields of nodes are stored in a separate Object[] array.
One encoder instance can be used to encode multiple graphs. This requires that GraphEncoder.prepare(org.graalvm.compiler.nodes.StructuredGraph)
is called for all graphs first, followed by one call to GraphEncoder.finishPrepare()
. Then
GraphEncoder.encode(org.graalvm.compiler.nodes.StructuredGraph)
can be called for all graphs. The objects
and
node classes
arrays do not change anymore after preparation.
Multiple encoded graphs share the Object[] array, and elements of the Object[] array are
de-duplicated using Object equality
. This uses the assumption and good
coding practice that data objects are immutable if Object.equals(java.lang.Object)
is implemented.
Unfortunately, this cannot be enforced.
The Graal NodeClass
does not have a unique id that allows class lookup from an id.
Therefore, the encoded graph contains a NodeClass
[] array for lookup, and type ids are
encoding-local.
The encoded graph has the following structure: First, all nodes and their edges are serialized.
The start offset of every node is then known. The raw node data is followed by metadata, i.e.,
the maximum fixed node order id and a "table of contents" that lists the start offset for every
node.
The beginning of this metadata is the return value of GraphEncoder.encode(org.graalvm.compiler.nodes.StructuredGraph)
and stored in
EncodedGraph.getStartOffset()
. The order of nodes in the table of contents is the
orderId
of a node. Note that the orderId is not the regular node id
that every Graal graph node gets assigned. The orderId is computed and used just for encoding and
decoding. The orderId of fixed nodes is assigned in reverse postorder. The decoder processes
nodes using that order, which ensures that all predecessors of a node (including all
predecessors
of a block
) are decoded before the node.
The order id of floating node does not matter during decoding, so floating nodes get order ids
after all fixed nodes. The order id is used to encode edges between nodes
Structure of an encoded node:
struct Node { unsigned typeId unsigned[] inputOrderIds signed[] properties unsigned[] successorOrderIds }All numbers (unsigned and signed) are stored using a variable-length encoding as defined in
TypeReader
and TypeWriter
. Especially orderIds are small, so the variable-length
encoding is important to keep the encoding compact.
The properties, successors, and inputs are written in the order as defined in
FieldIntrospection.getData()
, NodeClass.getSuccessorEdges()
, and
NodeClass.getInputEdges()
. For variable-length successors and input lists, first the
length is written and then the orderIds. There is a distinction between null lists (encoded as
length -1) and empty lists (encoded as length 0). No reverse edges are written (predecessors,
usages) since that information can be easily restored during decoding.
Some nodes have additional information written after the properties, successors, and inputs:
AbstractEndNode
: the orderId of the merge node and then all phi
mappings
from this end to the merge node are written. LoopExitNode
: the orderId of
all proxy nodes
of the loop exit is written.Modifier and Type | Field and Description |
---|---|
protected jdk.vm.ci.code.Architecture |
architecture |
protected static int |
BEGIN_NEXT_ORDER_ID_OFFSET
The known offset between the orderId of a
AbstractBeginNode and its
successor . |
protected DebugContext |
debug |
static int |
FIRST_NODE_ORDER_ID
The orderId of the first actual node after the
start node . |
static int |
MAX_INDEX_1_BYTE
Maximum unsigned integer fitting on 1 byte.
|
static int |
MAX_INDEX_2_BYTES
Maximum unsigned integer fitting on 2 bytes.
|
protected FrequencyEncoder<NodeClass<?>> |
nodeClasses
Collects all node classes referenced in graphs.
|
protected NodeClass<?>[] |
nodeClassesArray
The last snapshot of
GraphEncoder.nodeClasses that was retrieved. |
static int |
NULL_ORDER_ID
The orderId that always represents
null . |
protected FrequencyEncoder<Object> |
objects
Collects all non-primitive data referenced from nodes.
|
protected Object[] |
objectsArray
The last snapshot of
GraphEncoder.objects that was retrieved. |
static int |
START_NODE_ORDER_ID
The orderId of the
start node of the encoded graph. |
protected UnsafeArrayTypeWriter |
writer
The writer for the encoded graphs.
|
Constructor and Description |
---|
GraphEncoder(jdk.vm.ci.code.Architecture architecture) |
GraphEncoder(jdk.vm.ci.code.Architecture architecture,
DebugContext debug) |
Modifier and Type | Method and Description |
---|---|
int |
encode(StructuredGraph graph)
Compresses a graph to a byte array.
|
static EncodedGraph |
encodeSingleGraph(StructuredGraph graph,
jdk.vm.ci.code.Architecture architecture)
Utility method that does everything necessary to encode a single graph.
|
void |
finishPrepare() |
byte[] |
getEncoding() |
NodeClass<?>[] |
getNodeClasses() |
Object[] |
getObjects() |
void |
prepare(StructuredGraph graph)
Must be invoked before
GraphEncoder.finishPrepare() and GraphEncoder.encode(org.graalvm.compiler.nodes.StructuredGraph) . |
boolean |
verifyEncoding(StructuredGraph originalGraph,
EncodedGraph encodedGraph)
Verification code that checks that the decoding of an encode graph is the same as the
original graph.
|
protected void |
writeEdges(Node node,
Edges edges,
org.graalvm.compiler.nodes.GraphEncoder.NodeOrder nodeOrder) |
protected void |
writeObjectId(Object object) |
protected void |
writeOrderId(Node node,
org.graalvm.compiler.nodes.GraphEncoder.NodeOrder nodeOrder) |
protected void |
writeProperties(Node node,
Fields fields) |
public static final int NULL_ORDER_ID
null
.public static final int START_NODE_ORDER_ID
start node
of the encoded graph.public static final int FIRST_NODE_ORDER_ID
start node
.public static final int MAX_INDEX_1_BYTE
public static final int MAX_INDEX_2_BYTES
protected static final int BEGIN_NEXT_ORDER_ID_OFFSET
AbstractBeginNode
and its
successor
.protected final jdk.vm.ci.code.Architecture architecture
protected final FrequencyEncoder<Object> objects
protected final FrequencyEncoder<NodeClass<?>> nodeClasses
NodeClass
currently does not have a unique id.protected final UnsafeArrayTypeWriter writer
protected Object[] objectsArray
GraphEncoder.objects
that was retrieved.protected NodeClass<?>[] nodeClassesArray
GraphEncoder.nodeClasses
that was retrieved.protected DebugContext debug
public GraphEncoder(jdk.vm.ci.code.Architecture architecture)
public GraphEncoder(jdk.vm.ci.code.Architecture architecture, DebugContext debug)
public static EncodedGraph encodeSingleGraph(StructuredGraph graph, jdk.vm.ci.code.Architecture architecture)
public void prepare(StructuredGraph graph)
GraphEncoder.finishPrepare()
and GraphEncoder.encode(org.graalvm.compiler.nodes.StructuredGraph)
.public void finishPrepare()
public Object[] getObjects()
public NodeClass<?>[] getNodeClasses()
public int encode(StructuredGraph graph)
GraphEncoder
.graph
- The graph to encodepublic byte[] getEncoding()
protected void writeEdges(Node node, Edges edges, org.graalvm.compiler.nodes.GraphEncoder.NodeOrder nodeOrder)
protected void writeOrderId(Node node, org.graalvm.compiler.nodes.GraphEncoder.NodeOrder nodeOrder)
protected void writeObjectId(Object object)
public boolean verifyEncoding(StructuredGraph originalGraph, EncodedGraph encodedGraph)