src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File hotspot Sdiff src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial

src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java

Print this page




  15  * You should have received a copy of the GNU General Public License version
  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.core.test.tutorial;
  24 
  25 import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions;
  26 
  27 import java.util.ArrayDeque;
  28 import java.util.Collections;
  29 import java.util.Deque;
  30 import java.util.HashMap;
  31 import java.util.HashSet;
  32 import java.util.Map;
  33 import java.util.Set;
  34 
  35 import org.graalvm.compiler.debug.Debug;

  36 import org.graalvm.compiler.debug.GraalError;
  37 import org.graalvm.compiler.debug.Debug.Scope;
  38 import org.graalvm.compiler.graph.Node;
  39 import org.graalvm.compiler.graph.NodeMap;
  40 import org.graalvm.compiler.java.GraphBuilderPhase;
  41 import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
  42 import org.graalvm.compiler.nodes.ConstantNode;
  43 import org.graalvm.compiler.nodes.FixedNode;
  44 import org.graalvm.compiler.nodes.Invoke;
  45 import org.graalvm.compiler.nodes.ParameterNode;
  46 import org.graalvm.compiler.nodes.ReturnNode;
  47 import org.graalvm.compiler.nodes.StructuredGraph;
  48 import org.graalvm.compiler.nodes.ValueNode;
  49 import org.graalvm.compiler.nodes.ValuePhiNode;
  50 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  51 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
  52 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
  53 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
  54 import org.graalvm.compiler.nodes.java.LoadFieldNode;
  55 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
  56 import org.graalvm.compiler.nodes.java.NewArrayNode;
  57 import org.graalvm.compiler.nodes.java.NewInstanceNode;
  58 import org.graalvm.compiler.nodes.java.StoreFieldNode;
  59 import org.graalvm.compiler.nodes.spi.StampProvider;
  60 import org.graalvm.compiler.nodes.util.GraphUtil;

  61 import org.graalvm.compiler.phases.OptimisticOptimizations;
  62 import org.graalvm.compiler.phases.graph.StatelessPostOrderNodeIterator;
  63 
  64 import jdk.vm.ci.meta.JavaConstant;
  65 import jdk.vm.ci.meta.JavaKind;
  66 import jdk.vm.ci.meta.MetaAccessProvider;
  67 import jdk.vm.ci.meta.ResolvedJavaField;
  68 import jdk.vm.ci.meta.ResolvedJavaMethod;
  69 import jdk.vm.ci.meta.ResolvedJavaType;
  70 
  71 /**
  72  * A simple context-insensitive static analysis based on the Graal API. It is intended for
  73  * educational purposes, not for use in production. Only a limited set of Java functionality is
  74  * supported to keep the code minimal.
  75  * <p>
  76  * The analysis builds a directed graph of {@link TypeFlow type flows}. If a type is added to type
  77  * flow, it is propagated to all {@link TypeFlow#uses uses} of the type flow. Types are propagated
  78  * using a {@link #worklist} of changed type flows until a fixpoint is reached, i.e., until no more
  79  * types need to be added to any type state.
  80  * <p>


 223         }
 224 
 225         /**
 226          * All {@link TypeFlow#getTypes() types} that the return value of this method can have.
 227          */
 228         public TypeFlow getFormalReturn() {
 229             return formalReturn;
 230         }
 231 
 232         @Override
 233         @SuppressWarnings("try")
 234         protected void process() {
 235             if (!processed) {
 236                 /* We want to process a method only once. */
 237                 processed = true;
 238 
 239                 /*
 240                  * Build the Graal graph for the method using the bytecode parser provided by Graal.
 241                  */
 242 
 243                 StructuredGraph graph = new StructuredGraph.Builder(getInitialOptions()).method(method).build();


 244                 /*
 245                  * Support for graph dumping, IGV uses this information to show the method name of a
 246                  * graph.
 247                  */
 248                 try (Scope scope = Debug.scope("graph building", graph)) {
 249                     /*
 250                      * We want all types to be resolved by the graph builder, i.e., we want classes
 251                      * referenced by the bytecodes to be loaded and initialized. Since we do not run
 252                      * the code before static analysis, the classes would otherwise be not loaded
 253                      * yet and the bytecode parser would only create a graph.
 254                      */
 255                     Plugins plugins = new Plugins(new InvocationPlugins());
 256                     GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
 257                     /*
 258                      * For simplicity, we ignore all exception handling during the static analysis.
 259                      * This is a constraint of this example code, a real static analysis needs to
 260                      * handle the Graal nodes for throwing and handling exceptions.
 261                      */
 262                     graphBuilderConfig = graphBuilderConfig.withBytecodeExceptionMode(BytecodeExceptionMode.OmitAll);
 263                     /*
 264                      * We do not want Graal to perform any speculative optimistic optimizations,
 265                      * i.e., we do not want to use profiling information. Since we do not run the
 266                      * code before static analysis, the profiling information is empty and therefore
 267                      * wrong.
 268                      */
 269                     OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE;
 270 
 271                     GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, null, null, graphBuilderConfig, optimisticOpts, null);
 272                     graphBuilder.apply(graph);
 273                 } catch (Throwable ex) {
 274                     Debug.handle(ex);
 275                 }
 276 
 277                 /*
 278                  * Build the type flow graph from the Graal graph, i.e., process all nodes that are
 279                  * deal with objects.
 280                  */
 281 
 282                 TypeFlowBuilder typeFlowBuilder = new TypeFlowBuilder(graph);
 283                 typeFlowBuilder.apply();
 284             }
 285         }
 286     }
 287 
 288     /**
 289      * The active element during static analysis: types are added until a fixed point is reached.
 290      * When a new type is added, it is propagated to all usages by putting this element on the
 291      * {@link StaticAnalysis#addToWorklist worklist}.
 292      */
 293     public class TypeFlow extends WorklistEntry {
 294         private final Set<ResolvedJavaType> types;




  15  * You should have received a copy of the GNU General Public License version
  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.core.test.tutorial;
  24 
  25 import static org.graalvm.compiler.core.test.GraalCompilerTest.getInitialOptions;
  26 
  27 import java.util.ArrayDeque;
  28 import java.util.Collections;
  29 import java.util.Deque;
  30 import java.util.HashMap;
  31 import java.util.HashSet;
  32 import java.util.Map;
  33 import java.util.Set;
  34 
  35 import org.graalvm.compiler.debug.DebugHandlersFactory;
  36 import org.graalvm.compiler.debug.DebugContext;
  37 import org.graalvm.compiler.debug.GraalError;

  38 import org.graalvm.compiler.graph.Node;
  39 import org.graalvm.compiler.graph.NodeMap;
  40 import org.graalvm.compiler.java.GraphBuilderPhase;
  41 import org.graalvm.compiler.nodes.CallTargetNode.InvokeKind;
  42 import org.graalvm.compiler.nodes.ConstantNode;
  43 import org.graalvm.compiler.nodes.FixedNode;
  44 import org.graalvm.compiler.nodes.Invoke;
  45 import org.graalvm.compiler.nodes.ParameterNode;
  46 import org.graalvm.compiler.nodes.ReturnNode;
  47 import org.graalvm.compiler.nodes.StructuredGraph;
  48 import org.graalvm.compiler.nodes.ValueNode;
  49 import org.graalvm.compiler.nodes.ValuePhiNode;
  50 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  51 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.BytecodeExceptionMode;
  52 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
  53 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
  54 import org.graalvm.compiler.nodes.java.LoadFieldNode;
  55 import org.graalvm.compiler.nodes.java.MethodCallTargetNode;
  56 import org.graalvm.compiler.nodes.java.NewArrayNode;
  57 import org.graalvm.compiler.nodes.java.NewInstanceNode;
  58 import org.graalvm.compiler.nodes.java.StoreFieldNode;
  59 import org.graalvm.compiler.nodes.spi.StampProvider;
  60 import org.graalvm.compiler.nodes.util.GraphUtil;
  61 import org.graalvm.compiler.options.OptionValues;
  62 import org.graalvm.compiler.phases.OptimisticOptimizations;
  63 import org.graalvm.compiler.phases.graph.StatelessPostOrderNodeIterator;
  64 
  65 import jdk.vm.ci.meta.JavaConstant;
  66 import jdk.vm.ci.meta.JavaKind;
  67 import jdk.vm.ci.meta.MetaAccessProvider;
  68 import jdk.vm.ci.meta.ResolvedJavaField;
  69 import jdk.vm.ci.meta.ResolvedJavaMethod;
  70 import jdk.vm.ci.meta.ResolvedJavaType;
  71 
  72 /**
  73  * A simple context-insensitive static analysis based on the Graal API. It is intended for
  74  * educational purposes, not for use in production. Only a limited set of Java functionality is
  75  * supported to keep the code minimal.
  76  * <p>
  77  * The analysis builds a directed graph of {@link TypeFlow type flows}. If a type is added to type
  78  * flow, it is propagated to all {@link TypeFlow#uses uses} of the type flow. Types are propagated
  79  * using a {@link #worklist} of changed type flows until a fixpoint is reached, i.e., until no more
  80  * types need to be added to any type state.
  81  * <p>


 224         }
 225 
 226         /**
 227          * All {@link TypeFlow#getTypes() types} that the return value of this method can have.
 228          */
 229         public TypeFlow getFormalReturn() {
 230             return formalReturn;
 231         }
 232 
 233         @Override
 234         @SuppressWarnings("try")
 235         protected void process() {
 236             if (!processed) {
 237                 /* We want to process a method only once. */
 238                 processed = true;
 239 
 240                 /*
 241                  * Build the Graal graph for the method using the bytecode parser provided by Graal.
 242                  */
 243 
 244                 OptionValues options = getInitialOptions();
 245                 DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER);
 246                 StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).build();
 247                 /*
 248                  * Support for graph dumping, IGV uses this information to show the method name of a
 249                  * graph.
 250                  */
 251                 try (DebugContext.Scope scope = debug.scope("graph building", graph)) {
 252                     /*
 253                      * We want all types to be resolved by the graph builder, i.e., we want classes
 254                      * referenced by the bytecodes to be loaded and initialized. Since we do not run
 255                      * the code before static analysis, the classes would otherwise be not loaded
 256                      * yet and the bytecode parser would only create a graph.
 257                      */
 258                     Plugins plugins = new Plugins(new InvocationPlugins());
 259                     GraphBuilderConfiguration graphBuilderConfig = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true);
 260                     /*
 261                      * For simplicity, we ignore all exception handling during the static analysis.
 262                      * This is a constraint of this example code, a real static analysis needs to
 263                      * handle the Graal nodes for throwing and handling exceptions.
 264                      */
 265                     graphBuilderConfig = graphBuilderConfig.withBytecodeExceptionMode(BytecodeExceptionMode.OmitAll);
 266                     /*
 267                      * We do not want Graal to perform any speculative optimistic optimizations,
 268                      * i.e., we do not want to use profiling information. Since we do not run the
 269                      * code before static analysis, the profiling information is empty and therefore
 270                      * wrong.
 271                      */
 272                     OptimisticOptimizations optimisticOpts = OptimisticOptimizations.NONE;
 273 
 274                     GraphBuilderPhase.Instance graphBuilder = new GraphBuilderPhase.Instance(metaAccess, stampProvider, null, null, graphBuilderConfig, optimisticOpts, null);
 275                     graphBuilder.apply(graph);
 276                 } catch (Throwable ex) {
 277                     debug.handle(ex);
 278                 }
 279 
 280                 /*
 281                  * Build the type flow graph from the Graal graph, i.e., process all nodes that are
 282                  * deal with objects.
 283                  */
 284 
 285                 TypeFlowBuilder typeFlowBuilder = new TypeFlowBuilder(graph);
 286                 typeFlowBuilder.apply();
 287             }
 288         }
 289     }
 290 
 291     /**
 292      * The active element during static analysis: types are added until a fixed point is reached.
 293      * When a new type is added, it is propagated to all usages by putting this element on the
 294      * {@link StaticAnalysis#addToWorklist worklist}.
 295      */
 296     public class TypeFlow extends WorklistEntry {
 297         private final Set<ResolvedJavaType> types;


src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/tutorial/StaticAnalysis.java
Index Unified diffs Context diffs Sdiffs Patch New Old Previous File Next File