< prev index next >

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

Print this page
rev 56282 : [mq]: graal


  26 
  27 import static java.lang.reflect.Modifier.isStatic;
  28 import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
  29 import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes;
  30 import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
  31 import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION;
  32 
  33 import java.lang.annotation.ElementType;
  34 import java.lang.annotation.Retention;
  35 import java.lang.annotation.RetentionPolicy;
  36 import java.lang.annotation.Target;
  37 import java.lang.reflect.Constructor;
  38 import java.lang.reflect.Executable;
  39 import java.lang.reflect.InvocationTargetException;
  40 import java.lang.reflect.Method;
  41 import java.util.ArrayList;
  42 import java.util.Arrays;
  43 import java.util.Collection;
  44 import java.util.Collections;
  45 import java.util.EnumMap;

  46 import java.util.List;
  47 import java.util.ListIterator;
  48 import java.util.Map;
  49 import java.util.Set;
  50 import java.util.concurrent.ConcurrentHashMap;
  51 import java.util.function.Supplier;
  52 
  53 import org.graalvm.compiler.api.directives.GraalDirectives;
  54 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
  55 import org.graalvm.compiler.api.test.Graal;
  56 import org.graalvm.compiler.code.CompilationResult;
  57 import org.graalvm.compiler.core.CompilationPrinter;
  58 import org.graalvm.compiler.core.GraalCompiler;
  59 import org.graalvm.compiler.core.GraalCompiler.Request;
  60 import org.graalvm.compiler.core.common.CompilationIdentifier;
  61 import org.graalvm.compiler.core.common.type.StampFactory;
  62 import org.graalvm.compiler.core.target.Backend;
  63 import org.graalvm.compiler.debug.DebugContext;
  64 import org.graalvm.compiler.debug.DebugDumpHandler;
  65 import org.graalvm.compiler.debug.DebugDumpScope;
  66 import org.graalvm.compiler.debug.DebugHandlersFactory;
  67 import org.graalvm.compiler.debug.GraalError;
  68 import org.graalvm.compiler.debug.TTY;
  69 import org.graalvm.compiler.graph.Node;
  70 import org.graalvm.compiler.graph.NodeClass;
  71 import org.graalvm.compiler.graph.NodeMap;
  72 import org.graalvm.compiler.java.BytecodeParser;
  73 import org.graalvm.compiler.java.ComputeLoopFrequenciesClosure;
  74 import org.graalvm.compiler.java.GraphBuilderPhase;
  75 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
  76 import org.graalvm.compiler.lir.phases.LIRSuites;

  77 import org.graalvm.compiler.nodeinfo.NodeInfo;
  78 import org.graalvm.compiler.nodeinfo.NodeSize;
  79 import org.graalvm.compiler.nodeinfo.Verbosity;
  80 import org.graalvm.compiler.nodes.BreakpointNode;
  81 import org.graalvm.compiler.nodes.Cancellable;
  82 import org.graalvm.compiler.nodes.ConstantNode;
  83 import org.graalvm.compiler.nodes.FixedWithNextNode;
  84 import org.graalvm.compiler.nodes.FrameState;
  85 import org.graalvm.compiler.nodes.FullInfopointNode;
  86 import org.graalvm.compiler.nodes.Invoke;
  87 import org.graalvm.compiler.nodes.InvokeNode;
  88 import org.graalvm.compiler.nodes.InvokeWithExceptionNode;
  89 import org.graalvm.compiler.nodes.ParameterNode;
  90 import org.graalvm.compiler.nodes.ProxyNode;
  91 import org.graalvm.compiler.nodes.ReturnNode;
  92 import org.graalvm.compiler.nodes.StructuredGraph;
  93 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  94 import org.graalvm.compiler.nodes.StructuredGraph.Builder;
  95 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
  96 import org.graalvm.compiler.nodes.ValueNode;
  97 import org.graalvm.compiler.nodes.cfg.Block;
  98 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  99 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 100 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
 101 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
 102 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
 103 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
 104 import org.graalvm.compiler.nodes.java.AccessFieldNode;
 105 import org.graalvm.compiler.nodes.spi.LoweringProvider;
 106 import org.graalvm.compiler.nodes.spi.Replacements;
 107 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
 108 import org.graalvm.compiler.options.OptionValues;
 109 import org.graalvm.compiler.phases.BasePhase;
 110 import org.graalvm.compiler.phases.OptimisticOptimizations;
 111 import org.graalvm.compiler.phases.Phase;
 112 import org.graalvm.compiler.phases.PhaseSuite;
 113 import org.graalvm.compiler.phases.common.CanonicalizerPhase;
 114 import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
 115 import org.graalvm.compiler.phases.common.inlining.InliningPhase;
 116 import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
 117 import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy;
 118 import org.graalvm.compiler.phases.schedule.SchedulePhase;
 119 import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
 120 import org.graalvm.compiler.phases.tiers.HighTierContext;
 121 import org.graalvm.compiler.phases.tiers.MidTierContext;
 122 import org.graalvm.compiler.phases.tiers.Suites;
 123 import org.graalvm.compiler.phases.tiers.TargetProvider;
 124 import org.graalvm.compiler.phases.util.Providers;
 125 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
 126 import org.graalvm.compiler.runtime.RuntimeProvider;
 127 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
 128 import org.graalvm.compiler.test.AddExports;
 129 import org.graalvm.compiler.test.GraalTest;
 130 import org.graalvm.compiler.test.JLModule;
 131 import org.junit.After;
 132 import org.junit.Assert;

 133 import org.junit.Test;
 134 import org.junit.internal.AssumptionViolatedException;
 135 
 136 import jdk.vm.ci.code.Architecture;
 137 import jdk.vm.ci.code.BailoutException;
 138 import jdk.vm.ci.code.CodeCacheProvider;
 139 import jdk.vm.ci.code.InstalledCode;
 140 import jdk.vm.ci.code.TargetDescription;
 141 import jdk.vm.ci.meta.Assumptions.Assumption;
 142 import jdk.vm.ci.meta.ConstantReflectionProvider;
 143 import jdk.vm.ci.meta.DeoptimizationReason;
 144 import jdk.vm.ci.meta.JavaConstant;
 145 import jdk.vm.ci.meta.JavaKind;
 146 import jdk.vm.ci.meta.JavaType;
 147 import jdk.vm.ci.meta.MetaAccessProvider;
 148 import jdk.vm.ci.meta.ProfilingInfo;
 149 import jdk.vm.ci.meta.ResolvedJavaMethod;
 150 import jdk.vm.ci.meta.ResolvedJavaType;
 151 import jdk.vm.ci.meta.SpeculationLog;
 152 


 178      */
 179     public static OptionValues getInitialOptions() {
 180         return Graal.getRequiredCapability(OptionValues.class);
 181     }
 182 
 183     private static final int BAILOUT_RETRY_LIMIT = 1;
 184     private final Providers providers;
 185     private final Backend backend;
 186 
 187     /**
 188      * Representative class for the {@code java.base} module.
 189      */
 190     public static final Class<?> JAVA_BASE = Class.class;
 191 
 192     /**
 193      * Exports the package named {@code packageName} declared in {@code moduleMember}'s module to
 194      * this object's module. This must be called before accessing packages that are no longer public
 195      * as of JDK 9.
 196      */
 197     protected final void exportPackage(Class<?> moduleMember, String packageName) {
 198         if (JavaVersionUtil.JAVA_SPEC > 8) {
 199             JLModule.exportPackageTo(moduleMember, packageName, getClass());
 200         }
 201     }
 202 
 203     /**
 204      * Denotes a test method that must be inlined by the {@link BytecodeParser}.
 205      */
 206     @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
 207     @Retention(RetentionPolicy.RUNTIME)
 208     public @interface BytecodeParserForceInline {
 209     }
 210 
 211     /**
 212      * Denotes a test method that must never be inlined by the {@link BytecodeParser}.
 213      */
 214     @Retention(RetentionPolicy.RUNTIME)
 215     @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
 216     public @interface BytecodeParserNeverInline {
 217         /**
 218          * Specifies if the call should be implemented with {@link InvokeWithExceptionNode} instead
 219          * of {@link InvokeNode}.
 220          */


 327             }
 328 
 329             @Override
 330             public float codeSizeIncrease() {
 331                 return NodeSize.IGNORE_SIZE_CONTRACT_FACTOR;
 332             }
 333 
 334             @Override
 335             protected CharSequence getName() {
 336                 return "CheckGraphPhase";
 337             }
 338         });
 339         return ret;
 340     }
 341 
 342     protected LIRSuites createLIRSuites(OptionValues opts) {
 343         LIRSuites ret = backend.getSuites().getDefaultLIRSuites(opts).copy();
 344         return ret;
 345     }
 346 







 347     public GraalCompilerTest() {
 348         this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
 349         this.providers = getBackend().getProviders();
 350     }
 351 
 352     /**
 353      * Set up a test for a non-default backend. The test should check (via {@link #getBackend()} )
 354      * whether the desired backend is available.
 355      *
 356      * @param arch the name of the desired backend architecture
 357      */
 358     public GraalCompilerTest(Class<? extends Architecture> arch) {
 359         RuntimeProvider runtime = Graal.getRequiredCapability(RuntimeProvider.class);
 360         Backend b = runtime.getBackend(arch);
 361         if (b != null) {
 362             this.backend = b;
 363         } else {
 364             // Fall back to the default/host backend
 365             this.backend = runtime.getHostBackend();
 366         }


 906                     ArrayStoreException.class,
 907                     ClassCastException.class,
 908                     NullPointerException.class);
 909 
 910     protected void assertEquals(Result expect, Result actual) {
 911         if (expect.exception != null) {
 912             Assert.assertTrue("expected " + expect.exception, actual.exception != null);
 913             Assert.assertEquals("Exception class", expect.exception.getClass(), actual.exception.getClass());
 914             // C2 can optimize out the stack trace and message in some cases
 915             if (expect.exception.getMessage() != null || !C2_OMIT_STACK_TRACE_IN_FAST_THROW_EXCEPTIONS.contains(expect.exception.getClass())) {
 916                 Assert.assertEquals("Exception message", expect.exception.getMessage(), actual.exception.getMessage());
 917             }
 918         } else {
 919             if (actual.exception != null) {
 920                 throw new AssertionError("expected " + expect.returnValue + " but got an exception", actual.exception);
 921             }
 922             assertDeepEquals(expect.returnValue, actual.returnValue);
 923         }
 924     }
 925 
 926     private Map<ResolvedJavaMethod, InstalledCode> cache = new ConcurrentHashMap<>();
 927 
 928     /**
 929      * Gets installed code for a given method, compiling it first if necessary. The graph is parsed
 930      * {@link #parseEager eagerly}.
 931      */
 932     protected final InstalledCode getCode(ResolvedJavaMethod method) {
 933         return getCode(method, null, false, false, getInitialOptions());
 934     }
 935 
 936     protected final InstalledCode getCode(ResolvedJavaMethod method, OptionValues options) {
 937         return getCode(method, null, false, false, options);
 938     }
 939 
 940     /**
 941      * Gets installed code for a given method, compiling it first if necessary.
 942      *
 943      * @param installedCodeOwner the method the compiled code will be associated with when installed
 944      * @param graph the graph to be compiled. If null, a graph will be obtained from
 945      *            {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}.
 946      */
 947     protected final InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) {


 959      */
 960     protected final InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile) {
 961         return getCode(installedCodeOwner, graph, forceCompile, false, graph == null ? getInitialOptions() : graph.getOptions());
 962     }
 963 
 964     /**
 965      * Gets installed code for a given method and graph, compiling it first if necessary.
 966      *
 967      * @param installedCodeOwner the method the compiled code will be associated with when installed
 968      * @param graph the graph to be compiled. If null, a graph will be obtained from
 969      *            {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}.
 970      * @param forceCompile specifies whether to ignore any previous code cached for the (method,
 971      *            key) pair
 972      * @param installAsDefault specifies whether to install as the default implementation
 973      * @param options the options that will be used in {@link #parseForCompile(ResolvedJavaMethod)}
 974      */
 975     @SuppressWarnings("try")
 976     protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) {
 977         boolean useCache = !forceCompile && getArgumentToBind() == null;
 978         if (useCache && graph == null) {
 979             InstalledCode cached = cache.get(installedCodeOwner);
 980             if (cached != null) {
 981                 if (cached.isValid()) {
 982                     return cached;
 983                 }
 984             }
 985         }
 986         // loop for retrying compilation
 987         for (int retry = 0; retry <= BAILOUT_RETRY_LIMIT; retry++) {
 988             final CompilationIdentifier id = getOrCreateCompilationId(installedCodeOwner, graph);
 989 
 990             InstalledCode installedCode = null;
 991             StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, id, options) : graph;
 992             DebugContext debug = graphToCompile.getDebug();
 993 
 994             try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", new DebugDumpScope(id.toString(CompilationIdentifier.Verbosity.ID), true))) {
 995                 CompilationPrinter printer = CompilationPrinter.begin(options, id, installedCodeOwner, INVOCATION_ENTRY_BCI);
 996                 CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(graphToCompile.compilationId()), id, options);
 997                 printer.finish(compResult);
 998 
 999                 try (DebugContext.Scope s = debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult);
