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 }