From 5c626bb20915c2fdc8bdffc220bdd345a4bd9f56 Mon Sep 17 00:00:00 2001 From: kshefov Date: Thu, 18 Jun 2015 19:15:14 +0300 Subject: [PATCH] 8062904: TEST_BUG: Tests java/lang/invoke/LFCaching fail when run with -Xcomp option Reviewed-by: vlivanov --- .../invoke/LFCaching/LFCachingTestCase.java | 2 +- .../LFCaching/LFGarbageCollectedTest.java | 16 +- .../LFCaching/LFMultiThreadCachingTest.java | 49 +++++- .../LFCaching/LFSingleThreadCachingTest.java | 4 +- .../invoke/LFCaching/LambdaFormTestCase.java | 149 ++++++++++-------- 5 files changed, 136 insertions(+), 84 deletions(-) diff --git a/test/java/lang/invoke/LFCaching/LFCachingTestCase.java b/test/java/lang/invoke/LFCaching/LFCachingTestCase.java index 50a57e40c..b5f99bd00 100644 --- a/test/java/lang/invoke/LFCaching/LFCachingTestCase.java +++ b/test/java/lang/invoke/LFCaching/LFCachingTestCase.java @@ -77,7 +77,7 @@ public abstract class LFCachingTestCase extends LambdaFormTestCase { } } catch (IllegalAccessException | IllegalArgumentException | SecurityException | InvocationTargetException ex) { - throw new Error("Unexpected exception: ", ex); + throw new Error("Unexpected exception", ex); } } } diff --git a/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java b/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java index a60d46044..347fabbb4 100644 --- a/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java +++ b/test/java/lang/invoke/LFCaching/LFGarbageCollectedTest.java @@ -59,10 +59,10 @@ public final class LFGarbageCollectedTest extends LambdaFormTestCase { super(testMethod); } - PhantomReference ph; - ReferenceQueue rq = new ReferenceQueue(); - MethodType mtype; - Map data; + PhantomReference ph; + ReferenceQueue rq = new ReferenceQueue(); + MethodType mtype; + Map data; @Override public void doTest() { @@ -73,7 +73,7 @@ public final class LFGarbageCollectedTest extends LambdaFormTestCase { try { adapter = testCase.getTestCaseMH(data, TestMethods.Kind.ONE); } catch (NoSuchMethodException ex) { - throw new Error("Unexpected exception: ", ex); + throw new Error("Unexpected exception", ex); } mtype = adapter.type(); Object lambdaForm = INTERNAL_FORM.invoke(adapter); @@ -94,12 +94,12 @@ public final class LFGarbageCollectedTest extends LambdaFormTestCase { collectLambdaForm(); } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException ex) { - throw new Error("Unexpected exception: ", ex); + throw new Error("Unexpected exception", ex); } } private void collectLambdaForm() throws IllegalAccessException { - // Usually, 2 System.GCs are necessary to enqueue a SoftReference. + // Usually, 2 System.GCs are necessary to enqueue a SoftReference. System.gc(); System.gc(); @@ -129,7 +129,7 @@ public final class LFGarbageCollectedTest extends LambdaFormTestCase { }; } - private void dumpTestData() { + private void dumpTestData() { System.err.println("Test case: " + getTestMethod()); for (String s : data.keySet()) { System.err.printf("\t%20s => %s\n", s, data.get(s)); diff --git a/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java b/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java index 35c2f97d1..05d378bcf 100644 --- a/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java +++ b/test/java/lang/invoke/LFCaching/LFMultiThreadCachingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -35,18 +35,23 @@ */ import java.lang.invoke.MethodHandle; +import java.util.Collections; import java.util.EnumSet; +import java.util.HashMap; import java.util.Map; import java.util.concurrent.BrokenBarrierException; import java.util.concurrent.ConcurrentLinkedQueue; import java.util.concurrent.CountDownLatch; import java.util.concurrent.CyclicBarrier; +import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor; /** * Multiple threaded lambda forms caching test class. */ public final class LFMultiThreadCachingTest extends LFCachingTestCase { + private static final TestMethods.Kind[] KINDS; + static { EnumSet set = EnumSet.complementOf(EnumSet.of(TestMethods.Kind.EXCEPT)); KINDS = set.toArray(new TestMethods.Kind[set.size()]); @@ -72,21 +77,55 @@ public final class LFMultiThreadCachingTest extends LFCachingTestCase { ConcurrentLinkedQueue adapters = new ConcurrentLinkedQueue<>(); CyclicBarrier begin = new CyclicBarrier(CORES); CountDownLatch end = new CountDownLatch(CORES); + final Map threadUncaughtExceptions + = Collections.synchronizedMap(new HashMap(CORES)); + Thread.UncaughtExceptionHandler exHandler = (t, e) -> { + threadUncaughtExceptions.put(t, e); + }; for (int i = 0; i < CORES; ++i) { TestMethods.Kind kind = KINDS[i % KINDS.length]; - new Thread(() -> { + Thread t = new Thread(() -> { try { begin.await(); adapters.add(getTestMethod().getTestCaseMH(data, kind)); - } catch (InterruptedException | BrokenBarrierException | IllegalAccessException | NoSuchMethodException ex) { - throw new Error("Unexpected exception: ", ex); + } catch (InterruptedException | BrokenBarrierException + | IllegalAccessException | NoSuchMethodException ex) { + throw new Error("Unexpected exception", ex); } finally { end.countDown(); } - }).start(); + }); + t.setUncaughtExceptionHandler(exHandler); + t.start(); } try { end.await(); + boolean vmeThrown = false; + boolean nonVmeThrown = false; + Throwable vme = null; + for (Map.Entry entry : threadUncaughtExceptions.entrySet()) { + Thread t = entry.getKey(); + Throwable e = entry.getValue(); + System.err.printf("%nA thread with name \"%s\" of %d threads" + + " has thrown exception:%n", t.getName(), CORES); + e.printStackTrace(); + if (CodeCacheOverflowProcessor.isThrowableCausedByVME(e)) { + vmeThrown = true; + vme = e; + } else { + nonVmeThrown = true; + } + if (nonVmeThrown) { + throw new Error("One ore more threads have" + + " thrown unexpected exceptions. See log."); + } + if (vmeThrown) { + throw new Error("One ore more threads have" + + " thrown VirtualMachineError caused by" + + " code cache overflow. See log.", vme); + } + } } catch (InterruptedException ex) { throw new Error("Unexpected exception: ", ex); } diff --git a/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java b/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java index 6a44e44d8..3d468a483 100644 --- a/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java +++ b/test/java/lang/invoke/LFCaching/LFSingleThreadCachingTest.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -62,7 +62,7 @@ public final class LFSingleThreadCachingTest extends LFCachingTestCase { adapter1 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.ONE); adapter2 = getTestMethod().getTestCaseMH(data, TestMethods.Kind.TWO); } catch (NoSuchMethodException | IllegalAccessException ex) { - throw new Error("Unexpected exception: ", ex); + throw new Error("Unexpected exception", ex); } checkLFCaching(adapter1, adapter2); } diff --git a/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java b/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java index 5d037cabc..f94588380 100644 --- a/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java +++ b/test/java/lang/invoke/LFCaching/LambdaFormTestCase.java @@ -1,5 +1,5 @@ /* - * Copyright (c) 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2014, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -22,8 +22,7 @@ */ import com.oracle.testlibrary.jsr292.Helper; -import com.sun.management.HotSpotDiagnosticMXBean; - +import com.oracle.testlibrary.jsr292.CodeCacheOverflowProcessor; import java.lang.invoke.MethodHandle; import java.lang.management.GarbageCollectorMXBean; import java.lang.management.ManagementFactory; @@ -45,8 +44,6 @@ import jdk.testlibrary.TimeLimitedRunner; */ public abstract class LambdaFormTestCase { - private static final double ITERATIONS_TO_CODE_CACHE_SIZE_RATIO - = 45 / (128.0 * 1024 * 1024); private static final long TIMEOUT = Helper.IS_THOROUGH ? 0L : (long) (Utils.adjustTimeout(Utils.DEFAULT_TEST_TIMEOUT) * 0.9); /** @@ -73,23 +70,89 @@ public abstract class LambdaFormTestCase { REF_FIELD = Reference.class.getDeclaredField("referent"); REF_FIELD.setAccessible(true); } catch (Exception ex) { - throw new Error("Unexpected exception: ", ex); + throw new Error("Unexpected exception", ex); } gcInfo = ManagementFactory.getGarbageCollectorMXBeans(); - if (gcInfo.size() == 0) { + if (gcInfo.size() == 0) { throw new Error("No GarbageCollectorMXBeans found."); } } private final TestMethods testMethod; - private static long totalIterations = 0L; - private static long doneIterations = 0L; - private static boolean passed = true; - private static int testCounter = 0; - private static int failCounter = 0; private long gcCountAtStart; + private static class TestRun { + + final Function ctor; + final Collection testMethods; + final long totalIterations; + long doneIterations; + long testCounter; + long failCounter; + boolean passed; + + TestRun(Function ctor, Collection testMethods) { + this.ctor = ctor; + this.testMethods = testMethods; + long testCaseNum = testMethods.size(); + long iterations = Math.max(1, Helper.TEST_LIMIT / testCaseNum); + System.out.printf("Number of iterations according to -DtestLimit is %d (%d cases)%n", + iterations, iterations * testCaseNum); + System.out.printf("Number of iterations is set to %d (%d cases)%n", + iterations, iterations * testCaseNum); + System.out.flush(); + totalIterations = iterations; + doneIterations = 0L; + testCounter = 0L; + failCounter = 0L; + passed = true; + } + + Boolean doIteration() { + if (doneIterations >= totalIterations) { + return false; + } + System.err.println(String.format("Iteration %d:", doneIterations)); + for (TestMethods testMethod : testMethods) { + LambdaFormTestCase testCase = ctor.apply(testMethod); + try { + System.err.printf("Tested LF caching feature" + + " with MethodHandles.%s method.%n", + testCase.getTestMethod().name); + Throwable t = CodeCacheOverflowProcessor + .runMHTest(testCase::doTest); + if (t != null) { + return false; + } + System.err.println("PASSED"); + } catch (OutOfMemoryError oome) { + // Don't swallow OOME so a heap dump can be created. + System.err.println("FAILED"); + throw oome; + } catch (Throwable t) { + t.printStackTrace(); + System.err.printf("FAILED. Caused by %s%n", t.getMessage()); + passed = false; + failCounter++; + } + testCounter++; + } + doneIterations++; + return true; + } + + void checkPassed() { + if (!passed) { + throw new Error(String.format("%d of %d test cases FAILED! %n" + + "Rerun the test with the same \"-Dseed=\" option as in the log file!", + failCounter, testCounter)); + } else { + System.err.printf("All %d test cases PASSED!%n", testCounter); + } + } + } + /** * Test case constructor. Generates test cases with random method types for * given methods form {@code j.l.i.MethodHandles} class. @@ -123,65 +186,15 @@ public abstract class LambdaFormTestCase { * @param testMethods list of test methods */ public static void runTests(Function ctor, Collection testMethods) { - long testCaseNum = testMethods.size(); - totalIterations = Math.max(1, Helper.TEST_LIMIT / testCaseNum); - System.out.printf("Number of iterations according to -DtestLimit is %d (%d cases)%n", - totalIterations, totalIterations * testCaseNum); - HotSpotDiagnosticMXBean hsDiagBean = ManagementFactory.getPlatformMXBean(HotSpotDiagnosticMXBean.class); - long codeCacheSize = Long.parseLong( - hsDiagBean.getVMOption("ReservedCodeCacheSize").getValue()); - System.out.printf("Code Cache Size is %d bytes%n", codeCacheSize); - long iterationsByCodeCacheSize = (long) (codeCacheSize - * ITERATIONS_TO_CODE_CACHE_SIZE_RATIO); - System.out.printf("Number of iterations limited by code cache size is %d (%d cases)%n", - iterationsByCodeCacheSize, iterationsByCodeCacheSize * testCaseNum); - if (totalIterations > iterationsByCodeCacheSize) { - totalIterations = iterationsByCodeCacheSize; - } - System.out.printf("Number of iterations is set to %d (%d cases)%n", - totalIterations, totalIterations * testCaseNum); - System.out.flush(); - TimeLimitedRunner runner = new TimeLimitedRunner(TIMEOUT, 4.0d, - () -> { - if (doneIterations >= totalIterations) { - return false; - } - System.err.println(String.format("Iteration %d:", doneIterations)); - for (TestMethods testMethod : testMethods) { - LambdaFormTestCase testCase = ctor.apply(testMethod); - try { - System.err.printf("Tested LF caching feature with MethodHandles.%s method.%n", - testCase.getTestMethod().name); - testCase.doTest(); - System.err.println("PASSED"); - } catch (OutOfMemoryError e) { - // Don't swallow OOME so a heap dump can be created. - System.err.println("FAILED"); - throw e; - } catch (Throwable t) { - t.printStackTrace(); - System.err.println("FAILED"); - passed = false; - failCounter++; - } - testCounter++; - } - doneIterations++; - return true; - }); + LambdaFormTestCase.TestRun run + = new LambdaFormTestCase.TestRun(ctor, testMethods); + TimeLimitedRunner runner = new TimeLimitedRunner(TIMEOUT, 4.0d, run::doIteration); try { runner.call(); - } catch (Throwable t) { - t.printStackTrace(); + } catch (Exception ex) { System.err.println("FAILED"); - throw new Error("Unexpected error!"); - } - if (!passed) { - throw new Error(String.format("%d of %d test cases FAILED! %n" - + "Rerun the test with the same \"-Dseed=\" option as in the log file!", - failCounter, testCounter)); - } else { - System.err.println(String.format("All %d test cases PASSED!", testCounter)); + throw new Error("Unexpected error!", ex); } + run.checkPassed(); } } -- GitLab