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; |