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