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 prepare(com.oracle.graal.nodes.StructuredGraph)
is called for all graphs first, followed by one call to finishPrepare()
. Then
encode(com.oracle.graal.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 a
"table of contents" that lists the start offset for every node.
The beginning of that table of contents is the return value of encode(com.oracle.graal.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 signed[] properties unsigned[] successorOrderIds unsigned[] inputOrderIds }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 | Class and Description |
---|---|
(package private) static class |
GraphEncoder.NodeOrder |
Modifier and Type | Field and Description |
---|---|
protected Architecture |
architecture |
protected static int |
BEGIN_NEXT_ORDER_ID_OFFSET
The known offset between the orderId of a
AbstractBeginNode and its
successor . |
static int |
FIRST_NODE_ORDER_ID
The orderId of the first actual node after the
start node . |
protected FrequencyEncoder<NodeClass<?>> |
nodeClasses
Collects all node classes referenced in graphs.
|
protected NodeClass<?>[] |
nodeClassesArray
The last snapshot of
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
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(Architecture architecture) |
Modifier and Type | Method and Description |
---|---|
long |
encode(StructuredGraph graph)
Compresses a graph to a byte array.
|
static EncodedGraph |
encodeSingleGraph(StructuredGraph graph,
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
finishPrepare() and encode(com.oracle.graal.nodes.StructuredGraph) . |
static boolean |
verifyEncoding(StructuredGraph originalGraph,
EncodedGraph encodedGraph,
Architecture architecture)
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,
GraphEncoder.NodeOrder nodeOrder) |
protected void |
writeObjectId(Object object) |
protected void |
writeOrderId(Node node,
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
.protected static final int BEGIN_NEXT_ORDER_ID_OFFSET
AbstractBeginNode
and its
successor
.protected final 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
objects
that was retrieved.protected NodeClass<?>[] nodeClassesArray
nodeClasses
that was retrieved.public GraphEncoder(Architecture architecture)
public static EncodedGraph encodeSingleGraph(StructuredGraph graph, Architecture architecture)
public void prepare(StructuredGraph graph)
finishPrepare()
and encode(com.oracle.graal.nodes.StructuredGraph)
.public void finishPrepare()
public Object[] getObjects()
public NodeClass<?>[] getNodeClasses()
public long encode(StructuredGraph graph)
GraphEncoder
.graph
- The graph to encodepublic byte[] getEncoding()
protected void writeProperties(Node node, Fields fields)
protected void writeEdges(Node node, Edges edges, GraphEncoder.NodeOrder nodeOrder)
protected void writeOrderId(Node node, GraphEncoder.NodeOrder nodeOrder)
protected void writeObjectId(Object object)
public static boolean verifyEncoding(StructuredGraph originalGraph, EncodedGraph encodedGraph, Architecture architecture)