1000                                 DebugContext.Activation a = debug.activate()) {
1001                     try {
1002                         if (installAsDefault) {
1003                             installedCode = addDefaultMethod(debug, installedCodeOwner, compResult);
1004                         } else {
1005                             installedCode = addMethod(debug, installedCodeOwner, compResult);
1006                         }
1007                         if (installedCode == null) {
1008                             throw new GraalError("Could not install code for " + installedCodeOwner.format("%H.%n(%p)"));
1009                         }
1010                     } catch (BailoutException e) {
1011                         if (retry < BAILOUT_RETRY_LIMIT && graph == null && !e.isPermanent()) {
1012                             // retry (if there is no predefined graph)
1013                             TTY.println(String.format("Restart compilation %s (%s) due to a non-permanent bailout!", installedCodeOwner, id));
1014                             continue;
1015                         }
1016                         throw e;
1017                     }
1018                 } catch (Throwable e) {
1019                     throw debug.handle(e);
1020                 }
1021             } catch (Throwable e) {
1022                 throw debug.handle(e);
1023             }
1024 
1025             if (useCache) {
1026                 cache.put(installedCodeOwner, installedCode);
1027             }
1028             return installedCode;
1029         }
1030         throw GraalError.shouldNotReachHere();
1031     }
1032 
1033     /**
1034      * Used to produce a graph for a method about to be compiled by
1035      * {@link #compile(ResolvedJavaMethod, StructuredGraph)} if the second parameter to that method
1036      * is null.
1037      *
1038      * The default implementation in {@link GraalCompilerTest} is to call {@link #parseEager}.
1039      */
1040     protected StructuredGraph parseForCompile(ResolvedJavaMethod method, OptionValues options) {
1041         return parseEager(method, AllowAssumptions.YES, getCompilationId(method), options);
1042     }
1043 
1044     protected final StructuredGraph parseForCompile(ResolvedJavaMethod method, DebugContext debug) {
1045         return parseEager(method, AllowAssumptions.YES, debug);
1046     }


