1 /*
   2  * Copyright (c) 2014, 2019, Oracle and/or its affiliates. All rights reserved.
   3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
   4  *
   5  * This code is free software; you can redistribute it and/or modify it
   6  * under the terms of the GNU General Public License version 2 only, as
   7  * published by the Free Software Foundation.
   8  *
   9  * This code is distributed in the hope that it will be useful, but WITHOUT
  10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
  12  * version 2 for more details (a copy is included in the LICENSE file that
  13  * accompanied this code).
  14  *
  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 
  24 
  25 package org.graalvm.compiler.core.test;
  26 
  27 import java.io.File;
  28 import java.io.IOException;
  29 import java.io.PrintWriter;
  30 import java.io.StringWriter;
  31 import java.lang.annotation.Annotation;
  32 import java.lang.reflect.Method;
  33 import java.lang.reflect.Modifier;
  34 import java.util.ArrayList;
  35 import java.util.Arrays;
  36 import java.util.Collections;
  37 import java.util.Enumeration;
  38 import java.util.List;
  39 import java.util.concurrent.LinkedBlockingQueue;
  40 import java.util.concurrent.ThreadPoolExecutor;
  41 import java.util.concurrent.TimeUnit;
  42 import java.util.zip.ZipEntry;
  43 import java.util.zip.ZipFile;
  44 
  45 import org.graalvm.compiler.api.replacements.MethodSubstitution;
  46 import org.graalvm.compiler.api.replacements.Snippet;
  47 import org.graalvm.compiler.api.replacements.Snippet.ConstantParameter;
  48 import org.graalvm.compiler.api.replacements.Snippet.NonNullParameter;
  49 import org.graalvm.compiler.api.replacements.Snippet.VarargsParameter;
  50 import org.graalvm.compiler.api.test.Graal;
  51 import org.graalvm.compiler.bytecode.BridgeMethodUtils;
  52 import org.graalvm.compiler.core.CompilerThreadFactory;
  53 import org.graalvm.compiler.core.common.LIRKind;
  54 import org.graalvm.compiler.core.common.type.ArithmeticOpTable;
  55 import org.graalvm.compiler.debug.DebugCloseable;
  56 import org.graalvm.compiler.debug.DebugContext;
  57 import org.graalvm.compiler.debug.DebugHandlersFactory;
  58 import org.graalvm.compiler.debug.GraalError;
  59 import org.graalvm.compiler.graph.Node;
  60 import org.graalvm.compiler.graph.NodeClass;
  61 import org.graalvm.compiler.java.GraphBuilderPhase;
  62 import org.graalvm.compiler.nodeinfo.NodeInfo;
  63 import org.graalvm.compiler.nodes.PhiNode;
  64 import org.graalvm.compiler.nodes.StructuredGraph;
  65 import org.graalvm.compiler.nodes.StructuredGraph.AllowAssumptions;
  66 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration;
  67 import org.graalvm.compiler.nodes.graphbuilderconf.GraphBuilderConfiguration.Plugins;
  68 import org.graalvm.compiler.nodes.graphbuilderconf.InvocationPlugins;
  69 import org.graalvm.compiler.nodes.spi.CoreProviders;
  70 import org.graalvm.compiler.options.OptionValues;
  71 import org.graalvm.compiler.phases.OptimisticOptimizations;
  72 import org.graalvm.compiler.phases.PhaseSuite;
  73 import org.graalvm.compiler.phases.VerifyPhase;
  74 import org.graalvm.compiler.phases.VerifyPhase.VerificationError;
  75 import org.graalvm.compiler.phases.contract.VerifyNodeCosts;
  76 import org.graalvm.compiler.phases.tiers.HighTierContext;
  77 import org.graalvm.compiler.phases.util.Providers;
  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;
  82 import jdk.internal.vm.compiler.word.LocationIdentity;
  83 import org.junit.Assert;
  84 import org.junit.Assume;
  85 import org.junit.Test;
  86 
  87 import jdk.vm.ci.code.BailoutException;
  88 import jdk.vm.ci.code.Register;
  89 import jdk.vm.ci.code.Register.RegisterCategory;
  90 import jdk.vm.ci.meta.JavaField;
  91 import jdk.vm.ci.meta.JavaMethod;
  92 import jdk.vm.ci.meta.JavaType;
  93 import jdk.vm.ci.meta.MetaAccessProvider;
  94 import jdk.vm.ci.meta.ResolvedJavaMethod;
  95 import jdk.vm.ci.meta.ResolvedJavaType;
  96 import jdk.vm.ci.meta.Value;
  97 
  98 /**
  99  * Checks that all classes in *graal*.jar and *jvmci*.jar entries on the boot class path comply with
 100  * global invariants such as using {@link Object#equals(Object)} to compare certain types instead of
 101  * identity comparisons.
 102  */
 103 @AddExports("jdk.internal.vm.ci/*=jdk.aot")
 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>";
 111 
 112     private static boolean shouldVerifyEquals(ResolvedJavaMethod m) {
 113         if (m.getName().equals("identityEquals")) {
 114             ResolvedJavaType c = m.getDeclaringClass();
 115             if (c.getName().equals("Ljdk/vm/ci/meta/AbstractValue;") || c.getName().equals("jdk/vm/ci/meta/Value")) {
 116                 return false;
 117             }
 118         }
 119 
 120         return true;
 121     }
 122 
 123     public static String relativeFileName(String absolutePath) {
 124         int lastFileSeparatorIndex = absolutePath.lastIndexOf(File.separator);
 125         return absolutePath.substring(lastFileSeparatorIndex >= 0 ? lastFileSeparatorIndex : 0);
 126     }
 127 
 128     public static class InvariantsTool {
 129 
 130         protected boolean shouldProcess(String classpathEntry) {
 131             if (classpathEntry.equals(JRT_CLASS_PATH_ENTRY)) {
 132                 return true;
 133             }
 134             if (classpathEntry.endsWith(".jar")) {
 135                 String name = new File(classpathEntry).getName();
 136                 return name.contains("jvmci") || name.contains("graal") || name.contains("jdk.internal.vm.compiler");
 137             }
 138             return false;
 139         }
 140 
 141         protected String getClassPath() {
 142             String bootclasspath;
 143             if (JavaVersionUtil.JAVA_SPEC <= 8) {
 144                 bootclasspath = System.getProperty("sun.boot.class.path");
 145             } else {
 146                 bootclasspath = JRT_CLASS_PATH_ENTRY;
 147             }
 148             return bootclasspath;
 149         }
 150 
 151         protected boolean shouldLoadClass(String className) {
 152             if (className.equals("module-info") || className.startsWith("META-INF.versions.")) {
 153                 return false;
 154             }
 155             if (JavaVersionUtil.JAVA_SPEC > 8) {
 156                 // @formatter:off
 157                 /*
 158                  * Work around to prevent:
 159                  *
 160                  * org.graalvm.compiler.debug.GraalError: java.lang.IllegalAccessError: class org.graalvm.compiler.serviceprovider.GraalServices$Lazy (in module
 161                  * jdk.internal.vm.compiler) cannot access class java.lang.management.ManagementFactory (in module java.management) because module
 162                  * jdk.internal.vm.compiler does not read module java.management
 163                  *     at jdk.internal.vm.compiler/org.graalvm.compiler.debug.GraalError.shouldNotReachHere(GraalError.java:55)
 164                  *     at org.graalvm.compiler.core.test.CheckGraalInvariants$InvariantsTool.handleClassLoadingException(CheckGraalInvariants.java:149)
 165                  *     at org.graalvm.compiler.core.test.CheckGraalInvariants.initializeClasses(CheckGraalInvariants.java:321)
 166                  *     at org.graalvm.compiler.core.test.CheckGraalInvariants.runTest(CheckGraalInvariants.java:239)
 167                  *
 168                  * which occurs because JDK8 overlays are in modular jars. They are never used normally.
 169                  */
 170                 // @formatter:on
 171                 if (className.equals("org.graalvm.compiler.serviceprovider.GraalServices$Lazy")) {
 172                     return false;
 173                 }
 174             } else {
 175                 if (className.equals("jdk.vm.ci.services.JVMCIClassLoaderFactory")) {
 176                     return false;
 177                 }
 178             }
 179             return true;
 180         }
 181 
 182         protected void handleClassLoadingException(Throwable t) {
 183             GraalError.shouldNotReachHere(t);
 184         }
 185 
 186         protected void handleParsingException(Throwable t) {
 187             GraalError.shouldNotReachHere(t);
 188         }
 189 
 190         public boolean shouldVerifyFoldableMethods() {
 191             return true;
 192         }
 193     }
 194 
 195     @Test
 196     @SuppressWarnings("try")
 197     public void test() {
 198         assumeManagementLibraryIsLoadable();
 199         runTest(new InvariantsTool());
 200     }
 201 
 202     @SuppressWarnings("try")
 203     public static void runTest(InvariantsTool tool) {
 204         RuntimeProvider rt = Graal.getRequiredCapability(RuntimeProvider.class);
 205         Providers providers = rt.getHostBackend().getProviders();
 206         MetaAccessProvider metaAccess = providers.getMetaAccess();
 207 
 208         PhaseSuite<HighTierContext> graphBuilderSuite = new PhaseSuite<>();
 209         Plugins plugins = new Plugins(new InvocationPlugins());
 210         GraphBuilderConfiguration config = GraphBuilderConfiguration.getDefault(plugins).withEagerResolving(true).withUnresolvedIsError(true);
 211         graphBuilderSuite.appendPhase(new GraphBuilderPhase(config));
 212         HighTierContext context = new HighTierContext(providers, graphBuilderSuite, OptimisticOptimizations.NONE);
 213 
 214         Assume.assumeTrue(VerifyPhase.class.desiredAssertionStatus());
 215 
 216         String bootclasspath = tool.getClassPath();
 217         Assert.assertNotNull("Cannot find boot class path", bootclasspath);
 218 
 219         final List<String> classNames = new ArrayList<>();
 220         for (String path : bootclasspath.split(File.pathSeparator)) {
 221             if (tool.shouldProcess(path)) {
 222                 try {
 223                     if (path.equals(JRT_CLASS_PATH_ENTRY)) {
 224                         for (String className : ModuleSupport.getJRTGraalClassNames()) {
 225                             if (isGSON(className)) {
 226                                 /*
 227                                  * GSON classes are compiled with old JDK
 228                                  */
 229                                 continue;
 230                             }
 231                             classNames.add(className);
 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                         }
 256                     }
 257                 } catch (IOException ex) {
 258                     Assert.fail(ex.toString());
 259                 }
 260             }
 261         }
 262         Assert.assertFalse("Could not find graal jars on boot class path: " + bootclasspath, classNames.isEmpty());
 263 
 264         // Allows a subset of methods to be checked through use of a system property
 265         String property = System.getProperty(CheckGraalInvariants.class.getName() + ".filters");
 266         String[] filters = property == null ? null : property.split(",");
 267 
 268         OptionValues options = getInitialOptions();
 269         CompilerThreadFactory factory = new CompilerThreadFactory("CheckInvariantsThread");
 270         int availableProcessors = Runtime.getRuntime().availableProcessors();
 271         ThreadPoolExecutor executor = new ThreadPoolExecutor(availableProcessors, availableProcessors, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>(), factory);
 272 
 273         List<String> errors = Collections.synchronizedList(new ArrayList<>());
 274 
 275         List<VerifyPhase<CoreProviders>> verifiers = new ArrayList<>();
 276 
 277         // If you add a new type to test here, be sure to add appropriate
 278         // methods to the BadUsageWithEquals class below
 279         verifiers.add(new VerifyUsageWithEquals(Value.class));
 280         verifiers.add(new VerifyUsageWithEquals(Register.class));
 281         verifiers.add(new VerifyUsageWithEquals(RegisterCategory.class));
 282         verifiers.add(new VerifyUsageWithEquals(JavaType.class));
 283         verifiers.add(new VerifyUsageWithEquals(JavaMethod.class));
 284         verifiers.add(new VerifyUsageWithEquals(JavaField.class));
 285         verifiers.add(new VerifyUsageWithEquals(LocationIdentity.class));
 286         verifiers.add(new VerifyUsageWithEquals(LIRKind.class));
 287         verifiers.add(new VerifyUsageWithEquals(ArithmeticOpTable.class));
 288         verifiers.add(new VerifyUsageWithEquals(ArithmeticOpTable.Op.class));
 289 
 290         verifiers.add(new VerifyDebugUsage());
 291         verifiers.add(new VerifyCallerSensitiveMethods());
 292         verifiers.add(new VerifyVirtualizableUsage());
 293         verifiers.add(new VerifyUpdateUsages());
 294         verifiers.add(new VerifyBailoutUsage());
 295         verifiers.add(new VerifySystemPropertyUsage());
 296         verifiers.add(new VerifyInstanceOfUsage());
 297         verifiers.add(new VerifyGraphAddUsage());
 298         verifiers.add(new VerifyBufferUsage());
 299         verifiers.add(new VerifyGetOptionsUsage());
 300         verifiers.add(new VerifyUnsafeAccess());
 301 
 302         VerifyFoldableMethods foldableMethodsVerifier = new VerifyFoldableMethods();
 303         if (tool.shouldVerifyFoldableMethods()) {
 304             verifiers.add(foldableMethodsVerifier);
 305         }
 306 
 307         for (Method m : BadUsageWithEquals.class.getDeclaredMethods()) {
 308             ResolvedJavaMethod method = metaAccess.lookupJavaMethod(m);
 309             try (DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER)) {
 310                 StructuredGraph graph = new StructuredGraph.Builder(options, debug, AllowAssumptions.YES).method(method).build();
 311                 try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) {
 312                     graphBuilderSuite.apply(graph, context);
 313                     // update phi stamps
 314                     graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp);
 315                     checkGraph(verifiers, context, graph);
 316                     errors.add(String.format("Expected error while checking %s", m));
 317                 } catch (VerificationError e) {
 318                     // expected!
 319                 } catch (Throwable e) {
 320                     errors.add(String.format("Error while checking %s:%n%s", m, printStackTraceToString(e)));
 321                 }
 322             }
 323         }
 324         if (errors.isEmpty()) {
 325             // Order outer classes before the inner classes
 326             classNames.sort((String a, String b) -> a.compareTo(b));
 327             // Initialize classes in single thread to avoid deadlocking issues during initialization
 328             List<Class<?>> classes = initializeClasses(tool, classNames);
 329             for (Class<?> c : classes) {
 330                 String className = c.getName();
 331                 executor.execute(() -> {
 332                     try {
 333                         checkClass(c, metaAccess, verifiers);
 334                     } catch (Throwable e) {
 335                         errors.add(String.format("Error while checking %s:%n%s", className, printStackTraceToString(e)));
 336                     }
 337                 });
 338 
 339                 ResolvedJavaType type = metaAccess.lookupJavaType(c);
 340                 List<ResolvedJavaMethod> methods = new ArrayList<>();
 341                 try {
 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                 }
 347                 ResolvedJavaMethod clinit = type.getClassInitializer();
 348                 if (clinit != null) {
 349                     methods.add(clinit);
 350                 }
 351 
 352                 for (ResolvedJavaMethod method : methods) {
 353                     if (Modifier.isNative(method.getModifiers()) || Modifier.isAbstract(method.getModifiers())) {
 354                         // ignore
 355                     } else {
 356                         String methodName = className + "." + method.getName();
 357                         if (matches(filters, methodName)) {
 358                             executor.execute(() -> {
 359                                 try (DebugContext debug = DebugContext.create(options, DebugHandlersFactory.LOADER)) {
 360                                     boolean isSubstitution = method.getAnnotation(Snippet.class) != null || method.getAnnotation(MethodSubstitution.class) != null;
 361                                     StructuredGraph graph = new StructuredGraph.Builder(options, debug).method(method).setIsSubstitution(isSubstitution).build();
 362                                     try (DebugCloseable s = debug.disableIntercept(); DebugContext.Scope ds = debug.scope("CheckingGraph", graph, method)) {
 363                                         checkMethod(method);
 364                                         graphBuilderSuite.apply(graph, context);
 365                                         // update phi stamps
 366                                         graph.getNodes().filter(PhiNode.class).forEach(PhiNode::inferStamp);
 367                                         checkGraph(verifiers, context, graph);
 368                                     } catch (VerificationError e) {
 369                                         errors.add(e.getMessage());
 370                                     } catch (LinkageError e) {
 371                                         // suppress linkages errors resulting from eager resolution
 372                                     } catch (BailoutException e) {
 373                                         // Graal bail outs on certain patterns in Java bytecode
 374                                         // (e.g.,
 375                                         // unbalanced monitors introduced by jacoco).
 376                                     } catch (Throwable e) {
 377                                         try {
 378                                             tool.handleParsingException(e);
 379                                         } catch (Throwable t) {
 380                                             errors.add(String.format("Error while checking %s:%n%s", methodName, printStackTraceToString(e)));
 381                                         }
 382                                     }
 383                                 }
 384                             });
 385                         }
 386                     }
 387                 }
 388             }
 389 
 390             executor.shutdown();
 391             try {
 392                 executor.awaitTermination(1, TimeUnit.HOURS);
 393             } catch (InterruptedException e1) {
 394                 throw new RuntimeException(e1);
 395             }
 396 
 397             if (tool.shouldVerifyFoldableMethods()) {
 398                 try {
 399                     foldableMethodsVerifier.finish();
 400                 } catch (Throwable e) {
 401                     errors.add(e.getMessage());
 402                 }
 403             }
 404         }
 405         if (!errors.isEmpty()) {
 406             StringBuilder msg = new StringBuilder();
 407             String nl = String.format("%n");
 408             for (String e : errors) {
 409                 if (msg.length() != 0) {
 410                     msg.append(nl);
 411                 }
 412                 msg.append(e);
 413             }
 414             Assert.fail(msg.toString());
 415         }
 416     }
 417 
 418     private static boolean isInNativeImage(String className) {
 419         return className.startsWith("org.graalvm.nativeimage");
 420     }
 421 
 422     private static boolean isGSON(String className) {
 423         return className.contains("com.google.gson");
 424     }
 425 
 426     private static List<Class<?>> initializeClasses(InvariantsTool tool, List<String> classNames) {
 427         List<Class<?>> classes = new ArrayList<>(classNames.size());
 428         for (String className : classNames) {
 429             if (!tool.shouldLoadClass(className)) {
 430                 continue;
 431             }
 432             try {
 433                 Class<?> c = Class.forName(className, true, CheckGraalInvariants.class.getClassLoader());
 434                 classes.add(c);
 435             } catch (Throwable t) {
 436                 tool.handleClassLoadingException(t);
 437             }
 438         }
 439         return classes;
 440     }
 441 
 442     /**
 443      * @param metaAccess
 444      * @param verifiers
 445      */
 446     private static void checkClass(Class<?> c, MetaAccessProvider metaAccess, List<VerifyPhase<CoreProviders>> verifiers) {
 447         if (Node.class.isAssignableFrom(c)) {
 448             if (c.getAnnotation(NodeInfo.class) == null) {
 449                 throw new AssertionError(String.format("Node subclass %s requires %s annotation", c.getName(), NodeClass.class.getSimpleName()));
 450             }
 451             VerifyNodeCosts.verifyNodeClass(c);
 452         }
 453         for (VerifyPhase<CoreProviders> verifier : verifiers) {
 454             verifier.verifyClass(c, metaAccess);
 455         }
 456     }
 457 
 458     private static void checkMethod(ResolvedJavaMethod method) {
 459         if (method.getAnnotation(Snippet.class) == null) {
 460             Annotation[][] parameterAnnotations = method.getParameterAnnotations();
 461             for (int i = 0; i < parameterAnnotations.length; i++) {
 462                 for (Annotation a : parameterAnnotations[i]) {
 463                     Class<? extends Annotation> annotationType = a.annotationType();
 464                     if (annotationType == ConstantParameter.class || annotationType == VarargsParameter.class || annotationType == NonNullParameter.class) {
 465                         VerificationError verificationError = new VerificationError("Parameter %d of %s is annotated with %s but the method is not annotated with %s", i, method,
 466                                         annotationType.getSimpleName(),
 467                                         Snippet.class.getSimpleName());
 468                         throw verificationError;
 469                     }
 470                 }
 471             }
 472         }
 473     }
 474 
 475     /**
 476      * Checks the invariants for a single graph.
 477      */
 478     private static void checkGraph(List<VerifyPhase<CoreProviders>> verifiers, HighTierContext context, StructuredGraph graph) {
 479         for (VerifyPhase<CoreProviders> verifier : verifiers) {
 480             if (!(verifier instanceof VerifyUsageWithEquals) || shouldVerifyEquals(graph.method())) {
 481                 verifier.apply(graph, context);
 482             } else {
 483                 verifier.apply(graph, context);
 484             }
 485         }
 486         if (graph.method().isBridge()) {
 487             BridgeMethodUtils.getBridgedMethod(graph.method());
 488         }
 489     }
 490 
 491     private static boolean matches(String[] filters, String s) {
 492         if (filters == null || filters.length == 0) {
 493             return true;
 494         }
 495         for (String filter : filters) {
 496             if (s.contains(filter)) {
 497                 return true;
 498             }
 499         }
 500         return false;
 501     }
 502 
 503     private static String printStackTraceToString(Throwable t) {
 504         StringWriter sw = new StringWriter();
 505         t.printStackTrace(new PrintWriter(sw));
 506         return sw.toString();
 507     }
 508 
 509     static class BadUsageWithEquals {
 510         Value aValue;
 511         Register aRegister;
 512         RegisterCategory aRegisterCategory;
 513         JavaType aJavaType;
 514         JavaField aJavaField;
 515         JavaMethod aJavaMethod;
 516         LocationIdentity aLocationIdentity;
 517         LIRKind aLIRKind;
 518         ArithmeticOpTable anArithmeticOpTable;
 519         ArithmeticOpTable.Op anArithmeticOpTableOp;
 520 
 521         static Value aStaticValue;
 522         static Register aStaticRegister;
 523         static RegisterCategory aStaticRegisterCategory;
 524         static JavaType aStaticJavaType;
 525         static JavaField aStaticJavaField;
 526         static JavaMethod aStaticJavaMethod;
 527         static LocationIdentity aStaticLocationIdentity;
 528         static LIRKind aStaticLIRKind;
 529         static ArithmeticOpTable aStaticArithmeticOpTable;
 530         static ArithmeticOpTable.Op aStaticArithmeticOpTableOp;
 531 
 532         boolean test01(Value f) {
 533             return aValue == f;
 534         }
 535 
 536         boolean test02(Register f) {
 537             return aRegister == f;
 538         }
 539 
 540         boolean test03(RegisterCategory f) {
 541             return aRegisterCategory == f;
 542         }
 543 
 544         boolean test04(JavaType f) {
 545             return aJavaType == f;
 546         }
 547 
 548         boolean test05(JavaField f) {
 549             return aJavaField == f;
 550         }
 551 
 552         boolean test06(JavaMethod f) {
 553             return aJavaMethod == f;
 554         }
 555 
 556         boolean test07(LocationIdentity f) {
 557             return aLocationIdentity == f;
 558         }
 559 
 560         boolean test08(LIRKind f) {
 561             return aLIRKind == f;
 562         }
 563 
 564         boolean test09(ArithmeticOpTable f) {
 565             return anArithmeticOpTable == f;
 566         }
 567 
 568         boolean test10(ArithmeticOpTable.Op f) {
 569             return anArithmeticOpTableOp == f;
 570         }
 571 
 572         boolean test12(Value f) {
 573             return aStaticValue == f;
 574         }
 575 
 576         boolean test13(Register f) {
 577             return aStaticRegister == f;
 578         }
 579 
 580         boolean test14(RegisterCategory f) {
 581             return aStaticRegisterCategory == f;
 582         }
 583 
 584         boolean test15(JavaType f) {
 585             return aStaticJavaType == f;
 586         }
 587 
 588         boolean test16(JavaField f) {
 589             return aStaticJavaField == f;
 590         }
 591 
 592         boolean test17(JavaMethod f) {
 593             return aStaticJavaMethod == f;
 594         }
 595 
 596         boolean test18(LocationIdentity f) {
 597             return aStaticLocationIdentity == f;
 598         }
 599 
 600         boolean test19(LIRKind f) {
 601             return aStaticLIRKind == f;
 602         }
 603 
 604         boolean test20(ArithmeticOpTable f) {
 605             return aStaticArithmeticOpTable == f;
 606         }
 607 
 608         boolean test21(ArithmeticOpTable.Op f) {
 609             return aStaticArithmeticOpTableOp == f;
 610         }
 611     }
 612 }