Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance. Project price only 1 $
You can buy this project and download/modify it how often you want.
/*
* Copyright (c) 2015, 2023, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation. Oracle designates this
* particular file as subject to the "Classpath" exception as provided
* by Oracle in the LICENSE file that accompanied this code.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package org.graalvm.compiler.nodes;
import java.util.ArrayDeque;
import java.util.Deque;
import java.util.Iterator;
import java.util.Objects;
import org.graalvm.collections.Pair;
import org.graalvm.collections.UnmodifiableMapCursor;
import org.graalvm.compiler.core.common.Fields;
import org.graalvm.compiler.core.common.util.FrequencyEncoder;
import org.graalvm.compiler.core.common.util.TypeConversion;
import org.graalvm.compiler.core.common.util.TypeReader;
import org.graalvm.compiler.core.common.util.TypeWriter;
import org.graalvm.compiler.core.common.util.UnsafeArrayTypeWriter;
import org.graalvm.compiler.debug.DebugContext;
import org.graalvm.compiler.debug.GraalError;
import org.graalvm.compiler.graph.Edges;
import org.graalvm.compiler.graph.Node;
import org.graalvm.compiler.graph.NodeClass;
import org.graalvm.compiler.graph.NodeList;
import org.graalvm.compiler.graph.NodeMap;
import org.graalvm.compiler.graph.iterators.NodeIterable;
import org.graalvm.compiler.nodes.EncodedGraph.EncodedNodeReference;
import org.graalvm.compiler.nodes.java.ExceptionObjectNode;
import org.graalvm.compiler.replacements.nodes.MethodHandleWithExceptionNode;
import jdk.vm.ci.code.Architecture;
/**
* Encodes a {@link 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 {@link #prepare}
* is called for all graphs first, followed by one call to {@link #finishPrepare}. Then
* {@link #encode} can be called for all graphs. The {@link #getObjects() objects} and
* {@link #getNodeClasses() 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 {@link Object#equals Object equality}. This uses the assumption and good
* coding practice that data objects are immutable if {@link Object#equals} is implemented.
* Unfortunately, this cannot be enforced.
*
* The Graal {@link NodeClass} does not have a unique id that allows class lookup from an id.
* Therefore, the encoded graph contains a {@link 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 {@link #encode} and stored in
* {@link EncodedGraph#getStartOffset()}. The order of nodes in the table of contents is the
* {@link NodeOrder#orderIds 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
* {@link EndNode predecessors} of a {@link AbstractBeginNode 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:
*
*
*
* All numbers (unsigned and signed) are stored using a variable-length encoding as defined in
* {@link TypeReader} and {@link 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
* {@link NodeClass#getData}, {@link NodeClass#getSuccessorEdges()}, and
* {@link 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:
*
{@link AbstractEndNode}: the orderId of the merge node and then all {@link PhiNode phi
* mappings} from this end to the merge node are written. {@link LoopExitNode}: the orderId of
* all {@link ProxyNode proxy nodes} of the loop exit is written.
*/
public class GraphEncoder {
/**
* The orderId that always represents {@code null}.
*/
public static final int NULL_ORDER_ID = 0;
/**
* The orderId of the {@link StructuredGraph#start() start node} of the encoded graph.
*/
public static final int START_NODE_ORDER_ID = 1;
/**
* The orderId of the first actual node after the {@link StructuredGraph#start() start node}.
*/
public static final int FIRST_NODE_ORDER_ID = 2;
/**
* Maximum unsigned integer fitting on 1 byte.
*/
public static final int MAX_INDEX_1_BYTE = 1 << 8 - 1;
/**
* Maximum unsigned integer fitting on 2 bytes.
*/
public static final int MAX_INDEX_2_BYTES = 1 << 16 - 1;
/**
* The known offset between the orderId of a {@link AbstractBeginNode} and its
* {@link AbstractBeginNode#next() successor}.
*/
protected static final int BEGIN_NEXT_ORDER_ID_OFFSET = 1;
protected final Architecture architecture;
/**
* Collects all non-primitive data referenced from nodes. The encoding uses an index into an
* array for decoding. Because of the variable-length encoding, it is beneficial that frequently
* used objects have the small indices.
*/
protected final FrequencyEncoder