16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.nodes; 24 25 import java.util.ArrayDeque; 26 import java.util.Deque; 27 import java.util.Iterator; 28 import java.util.Objects; 29 30 import org.graalvm.compiler.core.common.Fields; 31 import org.graalvm.compiler.core.common.util.FrequencyEncoder; 32 import org.graalvm.compiler.core.common.util.TypeConversion; 33 import org.graalvm.compiler.core.common.util.TypeReader; 34 import org.graalvm.compiler.core.common.util.TypeWriter; 35 import org.graalvm.compiler.core.common.util.UnsafeArrayTypeWriter; 36 import org.graalvm.compiler.debug.Debug; 37 import org.graalvm.compiler.graph.Edges; 38 import org.graalvm.compiler.graph.Node; 39 import org.graalvm.compiler.graph.NodeClass; 40 import org.graalvm.compiler.graph.NodeList; 41 import org.graalvm.compiler.graph.NodeMap; 42 import org.graalvm.compiler.graph.iterators.NodeIterable; 43 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 44 import org.graalvm.compiler.nodes.java.ExceptionObjectNode; 45 import org.graalvm.util.UnmodifiableMapCursor; 46 import org.graalvm.util.Pair; 47 48 import jdk.vm.ci.code.Architecture; 49 50 /** 51 * Encodes a {@link StructuredGraph} to a compact byte[] array. All nodes of the graph and edges 52 * between the nodes are encoded. Primitive data fields of nodes are stored in the byte[] array. 53 * Object data fields of nodes are stored in a separate Object[] array. 54 * 55 * One encoder instance can be used to encode multiple graphs. This requires that {@link #prepare} 56 * is called for all graphs first, followed by one call to {@link #finishPrepare}. Then 57 * {@link #encode} can be called for all graphs. The {@link #getObjects() objects} and 58 * {@link #getNodeClasses() node classes} arrays do not change anymore after preparation. 59 * 60 * Multiple encoded graphs share the Object[] array, and elements of the Object[] array are 61 * de-duplicated using {@link Object#equals Object equality}. This uses the assumption and good 62 * coding practice that data objects are immutable if {@link Object#equals} is implemented. 63 * Unfortunately, this cannot be enforced. 64 * 65 * The Graal {@link NodeClass} does not have a unique id that allows class lookup from an id. 66 * Therefore, the encoded graph contains a {@link NodeClass}[] array for lookup, and type ids are 401 } 402 } 403 } 404 405 } 406 407 protected void writeOrderId(Node node, NodeOrder nodeOrder) { 408 writer.putUV(node == null ? NULL_ORDER_ID : nodeOrder.orderIds.get(node)); 409 } 410 411 protected void writeObjectId(Object object) { 412 writer.putUV(objects.getIndex(object)); 413 } 414 415 /** 416 * Verification code that checks that the decoding of an encode graph is the same as the 417 * original graph. 418 */ 419 @SuppressWarnings("try") 420 public static boolean verifyEncoding(StructuredGraph originalGraph, EncodedGraph encodedGraph, Architecture architecture) { 421 StructuredGraph decodedGraph = new StructuredGraph.Builder(originalGraph.getOptions(), AllowAssumptions.YES).method(originalGraph.method()).build(); 422 GraphDecoder decoder = new GraphDecoder(architecture, decodedGraph); 423 decoder.decode(encodedGraph); 424 425 decodedGraph.verify(); 426 try { 427 GraphComparison.verifyGraphsEqual(originalGraph, decodedGraph); 428 } catch (Throwable ex) { 429 try (Debug.Scope scope = Debug.scope("GraphEncoder")) { 430 Debug.dump(Debug.VERBOSE_LEVEL, originalGraph, "Original Graph"); 431 Debug.dump(Debug.VERBOSE_LEVEL, decodedGraph, "Decoded Graph"); 432 } 433 throw ex; 434 } 435 return true; 436 } 437 } 438 439 class GraphComparison { 440 public static boolean verifyGraphsEqual(StructuredGraph expectedGraph, StructuredGraph actualGraph) { 441 NodeMap<Node> nodeMapping = new NodeMap<>(expectedGraph); 442 Deque<Pair<Node, Node>> workList = new ArrayDeque<>(); 443 444 pushToWorklist(expectedGraph.start(), actualGraph.start(), nodeMapping, workList); 445 while (!workList.isEmpty()) { 446 Pair<Node, Node> pair = workList.removeFirst(); 447 Node expectedNode = pair.getLeft(); 448 Node actualNode = pair.getRight(); 449 assert expectedNode.getClass() == actualNode.getClass(); 450 451 NodeClass<?> nodeClass = expectedNode.getNodeClass(); | 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 package org.graalvm.compiler.nodes; 24 25 import java.util.ArrayDeque; 26 import java.util.Deque; 27 import java.util.Iterator; 28 import java.util.Objects; 29 30 import org.graalvm.compiler.core.common.Fields; 31 import org.graalvm.compiler.core.common.util.FrequencyEncoder; 32 import org.graalvm.compiler.core.common.util.TypeConversion; 33 import org.graalvm.compiler.core.common.util.TypeReader; 34 import org.graalvm.compiler.core.common.util.TypeWriter; 35 import org.graalvm.compiler.core.common.util.UnsafeArrayTypeWriter; 36 import org.graalvm.compiler.debug.DebugContext; 37 import org.graalvm.compiler.graph.Edges; 38 import org.graalvm.compiler.graph.Node; 39 import org.graalvm.compiler.graph.NodeClass; 40 import org.graalvm.compiler.graph.NodeList; 41 import org.graalvm.compiler.graph.NodeMap; 42 import org.graalvm.compiler.graph.iterators.NodeIterable; 43 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions; 44 import org.graalvm.compiler.nodes.java.ExceptionObjectNode; 45 import org.graalvm.util.Pair; 46 import org.graalvm.util.UnmodifiableMapCursor; 47 48 import jdk.vm.ci.code.Architecture; 49 50 /** 51 * Encodes a {@link StructuredGraph} to a compact byte[] array. All nodes of the graph and edges 52 * between the nodes are encoded. Primitive data fields of nodes are stored in the byte[] array. 53 * Object data fields of nodes are stored in a separate Object[] array. 54 * 55 * One encoder instance can be used to encode multiple graphs. This requires that {@link #prepare} 56 * is called for all graphs first, followed by one call to {@link #finishPrepare}. Then 57 * {@link #encode} can be called for all graphs. The {@link #getObjects() objects} and 58 * {@link #getNodeClasses() node classes} arrays do not change anymore after preparation. 59 * 60 * Multiple encoded graphs share the Object[] array, and elements of the Object[] array are 61 * de-duplicated using {@link Object#equals Object equality}. This uses the assumption and good 62 * coding practice that data objects are immutable if {@link Object#equals} is implemented. 63 * Unfortunately, this cannot be enforced. 64 * 65 * The Graal {@link NodeClass} does not have a unique id that allows class lookup from an id. 66 * Therefore, the encoded graph contains a {@link NodeClass}[] array for lookup, and type ids are 401 } 402 } 403 } 404 405 } 406 407 protected void writeOrderId(Node node, NodeOrder nodeOrder) { 408 writer.putUV(node == null ? NULL_ORDER_ID : nodeOrder.orderIds.get(node)); 409 } 410 411 protected void writeObjectId(Object object) { 412 writer.putUV(objects.getIndex(object)); 413 } 414 415 /** 416 * Verification code that checks that the decoding of an encode graph is the same as the 417 * original graph. 418 */ 419 @SuppressWarnings("try") 420 public static boolean verifyEncoding(StructuredGraph originalGraph, EncodedGraph encodedGraph, Architecture architecture) { 421 DebugContext debug = originalGraph.getDebug(); 422 StructuredGraph decodedGraph = new StructuredGraph.Builder(originalGraph.getOptions(), debug, AllowAssumptions.YES).method(originalGraph.method()).build(); 423 GraphDecoder decoder = new GraphDecoder(architecture, decodedGraph); 424 decoder.decode(encodedGraph); 425 426 decodedGraph.verify(); 427 try { 428 GraphComparison.verifyGraphsEqual(originalGraph, decodedGraph); 429 } catch (Throwable ex) { 430 originalGraph.getDebug(); 431 try (DebugContext.Scope scope = debug.scope("GraphEncoder")) { 432 debug.dump(DebugContext.VERBOSE_LEVEL, originalGraph, "Original Graph"); 433 debug.dump(DebugContext.VERBOSE_LEVEL, decodedGraph, "Decoded Graph"); 434 } 435 throw ex; 436 } 437 return true; 438 } 439 } 440 441 class GraphComparison { 442 public static boolean verifyGraphsEqual(StructuredGraph expectedGraph, StructuredGraph actualGraph) { 443 NodeMap<Node> nodeMapping = new NodeMap<>(expectedGraph); 444 Deque<Pair<Node, Node>> workList = new ArrayDeque<>(); 445 446 pushToWorklist(expectedGraph.start(), actualGraph.start(), nodeMapping, workList); 447 while (!workList.isEmpty()) { 448 Pair<Node, Node> pair = workList.removeFirst(); 449 Node expectedNode = pair.getLeft(); 450 Node actualNode = pair.getRight(); 451 assert expectedNode.getClass() == actualNode.getClass(); 452 453 NodeClass<?> nodeClass = expectedNode.getNodeClass(); |