test/hotspot/jtreg/serviceability/jvmti/GetOwnedMonitorStackDepthInfo/GetOwnedMonitorStackDepthInfoWithEATest.java
changeset 58512 5185bc8dcbb1
child 58522 17a34e111667
equal deleted inserted replaced
58511:eb68d459ba6a 58512:5185bc8dcbb1
       
     1 /*
       
     2  * Copyright (c) 2019 SAP SE. 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  * @test
       
    26  * @bug 8230677
       
    27  * @summary Test JVMTI's GetOwnedMonitorStackDepthInfo with scalar replaced objects and eliminated locks on stack (optimizations based on escape analysis).
       
    28  * @comment Without RFE 8227745 escape analysis needs to be switched off to pass the test. For the implementation of RFE 8227745 it serves as a regression test.
       
    29  * @requires (vm.compMode != "Xcomp" & vm.compiler2.enabled)
       
    30  * @library /test/lib
       
    31  * @compile GetOwnedMonitorStackDepthInfoWithEATest.java
       
    32  * @run main/othervm/native
       
    33  *                  -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
       
    34  *                  -XX:+UnlockDiagnosticVMOptions
       
    35  *                  -Xms32m -Xmx32m
       
    36  *                  -XX:CompileCommand=dontinline,*::dontinline_*
       
    37  *                  -XX:+PrintCompilation
       
    38  *                  -XX:+PrintInlining
       
    39  *                  -XX:-TieredCompilation
       
    40  *                  -Xbatch
       
    41  *                  -XX:CICompilerCount=1
       
    42  *                  -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
       
    43  *                  GetOwnedMonitorStackDepthInfoWithEATest
       
    44  * @run main/othervm/native
       
    45  *                  -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
       
    46  *                  -XX:+UnlockDiagnosticVMOptions
       
    47  *                  -Xms32m -Xmx32m
       
    48  *                  -XX:CompileCommand=dontinline,*::dontinline_*
       
    49  *                  -XX:+PrintCompilation
       
    50  *                  -XX:+PrintInlining
       
    51  *                  -XX:-TieredCompilation
       
    52  *                  -Xbatch
       
    53  *                  -XX:CICompilerCount=1
       
    54  *                  -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:-EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking -XX:-UseOptoBiasInlining
       
    55  *                  GetOwnedMonitorStackDepthInfoWithEATest
       
    56  * @run main/othervm/native
       
    57  *                  -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
       
    58  *                  -XX:+UnlockDiagnosticVMOptions
       
    59  *                  -Xms32m -Xmx32m
       
    60  *                  -XX:CompileCommand=dontinline,*::dontinline_*
       
    61  *                  -XX:+PrintCompilation
       
    62  *                  -XX:+PrintInlining
       
    63  *                  -XX:-TieredCompilation
       
    64  *                  -Xbatch
       
    65  *                  -XX:CICompilerCount=1
       
    66  *                  -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
       
    67  *                  GetOwnedMonitorStackDepthInfoWithEATest
       
    68  * @run main/othervm/native
       
    69  *                  -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
       
    70  *                  -XX:+UnlockDiagnosticVMOptions
       
    71  *                  -Xms32m -Xmx32m
       
    72  *                  -XX:CompileCommand=dontinline,*::dontinline_*
       
    73  *                  -XX:+PrintCompilation
       
    74  *                  -XX:+PrintInlining
       
    75  *                  -XX:-TieredCompilation
       
    76  *                  -Xbatch
       
    77  *                  -XX:CICompilerCount=1
       
    78  *                  -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking
       
    79  *                  GetOwnedMonitorStackDepthInfoWithEATest
       
    80  * @run main/othervm/native
       
    81  *                  -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
       
    82  *                  -XX:+UnlockDiagnosticVMOptions
       
    83  *                  -Xms32m -Xmx32m
       
    84  *                  -XX:CompileCommand=dontinline,*::dontinline_*
       
    85  *                  -XX:+PrintCompilation
       
    86  *                  -XX:+PrintInlining
       
    87  *                  -XX:-TieredCompilation
       
    88  *                  -Xbatch
       
    89  *                  -XX:CICompilerCount=1
       
    90  *                  -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
       
    91  *                  GetOwnedMonitorStackDepthInfoWithEATest
       
    92  * @run main/othervm/native
       
    93  *                  -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
       
    94  *                  -XX:+UnlockDiagnosticVMOptions
       
    95  *                  -Xms32m -Xmx32m
       
    96  *                  -XX:CompileCommand=dontinline,*::dontinline_*
       
    97  *                  -XX:+PrintCompilation
       
    98  *                  -XX:+PrintInlining
       
    99  *                  -XX:-TieredCompilation
       
   100  *                  -Xbatch
       
   101  *                  -XX:CICompilerCount=1
       
   102  *                  -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
       
   103  *                  GetOwnedMonitorStackDepthInfoWithEATest
       
   104  * @run main/othervm/native
       
   105  *                  -agentlib:GetOwnedMonitorStackDepthInfoWithEATest
       
   106  *                  -XX:+UnlockDiagnosticVMOptions
       
   107  *                  -Xms32m -Xmx32m
       
   108  *                  -XX:CompileCommand=dontinline,*::dontinline_*
       
   109  *                  -XX:+PrintCompilation
       
   110  *                  -XX:+PrintInlining
       
   111  *                  -XX:-TieredCompilation
       
   112  *                  -Xbatch
       
   113  *                  -XX:CICompilerCount=1
       
   114  *                  -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:-UseBiasedLocking
       
   115  *                  GetOwnedMonitorStackDepthInfoWithEATest
       
   116  */
       
   117 
       
   118 import jdk.test.lib.Asserts;
       
   119 
       
   120 public class GetOwnedMonitorStackDepthInfoWithEATest {
       
   121 
       
   122     public static final int COMPILE_THRESHOLD = 20000;
       
   123 
       
   124     /**
       
   125      * Native wrapper arround JVMTI's GetOwnedMonitorStackDepthInfo().
       
   126      * @param t The thread for which the owned monitors information should be retrieved.
       
   127      * @param ownedMonitors Array filled in by the call with the objects associated
       
   128      *        with the monitors owned by the given thread.
       
   129      * @param depths Per owned monitor the depth of the frame were it was locked.
       
   130      *        Filled in by the call
       
   131      * @return Number of monitors owned by the given thread.
       
   132      */
       
   133     public static native int getOwnedMonitorStackDepthInfo(Thread t, Object[] ownedMonitors, int[] depths);
       
   134 
       
   135     public static void main(String[] args) throws Exception {
       
   136         new GetOwnedMonitorStackDepthInfoWithEATest().runTest();
       
   137     }
       
   138 
       
   139     public void runTest() throws Exception {
       
   140         new TestCase_1().run();
       
   141         new TestCase_2().run();
       
   142     }
       
   143 
       
   144     public static abstract class TestCaseBase implements Runnable {
       
   145 
       
   146         public long checkSum;
       
   147         public boolean doLoop;
       
   148         public volatile long loopCount;
       
   149         public volatile boolean targetIsInLoop;
       
   150 
       
   151         public void run() {
       
   152             try {
       
   153                 msgHL("Executing test case " + getClass().getName());
       
   154                 warmUp();
       
   155                 runTest();
       
   156             } catch (Exception e) {
       
   157                 Asserts.fail("Unexpected Exception", e);
       
   158             }
       
   159         }
       
   160 
       
   161         public void warmUp() {
       
   162             int callCount = COMPILE_THRESHOLD + 1000;
       
   163             doLoop = true;
       
   164             while (callCount-- > 0) {
       
   165                 dontinline_testMethod();
       
   166             }
       
   167         }
       
   168 
       
   169         public abstract void runTest() throws Exception;
       
   170         public abstract void dontinline_testMethod();
       
   171 
       
   172         public long dontinline_endlessLoop() {
       
   173             long cs = checkSum;
       
   174             while (doLoop && loopCount-- > 0) {
       
   175                 targetIsInLoop = true;
       
   176                 checkSum += checkSum % ++cs;
       
   177             }
       
   178             loopCount = 3;
       
   179             targetIsInLoop = false;
       
   180             return checkSum;
       
   181         }
       
   182 
       
   183         public void waitUntilTargetThreadHasEnteredEndlessLoop() throws Exception {
       
   184             while(!targetIsInLoop) {
       
   185                 msg("Target has not yet entered the loop. Sleep 200ms.");
       
   186                 try { Thread.sleep(200); } catch (InterruptedException e) { /*ignore */ }
       
   187             }
       
   188             msg("Target has entered the loop.");
       
   189         }
       
   190 
       
   191         public void terminateEndlessLoop() throws Exception {
       
   192             msg("Terminate endless loop");
       
   193             do {
       
   194                 doLoop = false;
       
   195             } while(targetIsInLoop);
       
   196         }
       
   197 
       
   198         public void msg(String m) {
       
   199             System.out.println();
       
   200             System.out.println("### " + m);
       
   201             System.out.println();
       
   202         }
       
   203 
       
   204         public void msgHL(String m) {
       
   205             System.out.println();
       
   206             System.out.println("#####################################################");
       
   207             System.out.println("### " + m);
       
   208             System.out.println("###");
       
   209             System.out.println();
       
   210         }
       
   211     }
       
   212 
       
   213     /**
       
   214      * Starts target thread T and then queries monitor information for T using JVMTI's GetOwnedMonitorStackDepthInfo().
       
   215      * With escape analysis enabled the jit compiled method {@link #dontinline_testMethod()} has
       
   216      * scalar replaced objects with eliminated (nested) locking in scope when the monitor
       
   217      * information is retrieved. Effectively the objects escape through the JVMTI call. This works
       
   218      * only with RFE 8227745. Without it escape analysis needs to be disabled.
       
   219      */
       
   220     public static class TestCase_1 extends TestCaseBase {
       
   221 
       
   222         public void runTest() throws Exception {
       
   223             loopCount = 1L << 62; // endless loop
       
   224             Thread t1 = new Thread(() -> dontinline_testMethod(), "Target Thread");
       
   225             try {
       
   226                 t1.start();
       
   227                 waitUntilTargetThreadHasEnteredEndlessLoop();
       
   228                 int expectedMonitorCount = 1;
       
   229                 int resultSize = expectedMonitorCount + 3;
       
   230                 Object[] ownedMonitors = new Object[resultSize];
       
   231                 int[]    depths = new int[resultSize];
       
   232                 msg("Get monitor info");
       
   233                 int monitorCount = getOwnedMonitorStackDepthInfo(t1, ownedMonitors, depths);
       
   234                 Asserts.assertGreaterThanOrEqual(monitorCount, 0, "getOwnedMonitorsFor() call failed");
       
   235                 msg("Monitor info:");
       
   236                 for (int i = 0; i < monitorCount; i++) {
       
   237                     System.out.println(i + ": cls=" + (ownedMonitors[i] != null ? ownedMonitors[i].getClass() : null) + " depth=" + depths[i]);
       
   238                 }
       
   239                 Asserts.assertEQ(monitorCount, expectedMonitorCount, "unexpected monitor count returned by getOwnedMonitorsFor()");
       
   240                 Asserts.assertNotNull(ownedMonitors[0]);
       
   241                 Asserts.assertSame(ownedMonitors[0].getClass(), LockCls.class);
       
   242                 Asserts.assertEQ(depths[0], 1, "unexpected depth for owned monitor at index 0");
       
   243             } finally {
       
   244                 terminateEndlessLoop();
       
   245                 t1.join();
       
   246             }
       
   247         }
       
   248 
       
   249         public void dontinline_testMethod() {
       
   250             LockCls l1 = new LockCls();        // to be scalar replaced
       
   251             synchronized (l1) {
       
   252                 inlinedTestMethodWithNestedLocking(l1);
       
   253             }
       
   254         }
       
   255 
       
   256         public void inlinedTestMethodWithNestedLocking(LockCls l1) {
       
   257             synchronized (l1) {              // nested
       
   258                 dontinline_endlessLoop();
       
   259             }
       
   260         }
       
   261     }
       
   262 
       
   263     /**
       
   264      * Similar to {@link TestCase_1}. Additionally the target thread T has got eliminated locking
       
   265      * for a synchronized method of a different type {@linkplain LockCls2}.
       
   266      */
       
   267     public static class TestCase_2 extends TestCaseBase {
       
   268 
       
   269         public void runTest() throws Exception {
       
   270             loopCount = 1L << 62; // endless loop
       
   271             Thread t1 = new Thread(() -> dontinline_testMethod(), "Target Thread");
       
   272             t1.start();
       
   273             try {
       
   274                 waitUntilTargetThreadHasEnteredEndlessLoop();
       
   275                 int expectedMonitorCount = 2;
       
   276                 int resultSize = expectedMonitorCount + 3;
       
   277                 Object[] ownedMonitors = new Object[resultSize];
       
   278                 int[]    depths = new int[resultSize];
       
   279                 msg("Get monitor info");
       
   280                 int monitorCount = getOwnedMonitorStackDepthInfo(t1, ownedMonitors, depths);
       
   281                 terminateEndlessLoop();
       
   282                 t1.join();
       
   283                 Asserts.assertGreaterThanOrEqual(monitorCount, 0, "getOwnedMonitorsFor() call failed");
       
   284                 msg("Monitor info:");
       
   285                 for (int i = 0; i < monitorCount; i++) {
       
   286                     System.out.println(i + ": cls=" + (ownedMonitors[i] != null ? ownedMonitors[i].getClass() : null) + " depth=" + depths[i]);
       
   287                 }
       
   288                 Asserts.assertEQ(monitorCount, expectedMonitorCount, "unexpected monitor count returned by getOwnedMonitorsFor()");
       
   289                 Asserts.assertNotNull(ownedMonitors[0]);
       
   290                 Asserts.assertSame(ownedMonitors[0].getClass(), LockCls2.class);
       
   291                 Asserts.assertEQ(depths[0], 1, "unexpected depth for owned monitor at index 0");
       
   292 
       
   293                 Asserts.assertNotNull(ownedMonitors[1]);
       
   294                 Asserts.assertSame(ownedMonitors[1].getClass(), LockCls.class);
       
   295                 Asserts.assertEQ(depths[1], 3, "unexpected depth for owned monitor at index 1");
       
   296             } finally {
       
   297                 terminateEndlessLoop();
       
   298                 t1.join();
       
   299             }
       
   300         }
       
   301 
       
   302         public void dontinline_testMethod() {
       
   303             LockCls l1 = new LockCls();
       
   304             synchronized (l1) {
       
   305                 inlinedTestMethodWithNestedLocking(l1);
       
   306             }
       
   307         }
       
   308 
       
   309         public void inlinedTestMethodWithNestedLocking(LockCls l1) {
       
   310             synchronized (l1) {
       
   311                 dontinline_testMethod2();
       
   312             }
       
   313         }
       
   314 
       
   315         public void dontinline_testMethod2() {
       
   316             // Call synchronized method. Receiver of the call will be scalar replaced,
       
   317             // and locking will be eliminated. Here we use a different type.
       
   318             new LockCls2().inline_synchronized_testMethod(this);
       
   319         }
       
   320     }
       
   321 
       
   322     public static class LockCls {
       
   323     }
       
   324 
       
   325     public static class LockCls2 {
       
   326         public synchronized void inline_synchronized_testMethod(TestCaseBase testCase) {
       
   327             testCase.dontinline_endlessLoop();
       
   328         }
       
   329     }
       
   330 }