1305         ResolvedJavaMethod javaMethod = builder.getMethod();
1306         builder.speculationLog(getSpeculationLog());
1307         if (builder.getCancellable() == null) {
1308             builder.cancellable(getCancellable(javaMethod));
1309         }
1310         assert javaMethod.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + javaMethod;
1311         StructuredGraph graph = builder.build();
1312         DebugContext debug = graph.getDebug();
1313         try (DebugContext.Scope ds = debug.scope("Parsing", javaMethod, graph)) {
1314             graphBuilderSuite.apply(graph, getDefaultHighTierContext());
1315             Object[] args = getArgumentToBind();
1316             if (args != null) {
1317                 bindArguments(graph, args);
1318             }
1319             return graph;
1320         } catch (Throwable e) {
1321             throw debug.handle(e);
1322         }
1323     }
1324 


1325     protected void bindArguments(StructuredGraph graph, Object[] argsToBind) {
1326         ResolvedJavaMethod m = graph.method();
1327         Object receiver = isStatic(m.getModifiers()) ? null : this;
1328         Object[] args = argsWithReceiver(receiver, argsToBind);
1329         JavaType[] parameterTypes = m.toParameterTypes();
1330         assert parameterTypes.length == args.length;
1331         for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
1332             JavaConstant c = getSnippetReflection().forBoxed(parameterTypes[param.index()].getJavaKind(), args[param.index()]);


1333             ConstantNode replacement = ConstantNode.forConstant(c, getMetaAccess(), graph);
1334             param.replaceAtUsages(replacement);

1335         }
1336     }
1337 
1338     protected Object[] getArgumentToBind() {
1339         return null;
1340     }
1341 
1342     protected PhaseSuite<HighTierContext> getEagerGraphBuilderSuite() {
1343         return getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true).withUnresolvedIsError(true));
1344     }
1345 
1346     /**
1347      * Gets the cancellable that should be associated with a graph being created by any of the
1348      * {@code parse...()} methods.
1349      *
1350      * @param method the method being parsed into a graph
1351      */
1352     protected Cancellable getCancellable(ResolvedJavaMethod method) {
1353         return null;
1354     }




  26 
  27 import static java.lang.reflect.Modifier.isStatic;
  28 import static jdk.vm.ci.runtime.JVMCICompiler.INVOCATION_ENTRY_BCI;
  29 import static org.graalvm.compiler.nodes.ConstantNode.getConstantNodes;
  30 import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_NO_EXCEPTION;
  31 import static org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin.InlineInfo.DO_NOT_INLINE_WITH_EXCEPTION;
  32 
  33 import java.lang.annotation.ElementType;
  34 import java.lang.annotation.Retention;
  35 import java.lang.annotation.RetentionPolicy;
  36 import java.lang.annotation.Target;
  37 import java.lang.reflect.Constructor;
  38 import java.lang.reflect.Executable;
  39 import java.lang.reflect.InvocationTargetException;
  40 import java.lang.reflect.Method;
  41 import java.util.ArrayList;
  42 import java.util.Arrays;
  43 import java.util.Collection;
  44 import java.util.Collections;
  45 import java.util.EnumMap;
  46 import java.util.HashMap;
  47 import java.util.List;
  48 import java.util.ListIterator;
  49 import java.util.Map;
  50 import java.util.Set;
  51 import java.util.concurrent.ConcurrentHashMap;
  52 import java.util.function.Supplier;
  53 
  54 import org.graalvm.compiler.api.directives.GraalDirectives;
  55 import org.graalvm.compiler.api.replacements.SnippetReflectionProvider;
  56 import org.graalvm.compiler.api.test.Graal;
  57 import org.graalvm.compiler.code.CompilationResult;
  58 import org.graalvm.compiler.core.CompilationPrinter;
  59 import org.graalvm.compiler.core.GraalCompiler;
  60 import org.graalvm.compiler.core.GraalCompiler.Request;
  61 import org.graalvm.compiler.core.common.CompilationIdentifier;
  62 import org.graalvm.compiler.core.common.type.StampFactory;
  63 import org.graalvm.compiler.core.target.Backend;
  64 import org.graalvm.compiler.debug.DebugContext;
  65 import org.graalvm.compiler.debug.DebugDumpHandler;

  66 import org.graalvm.compiler.debug.DebugHandlersFactory;
  67 import org.graalvm.compiler.debug.GraalError;
  68 import org.graalvm.compiler.debug.TTY;
  69 import org.graalvm.compiler.graph.Node;
  70 import org.graalvm.compiler.graph.NodeClass;
  71 import org.graalvm.compiler.graph.NodeMap;
  72 import org.graalvm.compiler.java.BytecodeParser;
  73 import org.graalvm.compiler.java.ComputeLoopFrequenciesClosure;
  74 import org.graalvm.compiler.java.GraphBuilderPhase;
  75 import org.graalvm.compiler.lir.asm.CompilationResultBuilderFactory;
  76 import org.graalvm.compiler.lir.phases.LIRSuites;
  77 import org.graalvm.compiler.loop.phases.ConvertDeoptimizeToGuardPhase;
  78 import org.graalvm.compiler.nodeinfo.NodeInfo;
  79 import org.graalvm.compiler.nodeinfo.NodeSize;
  80 import org.graalvm.compiler.nodeinfo.Verbosity;
  81 import org.graalvm.compiler.nodes.BreakpointNode;
  82 import org.graalvm.compiler.nodes.Cancellable;
  83 import org.graalvm.compiler.nodes.ConstantNode;
  84 import org.graalvm.compiler.nodes.FixedWithNextNode;
  85 import org.graalvm.compiler.nodes.FrameState;
  86 import org.graalvm.compiler.nodes.FullInfopointNode;
  87 import org.graalvm.compiler.nodes.Invoke;
  88 import org.graalvm.compiler.nodes.InvokeNode;
  89 import org.graalvm.compiler.nodes.InvokeWithExceptionNode;
  90 import org.graalvm.compiler.nodes.ParameterNode;
  91 import org.graalvm.compiler.nodes.ProxyNode;
  92 import org.graalvm.compiler.nodes.ReturnNode;
  93 import org.graalvm.compiler.nodes.StructuredGraph;
  94 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  95 import org.graalvm.compiler.nodes.StructuredGraph.Builder;
  96 import org.graalvm.compiler.nodes.StructuredGraph.ScheduleResult;
  97 import org.graalvm.compiler.nodes.ValueNode;
  98 import org.graalvm.compiler.nodes.cfg.Block;
  99 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
 100 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
 101 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderContext;
 102 import org.graalvm.compiler.nodes.graphbuilderconf.InlineInvokePlugin;
 103 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugin;
 104 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
 105 import org.graalvm.compiler.nodes.java.AccessFieldNode;
 106 import org.graalvm.compiler.nodes.spi.LoweringProvider;
 107 import org.graalvm.compiler.nodes.spi.Replacements;
 108 import org.graalvm.compiler.nodes.virtual.VirtualObjectNode;
 109 import org.graalvm.compiler.options.OptionValues;
 110 import org.graalvm.compiler.phases.BasePhase;
 111 import org.graalvm.compiler.phases.OptimisticOptimizations;
 112 import org.graalvm.compiler.phases.Phase;
 113 import org.graalvm.compiler.phases.PhaseSuite;
 114 import org.graalvm.compiler.phases.common.CanonicalizerPhase;

 115 import org.graalvm.compiler.phases.common.inlining.InliningPhase;
 116 import org.graalvm.compiler.phases.common.inlining.info.InlineInfo;
 117 import org.graalvm.compiler.phases.common.inlining.policy.GreedyInliningPolicy;
 118 import org.graalvm.compiler.phases.schedule.SchedulePhase;
 119 import org.graalvm.compiler.phases.schedule.SchedulePhase.SchedulingStrategy;
 120 import org.graalvm.compiler.phases.tiers.HighTierContext;
 121 import org.graalvm.compiler.phases.tiers.MidTierContext;
 122 import org.graalvm.compiler.phases.tiers.Suites;
 123 import org.graalvm.compiler.phases.tiers.TargetProvider;
 124 import org.graalvm.compiler.phases.util.Providers;
 125 import org.graalvm.compiler.printer.GraalDebugHandlersFactory;
 126 import org.graalvm.compiler.runtime.RuntimeProvider;

 127 import org.graalvm.compiler.test.AddExports;
 128 import org.graalvm.compiler.test.GraalTest;
 129 import org.graalvm.compiler.test.ModuleSupport;
 130 import org.junit.After;
 131 import org.junit.Assert;
 132 import org.junit.BeforeClass;
 133 import org.junit.Test;
 134 import org.junit.internal.AssumptionViolatedException;
 135 
 136 import jdk.vm.ci.code.Architecture;
 137 import jdk.vm.ci.code.BailoutException;
 138 import jdk.vm.ci.code.CodeCacheProvider;
 139 import jdk.vm.ci.code.InstalledCode;
 140 import jdk.vm.ci.code.TargetDescription;
 141 import jdk.vm.ci.meta.Assumptions.Assumption;
 142 import jdk.vm.ci.meta.ConstantReflectionProvider;
 143 import jdk.vm.ci.meta.DeoptimizationReason;
 144 import jdk.vm.ci.meta.JavaConstant;
 145 import jdk.vm.ci.meta.JavaKind;
 146 import jdk.vm.ci.meta.JavaType;
 147 import jdk.vm.ci.meta.MetaAccessProvider;
 148 import jdk.vm.ci.meta.ProfilingInfo;
 149 import jdk.vm.ci.meta.ResolvedJavaMethod;
 150 import jdk.vm.ci.meta.ResolvedJavaType;
 151 import jdk.vm.ci.meta.SpeculationLog;
 152 


 178      */
 179     public static OptionValues getInitialOptions() {
 180         return Graal.getRequiredCapability(OptionValues.class);
 181     }
 182 
 183     private static final int BAILOUT_RETRY_LIMIT = 1;
 184     private final Providers providers;
 185     private final Backend backend;
 186 
 187     /**
 188      * Representative class for the {@code java.base} module.
 189      */
 190     public static final Class<?> JAVA_BASE = Class.class;
 191 
 192     /**
 193      * Exports the package named {@code packageName} declared in {@code moduleMember}'s module to
 194      * this object's module. This must be called before accessing packages that are no longer public
 195      * as of JDK 9.
 196      */
 197     protected final void exportPackage(Class<?> moduleMember, String packageName) {
 198         ModuleSupport.exportPackageTo(moduleMember, packageName, getClass());


 199     }
 200 
 201     /**
 202      * Denotes a test method that must be inlined by the {@link BytecodeParser}.
 203      */
 204     @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
 205     @Retention(RetentionPolicy.RUNTIME)
 206     public @interface BytecodeParserForceInline {
 207     }
 208 
 209     /**
 210      * Denotes a test method that must never be inlined by the {@link BytecodeParser}.
 211      */
 212     @Retention(RetentionPolicy.RUNTIME)
 213     @Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
 214     public @interface BytecodeParserNeverInline {
 215         /**
 216          * Specifies if the call should be implemented with {@link InvokeWithExceptionNode} instead
 217          * of {@link InvokeNode}.
 218          */


 325             }
 326 
 327             @Override
 328             public float codeSizeIncrease() {
 329                 return NodeSize.IGNORE_SIZE_CONTRACT_FACTOR;
 330             }
 331 
 332             @Override
 333             protected CharSequence getName() {
 334                 return "CheckGraphPhase";
 335             }
 336         });
 337         return ret;
 338     }
 339 
 340     protected LIRSuites createLIRSuites(OptionValues opts) {
 341         LIRSuites ret = backend.getSuites().getDefaultLIRSuites(opts).copy();
 342         return ret;
 343     }
 344 
 345     private static final ThreadLocal<HashMap<ResolvedJavaMethod, InstalledCode>> cache = ThreadLocal.withInitial(HashMap::new);
 346 
 347     @BeforeClass
 348     public static void resetCache() {
 349         cache.get().clear();
 350     }
 351 
 352     public GraalCompilerTest() {
 353         this.backend = Graal.getRequiredCapability(RuntimeProvider.class).getHostBackend();
 354         this.providers = getBackend().getProviders();
 355     }
 356 
 357     /**
 358      * Set up a test for a non-default backend. The test should check (via {@link #getBackend()} )
 359      * whether the desired backend is available.
 360      *
 361      * @param arch the name of the desired backend architecture
 362      */
 363     public GraalCompilerTest(Class<? extends Architecture> arch) {
 364         RuntimeProvider runtime = Graal.getRequiredCapability(RuntimeProvider.class);
 365         Backend b = runtime.getBackend(arch);
 366         if (b != null) {
 367             this.backend = b;
 368         } else {
 369             // Fall back to the default/host backend
 370             this.backend = runtime.getHostBackend();
 371         }


 911                     ArrayStoreException.class,
 912                     ClassCastException.class,
 913                     NullPointerException.class);
 914 
 915     protected void assertEquals(Result expect, Result actual) {
 916         if (expect.exception != null) {
 917             Assert.assertTrue("expected " + expect.exception, actual.exception != null);
 918             Assert.assertEquals("Exception class", expect.exception.getClass(), actual.exception.getClass());
 919             // C2 can optimize out the stack trace and message in some cases
 920             if (expect.exception.getMessage() != null || !C2_OMIT_STACK_TRACE_IN_FAST_THROW_EXCEPTIONS.contains(expect.exception.getClass())) {
 921                 Assert.assertEquals("Exception message", expect.exception.getMessage(), actual.exception.getMessage());
 922             }
 923         } else {
 924             if (actual.exception != null) {
 925                 throw new AssertionError("expected " + expect.returnValue + " but got an exception", actual.exception);
 926             }
 927             assertDeepEquals(expect.returnValue, actual.returnValue);
 928         }
 929     }
 930 


 931     /**
 932      * Gets installed code for a given method, compiling it first if necessary. The graph is parsed
 933      * {@link #parseEager eagerly}.
 934      */
 935     protected final InstalledCode getCode(ResolvedJavaMethod method) {
 936         return getCode(method, null, false, false, getInitialOptions());
 937     }
 938 
 939     protected final InstalledCode getCode(ResolvedJavaMethod method, OptionValues options) {
 940         return getCode(method, null, false, false, options);
 941     }
 942 
 943     /**
 944      * Gets installed code for a given method, compiling it first if necessary.
 945      *
 946      * @param installedCodeOwner the method the compiled code will be associated with when installed
 947      * @param graph the graph to be compiled. If null, a graph will be obtained from
 948      *            {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}.
 949      */
 950     protected final InstalledCode getCode(ResolvedJavaMethod installedCodeOwner, StructuredGraph graph) {


 962      */
 963     protected final InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile) {
 964         return getCode(installedCodeOwner, graph, forceCompile, false, graph == null ? getInitialOptions() : graph.getOptions());
 965     }
 966 
 967     /**
 968      * Gets installed code for a given method and graph, compiling it first if necessary.
 969      *
 970      * @param installedCodeOwner the method the compiled code will be associated with when installed
 971      * @param graph the graph to be compiled. If null, a graph will be obtained from
 972      *            {@code installedCodeOwner} via {@link #parseForCompile(ResolvedJavaMethod)}.
 973      * @param forceCompile specifies whether to ignore any previous code cached for the (method,
 974      *            key) pair
 975      * @param installAsDefault specifies whether to install as the default implementation
 976      * @param options the options that will be used in {@link #parseForCompile(ResolvedJavaMethod)}
 977      */
 978     @SuppressWarnings("try")
 979     protected InstalledCode getCode(final ResolvedJavaMethod installedCodeOwner, StructuredGraph graph, boolean forceCompile, boolean installAsDefault, OptionValues options) {
 980         boolean useCache = !forceCompile && getArgumentToBind() == null;
 981         if (useCache && graph == null) {
 982             InstalledCode cached = cache.get().get(installedCodeOwner);
 983             if (cached != null) {
 984                 if (cached.isValid()) {
 985                     return cached;
 986                 }
 987             }
 988         }
 989         // loop for retrying compilation
 990         for (int retry = 0; retry <= BAILOUT_RETRY_LIMIT; retry++) {
 991             final CompilationIdentifier id = getOrCreateCompilationId(installedCodeOwner, graph);
 992 
 993             InstalledCode installedCode = null;
 994             StructuredGraph graphToCompile = graph == null ? parseForCompile(installedCodeOwner, id, options) : graph;
 995             DebugContext debug = graphToCompile.getDebug();
 996 
 997             try (AllocSpy spy = AllocSpy.open(installedCodeOwner); DebugContext.Scope ds = debug.scope("Compiling", graph)) {
 998                 CompilationPrinter printer = CompilationPrinter.begin(options, id, installedCodeOwner, INVOCATION_ENTRY_BCI);
 999                 CompilationResult compResult = compile(installedCodeOwner, graphToCompile, new CompilationResult(graphToCompile.compilationId()), id, options);
1000                 printer.finish(compResult);
1001 
1002                 try (DebugContext.Scope s = debug.scope("CodeInstall", getCodeCache(), installedCodeOwner, compResult);
1003                                 DebugContext.Activation a = debug.activate()) {
1004                     try {
1005                         if (installAsDefault) {
1006                             installedCode = addDefaultMethod(debug, installedCodeOwner, compResult);
1007                         } else {
1008                             installedCode = addMethod(debug, installedCodeOwner, compResult);
1009                         }
1010                         if (installedCode == null) {
1011                             throw new GraalError("Could not install code for " + installedCodeOwner.format("%H.%n(%p)"));
1012                         }
1013                     } catch (BailoutException e) {
1014                         if (retry < BAILOUT_RETRY_LIMIT && graph == null && !e.isPermanent()) {
1015                             // retry (if there is no predefined graph)
1016                             TTY.println(String.format("Restart compilation %s (%s) due to a non-permanent bailout!", installedCodeOwner, id));
1017                             continue;
1018                         }
1019                         throw e;
1020                     }
1021                 } catch (Throwable e) {
1022                     throw debug.handle(e);
1023                 }
1024             } catch (Throwable e) {
1025                 throw debug.handle(e);
1026             }
1027 
1028             if (useCache) {
1029                 cache.get().put(installedCodeOwner, installedCode);
1030             }
1031             return installedCode;
1032         }
1033         throw GraalError.shouldNotReachHere();
1034     }
1035 
1036     /**
1037      * Used to produce a graph for a method about to be compiled by
1038      * {@link #compile(ResolvedJavaMethod, StructuredGraph)} if the second parameter to that method
1039      * is null.
1040      *
1041      * The default implementation in {@link GraalCompilerTest} is to call {@link #parseEager}.
1042      */
1043     protected StructuredGraph parseForCompile(ResolvedJavaMethod method, OptionValues options) {
1044         return parseEager(method, AllowAssumptions.YES, getCompilationId(method), options);
1045     }
1046 
1047     protected final StructuredGraph parseForCompile(ResolvedJavaMethod method, DebugContext debug) {
1048         return parseEager(method, AllowAssumptions.YES, debug);
1049     }


