src/jdk.internal.vm.compiler/share/classes/org.graalvm.compiler.core.test/src/org/graalvm/compiler/core/test/CheckGraalInvariants.java
branchdatagramsocketimpl-branch
changeset 58678 9cf78a70fa4f
parent 54328 37648a9c4a6a
child 58679 9c3209ff7550
equal deleted inserted replaced
58677:13588c901957 58678:9cf78a70fa4f
    64 import org.graalvm.compiler.nodes.StructuredGraph;
    64 import org.graalvm.compiler.nodes.StructuredGraph;
    65 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
    65 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
    66 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
    66 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
    67 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
    67 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
    68 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
    68 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
       
    69 import org.graalvm.compiler.nodes.spi.CoreProviders;
    69 import org.graalvm.compiler.options.OptionValues;
    70 import org.graalvm.compiler.options.OptionValues;
    70 import org.graalvm.compiler.phases.OptimisticOptimizations;
    71 import org.graalvm.compiler.phases.OptimisticOptimizations;
    71 import org.graalvm.compiler.phases.PhaseSuite;
    72 import org.graalvm.compiler.phases.PhaseSuite;
    72 import org.graalvm.compiler.phases.VerifyPhase;
    73 import org.graalvm.compiler.phases.VerifyPhase;
    73 import org.graalvm.compiler.phases.VerifyPhase.VerificationError;
    74 import org.graalvm.compiler.phases.VerifyPhase.VerificationError;
    74 import org.graalvm.compiler.phases.contract.VerifyNodeCosts;
    75 import org.graalvm.compiler.phases.contract.VerifyNodeCosts;
    75 import org.graalvm.compiler.phases.tiers.HighTierContext;
    76 import org.graalvm.compiler.phases.tiers.HighTierContext;
    76 import org.graalvm.compiler.phases.tiers.PhaseContext;
       
    77 import org.graalvm.compiler.phases.util.Providers;
    77 import org.graalvm.compiler.phases.util.Providers;
    78 import org.graalvm.compiler.runtime.RuntimeProvider;
    78 import org.graalvm.compiler.runtime.RuntimeProvider;
       
    79 import org.graalvm.compiler.serviceprovider.JavaVersionUtil;
       
    80 import org.graalvm.compiler.test.AddExports;
       
    81 import org.graalvm.compiler.test.ModuleSupport;
    79 import jdk.internal.vm.compiler.word.LocationIdentity;
    82 import jdk.internal.vm.compiler.word.LocationIdentity;
    80 import org.junit.Assert;
    83 import org.junit.Assert;
    81 import org.junit.Assume;
    84 import org.junit.Assume;
    82 import org.junit.Test;
    85 import org.junit.Test;
    83 
    86 
    95 /**
    98 /**
    96  * Checks that all classes in *graal*.jar and *jvmci*.jar entries on the boot class path comply with
    99  * Checks that all classes in *graal*.jar and *jvmci*.jar entries on the boot class path comply with
    97  * global invariants such as using {@link Object#equals(Object)} to compare certain types instead of
   100  * global invariants such as using {@link Object#equals(Object)} to compare certain types instead of
    98  * identity comparisons.
   101  * identity comparisons.
    99  */
   102  */
       
   103 @AddExports("jdk.internal.vm.ci/*=jdk.aot")
   100 public class CheckGraalInvariants extends GraalCompilerTest {
   104 public class CheckGraalInvariants extends GraalCompilerTest {
       
   105 
       
   106     /**
       
   107      * Magic token to denote the classes in the Java runtime image (i.e. in the {@code jrt:/} file
       
   108      * system).
       
   109      */
       
   110     public static final String JRT_CLASS_PATH_ENTRY = "<jrt>";
   101 
   111 
   102     private static boolean shouldVerifyEquals(ResolvedJavaMethod m) {
   112     private static boolean shouldVerifyEquals(ResolvedJavaMethod m) {
   103         if (m.getName().equals("identityEquals")) {
   113         if (m.getName().equals("identityEquals")) {
   104             ResolvedJavaType c = m.getDeclaringClass();
   114             ResolvedJavaType c = m.getDeclaringClass();
   105             if (c.getName().equals("Ljdk/vm/ci/meta/AbstractValue;") || c.getName().equals("jdk/vm/ci/meta/Value")) {
   115             if (c.getName().equals("Ljdk/vm/ci/meta/AbstractValue;") || c.getName().equals("jdk/vm/ci/meta/Value")) {
   116     }
   126     }
   117 
   127 
   118     public static class InvariantsTool {
   128     public static class InvariantsTool {
   119 
   129 
   120         protected boolean shouldProcess(String classpathEntry) {
   130         protected boolean shouldProcess(String classpathEntry) {
       
   131             if (classpathEntry.equals(JRT_CLASS_PATH_ENTRY)) {
       
   132                 return true;
       
   133             }
   121             if (classpathEntry.endsWith(".jar")) {
   134             if (classpathEntry.endsWith(".jar")) {
   122                 String name = new File(classpathEntry).getName();
   135                 String name = new File(classpathEntry).getName();
   123                 return name.contains("jvmci") || name.contains("graal") || name.contains("jdk.internal.vm.compiler");
   136                 return name.contains("jvmci") || name.contains("graal") || name.contains("jdk.internal.vm.compiler");
   124             }
   137             }
   125             return false;
   138             return false;
   126         }
   139         }
   127 
   140 
   128         protected String getClassPath() {
   141         protected String getClassPath() {
   129             String bootclasspath;
   142             String bootclasspath;
   130             if (Java8OrEarlier) {
   143             if (JavaVersionUtil.JAVA_SPEC <= 8) {
   131                 bootclasspath = System.getProperty("sun.boot.class.path");
   144                 bootclasspath = System.getProperty("sun.boot.class.path");
   132             } else {
   145             } else {
   133                 bootclasspath = System.getProperty("jdk.module.path") + File.pathSeparatorChar + System.getProperty("jdk.module.upgrade.path");
   146                 bootclasspath = JRT_CLASS_PATH_ENTRY;
   134             }
   147             }
   135             return bootclasspath;
   148             return bootclasspath;
   136         }
   149         }
   137 
   150 
   138         protected boolean shouldLoadClass(String className) {
   151         protected boolean shouldLoadClass(String className) {
   139             if (className.equals("module-info") || className.startsWith("META-INF.versions.")) {
   152             if (className.equals("module-info") || className.startsWith("META-INF.versions.")) {
   140                 return false;
   153                 return false;
   141             }
   154             }
   142             if (!Java8OrEarlier) {
   155             if (JavaVersionUtil.JAVA_SPEC > 8) {
   143                 // @formatter:off
   156                 // @formatter:off
   144                 /*
   157                 /*
   145                  * Work around to prevent:
   158                  * Work around to prevent:
   146                  *
   159                  *
   147                  * org.graalvm.compiler.debug.GraalError: java.lang.IllegalAccessError: class org.graalvm.compiler.serviceprovider.GraalServices$Lazy (in module
   160                  * org.graalvm.compiler.debug.GraalError: java.lang.IllegalAccessError: class org.graalvm.compiler.serviceprovider.GraalServices$Lazy (in module
   205 
   218 
   206         final List<String> classNames = new ArrayList<>();
   219         final List<String> classNames = new ArrayList<>();
   207         for (String path : bootclasspath.split(File.pathSeparator)) {
   220         for (String path : bootclasspath.split(File.pathSeparator)) {
   208             if (tool.shouldProcess(path)) {
   221             if (tool.shouldProcess(path)) {
   209                 try {
   222                 try {
   210                     final ZipFile zipFile = new ZipFile(new File(path));
   223                     if (path.equals(JRT_CLASS_PATH_ENTRY)) {
   211                     for (final Enumeration<? extends ZipEntry> entry = zipFile.entries(); entry.hasMoreElements();) {
   224                         for (String className : ModuleSupport.getJRTGraalClassNames()) {
   212                         final ZipEntry zipEntry = entry.nextElement();
       
   213                         String name = zipEntry.getName();
       
   214                         if (name.endsWith(".class") && !name.startsWith("META-INF/versions/")) {
       
   215                             String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
       
   216                             if (isInNativeImage(className)) {
       
   217                                 /*
       
   218                                  * Native Image is an external tool and does not need to follow the
       
   219                                  * Graal invariants.
       
   220                                  */
       
   221                                 continue;
       
   222                             }
       
   223                             if (isGSON(className)) {
   225                             if (isGSON(className)) {
   224                                 /*
   226                                 /*
   225                                  * GSON classes are compiled with old JDK
   227                                  * GSON classes are compiled with old JDK
   226                                  */
   228                                  */
   227                                 continue;
   229                                 continue;
   228                             }
   230                             }
   229                             classNames.add(className);
   231                             classNames.add(className);
   230                         }
   232                         }
       
   233                     } else {
       
   234                         final ZipFile zipFile = new ZipFile(new File(path));
       
   235                         for (final Enumeration<? extends ZipEntry> entry = zipFile.entries(); entry.hasMoreElements();) {
       
   236                             final ZipEntry zipEntry = entry.nextElement();
       
   237                             String name = zipEntry.getName();
       
   238                             if (name.endsWith(".class") && !name.startsWith("META-INF/versions/")) {
       
   239                                 String className = name.substring(0, name.length() - ".class".length()).replace('/', '.');
       
   240                                 if (isInNativeImage(className)) {
       
   241                                     /*
       
   242                                      * Native Image is an external tool and does not need to follow
       
   243                                      * the Graal invariants.
       
   244                                      */
       
   245                                     continue;
       
   246                                 }
       
   247                                 if (isGSON(className)) {
       
   248                                     /*
       
   249                                      * GSON classes are compiled with old JDK
       
   250                                      */
       
   251                                     continue;
       
   252                                 }
       
   253                                 classNames.add(className);
       
   254                             }
       
   255                         }
   231                     }
   256                     }
   232                 } catch (IOException ex) {
   257                 } catch (IOException ex) {
   233                     Assert.fail(ex.toString());
   258                     Assert.fail(ex.toString());
   234                 }
   259                 }
   235             }
   260             }
   245         int availableProcessors = Runtime.getRuntime().availableProcessors();
   270         int availableProcessors = Runtime.getRuntime().availableProcessors();
   246         ThreadPoolExecutor executor = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), factory);
   271         ThreadPoolExecutor executor = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), factory);
   247 
   272 
   248         List<String> errors = Collections.synchronizedList(new ArrayList<>());
   273         List<String> errors = Collections.synchronizedList(new ArrayList<>());
   249 
   274 
   250         List<VerifyPhase<PhaseContext>> verifiers = new ArrayList<>();
   275         List<VerifyPhase<CoreProviders>> verifiers = new ArrayList<>();
   251 
   276 
   252         // If you add a new type to test here, be sure to add appropriate
   277         // If you add a new type to test here, be sure to add appropriate
   253         // methods to the BadUsageWithEquals class below
   278         // methods to the BadUsageWithEquals class below
   254         verifiers.add(new VerifyUsageWithEquals(Value.class));
   279         verifiers.add(new VerifyUsageWithEquals(Value.class));
   255         verifiers.add(new VerifyUsageWithEquals(Register.class));
   280         verifiers.add(new VerifyUsageWithEquals(Register.class));
   268         verifiers.add(new VerifyUpdateUsages());
   293         verifiers.add(new VerifyUpdateUsages());
   269         verifiers.add(new VerifyBailoutUsage());
   294         verifiers.add(new VerifyBailoutUsage());
   270         verifiers.add(new VerifySystemPropertyUsage());
   295         verifiers.add(new VerifySystemPropertyUsage());
   271         verifiers.add(new VerifyInstanceOfUsage());
   296         verifiers.add(new VerifyInstanceOfUsage());
   272         verifiers.add(new VerifyGraphAddUsage());
   297         verifiers.add(new VerifyGraphAddUsage());
       
   298         verifiers.add(new VerifyBufferUsage());
   273         verifiers.add(new VerifyGetOptionsUsage());
   299         verifiers.add(new VerifyGetOptionsUsage());
   274         verifiers.add(new VerifyUnsafeAccess());
   300         verifiers.add(new VerifyUnsafeAccess());
   275 
   301 
   276         VerifyFoldableMethods foldableMethodsVerifier = new VerifyFoldableMethods();
   302         VerifyFoldableMethods foldableMethodsVerifier = new VerifyFoldableMethods();
   277         if (tool.shouldVerifyFoldableMethods()) {
   303         if (tool.shouldVerifyFoldableMethods()) {
   310                     }
   336                     }
   311                 });
   337                 });
   312 
   338 
   313                 ResolvedJavaType type = metaAccess.lookupJavaType(c);
   339                 ResolvedJavaType type = metaAccess.lookupJavaType(c);
   314                 List<ResolvedJavaMethod> methods = new ArrayList<>();
   340                 List<ResolvedJavaMethod> methods = new ArrayList<>();
   315                 methods.addAll(Arrays.asList(type.getDeclaredMethods()));
   341                 try {
   316                 methods.addAll(Arrays.asList(type.getDeclaredConstructors()));
   342                     methods.addAll(Arrays.asList(type.getDeclaredMethods()));
       
   343                     methods.addAll(Arrays.asList(type.getDeclaredConstructors()));
       
   344                 } catch (Throwable e) {
       
   345                     errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e)));
       
   346                 }
   317                 ResolvedJavaMethod clinit = type.getClassInitializer();
   347                 ResolvedJavaMethod clinit = type.getClassInitializer();
   318                 if (clinit != null) {
   348                 if (clinit != null) {
   319                     methods.add(clinit);
   349                     methods.add(clinit);
   320                 }
   350                 }
   321 
   351 
   400                 continue;
   430                 continue;
   401             }
   431             }
   402             try {
   432             try {
   403                 Class<?> c = Class.forName(className, true, CheckGraalInvariants.class.getClassLoader());
   433                 Class<?> c = Class.forName(className, true, CheckGraalInvariants.class.getClassLoader());
   404                 classes.add(c);
   434                 classes.add(c);
       
   435             } catch (UnsupportedClassVersionError e) {
       
   436                 // graal-test.jar can contain classes compiled for different Java versions
       
   437             } catch (NoClassDefFoundError e) {
       
   438                 if (!e.getMessage().contains("Could not initialize class")) {
       
   439                     throw e;
       
   440                 } else {
       
   441                     // A second or later attempt to initialize a class
       
   442                     // results in this confusing error where the
       
   443                     // original cause of initialization failure is lost
       
   444                 }
   405             } catch (Throwable t) {
   445             } catch (Throwable t) {
   406                 tool.handleClassLoadingException(t);
   446                 tool.handleClassLoadingException(t);
   407             }
   447             }
   408         }
   448         }
   409         return classes;
   449         return classes;
   411 
   451 
   412     /**
   452     /**
   413      * @param metaAccess
   453      * @param metaAccess
   414      * @param verifiers
   454      * @param verifiers
   415      */
   455      */
   416     private static void checkClass(Class<?> c, MetaAccessProvider metaAccess, List<VerifyPhase<PhaseContext>> verifiers) {
   456     private static void checkClass(Class<?> c, MetaAccessProvider metaAccess, List<VerifyPhase<CoreProviders>> verifiers) {
   417         if (Node.class.isAssignableFrom(c)) {
   457         if (Node.class.isAssignableFrom(c)) {
   418             if (c.getAnnotation(NodeInfo.class) == null) {
   458             if (c.getAnnotation(NodeInfo.class) == null) {
   419                 throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName()));
   459                 throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName()));
   420             }
   460             }
   421             VerifyNodeCosts.verifyNodeClass(c);
   461             VerifyNodeCosts.verifyNodeClass(c);
   422         }
   462         }
   423         for (VerifyPhase<PhaseContext> verifier : verifiers) {
   463         for (VerifyPhase<CoreProviders> verifier : verifiers) {
   424             verifier.verifyClass(c, metaAccess);
   464             verifier.verifyClass(c, metaAccess);
   425         }
   465         }
   426     }
   466     }
   427 
   467 
   428     private static void checkMethod(ResolvedJavaMethod method) {
   468     private static void checkMethod(ResolvedJavaMethod method) {
   443     }
   483     }
   444 
   484 
   445     /**
   485     /**
   446      * Checks the invariants for a single graph.
   486      * Checks the invariants for a single graph.
   447      */
   487      */
   448     private static void checkGraph(List<VerifyPhase<PhaseContext>> verifiers, HighTierContext context, StructuredGraph graph) {
   488     private static void checkGraph(List<VerifyPhase<CoreProviders>> verifiers, HighTierContext context, StructuredGraph graph) {
   449         for (VerifyPhase<PhaseContext> verifier : verifiers) {
   489         for (VerifyPhase<CoreProviders> verifier : verifiers) {
   450             if (!(verifier instanceof VerifyUsageWithEquals) || shouldVerifyEquals(graph.method())) {
   490             if (!(verifier instanceof VerifyUsageWithEquals) || shouldVerifyEquals(graph.method())) {
   451                 verifier.apply(graph, context);
   491                 verifier.apply(graph, context);
   452             } else {
   492             } else {
   453                 verifier.apply(graph, context);
   493                 verifier.apply(graph, context);
   454             }
   494             }