1308         ResolvedJavaMethod javaMethod = builder.getMethod();
1309         builder.speculationLog(getSpeculationLog());
1310         if (builder.getCancellable() == null) {
1311             builder.cancellable(getCancellable(javaMethod));
1312         }
1313         assert javaMethod.getAnnotation(Test.class) == null : "shouldn't parse method with @Test annotation: " + javaMethod;
1314         StructuredGraph graph = builder.build();
1315         DebugContext debug = graph.getDebug();
1316         try (DebugContext.Scope ds = debug.scope("Parsing", javaMethod, graph)) {
1317             graphBuilderSuite.apply(graph, getDefaultHighTierContext());
1318             Object[] args = getArgumentToBind();
1319             if (args != null) {
1320                 bindArguments(graph, args);
1321             }
1322             return graph;
1323         } catch (Throwable e) {
1324             throw debug.handle(e);
1325         }
1326     }
1327 
1328     protected static final Object NO_BIND = new Object();
1329 
1330     protected void bindArguments(StructuredGraph graph, Object[] argsToBind) {
1331         ResolvedJavaMethod m = graph.method();
1332         Object receiver = isStatic(m.getModifiers()) ? null : this;
1333         Object[] args = argsWithReceiver(receiver, argsToBind);
1334         JavaType[] parameterTypes = m.toParameterTypes();
1335         assert parameterTypes.length == args.length;
1336         for (ParameterNode param : graph.getNodes(ParameterNode.TYPE)) {
1337             Object arg = args[param.index()];
1338             if (arg != NO_BIND) {
1339                 JavaConstant c = getSnippetReflection().forBoxed(parameterTypes[param.index()].getJavaKind(), arg);
1340                 ConstantNode replacement = ConstantNode.forConstant(c, getMetaAccess(), graph);
1341                 param.replaceAtUsages(replacement);
1342             }
1343         }
1344     }
1345 
1346     protected Object[] getArgumentToBind() {
1347         return null;
1348     }
1349 
1350     protected PhaseSuite<HighTierContext> getEagerGraphBuilderSuite() {
1351         return getCustomGraphBuilderSuite(GraphBuilderConfiguration.getDefault(getDefaultGraphBuilderPlugins()).withEagerResolving(true).withUnresolvedIsError(true));
1352     }
1353 
1354     /**
1355      * Gets the cancellable that should be associated with a graph being created by any of the
1356      * {@code parse...()} methods.
1357      *
1358      * @param method the method being parsed into a graph
1359      */
1360     protected Cancellable getCancellable(ResolvedJavaMethod method) {
1361         return null;
1362     }


< prev index next >