1 /* 2 * Copyright (c) 2020 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 8230956 27 * @summary JVMTI agents can obtain references to not escaping objects using JVMTI Heap functions. 28 * Therefore optimizations based on escape analysis have to be reverted, 29 * i.e. scalar replaced objects need to be reallocated on the heap and objects with eliminated locking 30 * need to be relocked. 31 * @requires ((vm.compMode == "Xmixed") & vm.compiler2.enabled) 32 * @library /test/lib /test/hotspot/jtreg 33 * @build sun.hotspot.WhiteBox 34 * @run driver ClassFileInstaller sun.hotspot.WhiteBox 35 * @compile IterateHeapWithEscapeAnalysisEnabled.java 36 * 37 * @comment BLOCK BEGIN EXCLUSIVE TESTCASES { 38 * 39 * The following test cases are executed in fresh VMs, because they require that the 40 * capability can_tag_objects is not taken until dontinline_testMethod is jit compiled and 41 * an activation of the compiled version is on stack of the target thread. 42 * 43 * Without JDK-8227745 these test cases require that escape analysis is disabled at 44 * start-up, because can_tag_objects can be taken lazily, potentially after loading an 45 * agent dynamically by means of the attach API. Disabling escape analysis and invalidating 46 * compiled methods does not help then, because there may be compiled frames with ea-based 47 * optimizations on stack. Just like in this collection of test cases. 48 * 49 * @run main/othervm/native 50 * -agentlib:IterateHeapWithEscapeAnalysisEnabled 51 * -XX:+UnlockDiagnosticVMOptions 52 * -Xms256m -Xmx256m 53 * -XX:+PrintCompilation -XX:+PrintInlining 54 * -XX:+WhiteBoxAPI -Xbootclasspath/a:. 55 * -Xbatch 56 * -XX:CompileCommand=dontinline,*::dontinline_* 57 * -XX:+DoEscapeAnalysis 58 * IterateHeapWithEscapeAnalysisEnabled IterateOverReachableObjects 59 * @run main/othervm/native 60 * -agentlib:IterateHeapWithEscapeAnalysisEnabled 61 * -XX:+UnlockDiagnosticVMOptions 62 * -Xms256m -Xmx256m 63 * -XX:+PrintCompilation -XX:+PrintInlining 64 * -XX:+WhiteBoxAPI -Xbootclasspath/a:. 65 * -Xbatch 66 * -XX:CompileCommand=dontinline,*::dontinline_* 67 * -XX:+DoEscapeAnalysis 68 * IterateHeapWithEscapeAnalysisEnabled IterateOverHeap 69 * @run main/othervm/native 70 * -agentlib:IterateHeapWithEscapeAnalysisEnabled 71 * -XX:+UnlockDiagnosticVMOptions 72 * -Xms256m -Xmx256m 73 * -XX:+PrintCompilation -XX:+PrintInlining 74 * -XX:+WhiteBoxAPI -Xbootclasspath/a:. 75 * -Xbatch 76 * -XX:CompileCommand=dontinline,*::dontinline_* 77 * -XX:+DoEscapeAnalysis 78 * IterateHeapWithEscapeAnalysisEnabled IterateOverInstancesOfClass 79 * @run main/othervm/native 80 * -agentlib:IterateHeapWithEscapeAnalysisEnabled 81 * -XX:+UnlockDiagnosticVMOptions 82 * -Xms256m -Xmx256m 83 * -XX:+PrintCompilation -XX:+PrintInlining 84 * -XX:+WhiteBoxAPI -Xbootclasspath/a:. 85 * -Xbatch 86 * -XX:CompileCommand=dontinline,*::dontinline_* 87 * -XX:+DoEscapeAnalysis 88 * IterateHeapWithEscapeAnalysisEnabled FollowReferences 89 * @run main/othervm/native 90 * -agentlib:IterateHeapWithEscapeAnalysisEnabled 91 * -XX:+UnlockDiagnosticVMOptions 92 * -Xms256m -Xmx256m 93 * -XX:+PrintCompilation -XX:+PrintInlining 94 * -XX:+WhiteBoxAPI -Xbootclasspath/a:. 95 * -Xbatch 96 * -XX:CompileCommand=dontinline,*::dontinline_* 97 * -XX:+DoEscapeAnalysis 98 * IterateHeapWithEscapeAnalysisEnabled IterateThroughHeap 99 * 100 * @comment } BLOCK END EXCLUSIVE TESTCASES 101 * 102 * @comment BLOCK BEGIN NON EXCLUSIVE TESTCASES { 103 * 104 * @run main/othervm/native 105 * -agentlib:IterateHeapWithEscapeAnalysisEnabled 106 * -XX:+UnlockDiagnosticVMOptions 107 * -Xms256m -Xmx256m 108 * -XX:CompileCommand=dontinline,*::dontinline_* 109 * -XX:+PrintCompilation 110 * -XX:+PrintInlining 111 * -XX:+WhiteBoxAPI -Xbootclasspath/a:. 112 * -Xbatch 113 * -XX:+DoEscapeAnalysis -XX:+EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking 114 * IterateHeapWithEscapeAnalysisEnabled 115 * @run main/othervm/native 116 * -agentlib:IterateHeapWithEscapeAnalysisEnabled 117 * -XX:+UnlockDiagnosticVMOptions 118 * -Xms256m -Xmx256m 119 * -XX:CompileCommand=dontinline,*::dontinline_* 120 * -XX:+PrintCompilation 121 * -XX:+PrintInlining 122 * -XX:+WhiteBoxAPI -Xbootclasspath/a:. 123 * -Xbatch 124 * -XX:+DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking 125 * IterateHeapWithEscapeAnalysisEnabled 126 * @run main/othervm/native 127 * -agentlib:IterateHeapWithEscapeAnalysisEnabled 128 * -XX:+UnlockDiagnosticVMOptions 129 * -Xms256m -Xmx256m 130 * -XX:CompileCommand=dontinline,*::dontinline_* 131 * -XX:+PrintCompilation 132 * -XX:+PrintInlining 133 * -XX:+WhiteBoxAPI -Xbootclasspath/a:. 134 * -Xbatch 135 * -XX:-DoEscapeAnalysis -XX:-EliminateAllocations -XX:+EliminateLocks -XX:+EliminateNestedLocks -XX:+UseBiasedLocking 136 * IterateHeapWithEscapeAnalysisEnabled 137 * 138 * @comment } BLOCK END NON EXCLUSIVE TESTCASES 139 */ 140 141 import compiler.whitebox.CompilerWhiteBoxTest; 142 import jdk.test.lib.Asserts; 143 import sun.hotspot.WhiteBox; 144 145 public class IterateHeapWithEscapeAnalysisEnabled { 146 147 public static final WhiteBox WB = WhiteBox.getWhiteBox(); 148 149 public static final int COMPILE_THRESHOLD = CompilerWhiteBoxTest.THRESHOLD; 150 151 public static native int jvmtiTagClass(Class<?> cls, long tag); 152 153 // Methods to tag or count instances of a given class available in JVMTI 154 public static enum TaggingAndCountingMethods { 155 IterateOverReachableObjects, 156 IterateOverHeap, 157 IterateOverInstancesOfClass, 158 FollowReferences, 159 IterateThroughHeap 160 } 161 162 public static native int acquireCanTagObjectsCapability(); 163 public static native int registerMethod(TaggingAndCountingMethods m, String name); 164 public static native void agentTearDown(); 165 166 /** 167 * Count and tag instances of a given class. 168 * @param cls Used by the method {@link TaggingAndCountingMethods#IterateOverInstancesOfClass} as class to count and tag instances of. 169 * Ignored by other counting methods. 170 * @param clsTag Tag of the class to count and tag instances of. Used by all methods except 171 * {@link TaggingAndCountingMethods#IterateOverInstancesOfClass} 172 * @param instanceTag The tag to be set for selected instances. 173 * @param method JVMTI counting and tagging method to be used. 174 * @return The number of instances or -1 if the call fails. 175 */ 176 public static native int countAndTagInstancesOfClass(Class<?> cls, long clsTag, long instanceTag, TaggingAndCountingMethods method); 177 178 /** 179 * Get all objects tagged with the given tag. 180 * @param tag The tag used to select objects. 181 * @param result Selected objects are copied into this array. 182 * @return -1 to indicated failure and 0 for success. 183 */ 184 public static native int getObjectsWithTag(long tag, Object[] result); 185 186 public static void main(String[] args) throws Exception { 187 try { 188 new IterateHeapWithEscapeAnalysisEnabled().runTestCases(args); 189 } finally { 190 agentTearDown(); 191 } 192 } 193 194 public void runTestCases(String[] args) throws Exception { 195 // register various instance tagging and counting methods with agent 196 for (TaggingAndCountingMethods m : TaggingAndCountingMethods.values()) { 197 msg("register instance count method " + m.name()); 198 int rc = registerMethod(m, m.name()); 199 Asserts.assertGreaterThanOrEqual(rc, 0, "method " + m.name() + " is unknown to agent"); 200 } 201 202 if (args.length > 0) { 203 // EXCLUSIVE TEST CASES 204 // cant_tag_objects is acquired after warmup. Use given tagging/counting method. 205 new TestCase01(true, 100, TaggingAndCountingMethods.valueOf(args[0])).run(); 206 } else { 207 // NON-EXCLUSIVE TEST CASES 208 // cant_tag_objects is acquired before test cases are run, but still during live phase. 209 msgHL("Acquire capability can_tag_objects before first test case."); 210 int err = acquireCanTagObjectsCapability(); 211 Asserts.assertEQ(0, err, "acquireCanTagObjectsCapability FAILED"); 212 213 // run test cases 214 for (TaggingAndCountingMethods m : TaggingAndCountingMethods.values()) { 215 new TestCase01(false, 200, m).run(); 216 } 217 new TestCase02a(200).run(); 218 new TestCase02b(300).run(); 219 } 220 } 221 222 static class ABBox { 223 public int aVal; 224 public int bVal; 225 public TestCaseBase testCase; 226 227 public ABBox() { /* empty */ } 228 229 public ABBox(TestCaseBase testCase) { 230 this.testCase = testCase; 231 } 232 233 /** 234 * Increment {@link #aVal} and {@link #bVal} under lock. The method is supposed to 235 * be inlined into the test method and locking is supposed to be eliminated. After 236 * this object escaped to the JVMTI agent, the code with eliminated locking must 237 * not be used anymore. 238 */ 239 public synchronized void synchronizedSlowInc() { 240 aVal++; 241 testCase.waitingForCheck = true; 242 dontinline_waitForCheck(testCase); 243 testCase.waitingForCheck = false; 244 bVal++; 245 } 246 247 public static void dontinline_waitForCheck(TestCaseBase testCase) { 248 if (testCase.warmUpDone) { 249 while(!testCase.checkingNow) { 250 try { 251 Thread.sleep(50); 252 } catch (InterruptedException e) { /*ign*/ } 253 } 254 } 255 } 256 257 /** 258 * This method and incrementing {@link #aVal} and {@link #bVal} are synchronized. 259 * So {@link #aVal} and {@link #bVal} should always be equal. Unless the optimized version 260 * of {@link #synchronizedSlowInc()} without locking is still used after this object 261 * escaped to the JVMTI agent. 262 * @return 263 */ 264 public synchronized boolean check() { 265 return aVal == bVal; 266 } 267 } 268 269 public static abstract class TestCaseBase implements Runnable { 270 public final long classTag; 271 public long instanceTag; 272 273 public final Class<?> taggedClass; 274 275 public long checkSum; 276 public long loopCount; 277 public volatile boolean doLoop; 278 public volatile boolean targetIsInLoop; 279 280 public volatile boolean waitingForCheck; 281 public volatile boolean checkingNow; 282 283 public boolean warmUpDone; 284 285 public TestCaseBase(long classTag, Class<?> taggedClass) { 286 this.classTag = classTag; 287 this.taggedClass = taggedClass; 288 } 289 290 public void setUp() { 291 // Tag the class of instances to be scalar replaced 292 msg("tagging " + taggedClass.getName() + " with tag " + classTag); 293 int err = jvmtiTagClass(taggedClass, classTag); 294 Asserts.assertEQ(0, err, "jvmtiTagClass FAILED"); 295 } 296 297 // to be overridden by test cases 298 abstract public void dontinline_testMethod(); 299 300 public void warmUp() { 301 msg("WarmUp: START"); 302 int callCount = COMPILE_THRESHOLD + 1000; 303 doLoop = true; 304 while (callCount-- > 0) { 305 dontinline_testMethod(); 306 } 307 warmUpDone = true; 308 msg("WarmUp: DONE"); 309 } 310 311 public Object dontinline_endlessLoop(Object argEscape) { 312 long cs = checkSum; 313 while (loopCount-- > 0 && doLoop) { 314 targetIsInLoop = true; 315 checkSum += checkSum % ++cs; 316 } 317 loopCount = 3; 318 targetIsInLoop = false; 319 return argEscape; 320 } 321 322 public void waitUntilTargetThreadHasEnteredEndlessLoop() { 323 while(!targetIsInLoop) { 324 msg("Target has not yet entered the loop. Sleep 100ms."); 325 try { Thread.sleep(100); } catch (InterruptedException e) { /*ignore */ } 326 } 327 msg("Target has entered the loop."); 328 } 329 330 public void terminateEndlessLoop() throws Exception { 331 msg("Terminate endless loop"); 332 doLoop = false; 333 } 334 } 335 336 /** 337 * Use JVMTI heap functions associated with the elements of {@link TaggingAndCountingMethods} to 338 * get a reference to an object allocated in {@link TestCase01#dontinline_testMethod()}. The 339 * allocation can be eliminated / scalar replaced. The test case can be run in two modes: (1) 340 * the capability can_tag_objects which is required to use the JVMTI heap functions is taken 341 * before the test case (2) the capability is taken after {@link TestCase01#dontinline_testMethod()} 342 * is compiled and the target thread has an activation of it on stack. 343 */ 344 public static class TestCase01 extends TestCaseBase { 345 346 public volatile int testMethod_result; 347 public boolean acquireCanTagObjectsCapabilityAfterWarmup; 348 public TaggingAndCountingMethods taggingMethod; 349 350 public TestCase01(boolean acquireCanTagObjectsCapabilityAfterWarmup, long classTag, TaggingAndCountingMethods taggingMethod) { 351 super(classTag, ABBox.class); 352 instanceTag = classTag + 1; 353 this.acquireCanTagObjectsCapabilityAfterWarmup = acquireCanTagObjectsCapabilityAfterWarmup; 354 this.taggingMethod = taggingMethod; 355 } 356 357 @Override 358 public void setUp() { 359 if (!acquireCanTagObjectsCapabilityAfterWarmup) { 360 super.setUp(); 361 } 362 } 363 364 public void setUpAfterWarmUp() { 365 if (acquireCanTagObjectsCapabilityAfterWarmup) { 366 msg("Acquire capability can_tag_objects " + (warmUpDone ? "after" : "before") + " warmup."); 367 int err = acquireCanTagObjectsCapability(); 368 Asserts.assertEQ(0, err, "acquireCanTagObjectsCapability FAILED"); 369 super.setUp(); 370 } 371 } 372 373 public void run() { 374 try { 375 msgHL(getClass().getName() + ": test if object that may be scalar replaced is found using " + taggingMethod); 376 msg("The capability can_tag_object is acquired " + (acquireCanTagObjectsCapabilityAfterWarmup ? "AFTER" : "BEFORE") 377 + " warmup."); 378 setUp(); 379 warmUp(); 380 WB.deflateIdleMonitors(); 381 WB.fullGC(); // get rid of dead instances from previous test cases 382 runTest(taggingMethod); 383 } catch (Exception e) { 384 Asserts.fail("Unexpected Exception", e); 385 } 386 } 387 388 public void runTest(TaggingAndCountingMethods m) throws Exception { 389 loopCount = 1L << 62; // endless loop 390 doLoop = true; 391 testMethod_result = 0; 392 Thread t1 = new Thread(() -> dontinline_testMethod(), "Target Thread (" + getClass().getName() + ")"); 393 try { 394 t1.start(); 395 try { 396 waitUntilTargetThreadHasEnteredEndlessLoop(); 397 setUpAfterWarmUp(); 398 msg("count and tag instances of " + taggedClass.getName() + " with tag " + instanceTag + " using JVMTI " + m.name()); 399 int count = countAndTagInstancesOfClass(taggedClass, classTag, instanceTag, m); 400 msg("Done. Count is " + count); 401 Asserts.assertGreaterThanOrEqual(count, 0, "countAndTagInstancesOfClass FAILED"); 402 Asserts.assertEQ(count, 1, "unexpected number of instances"); 403 404 ABBox[] result = new ABBox[1]; 405 msg("get instances tagged with " + instanceTag + ". The instances escape thereby."); 406 int err = getObjectsWithTag(instanceTag, result); 407 msg("Done."); 408 Asserts.assertEQ(0, err, "getObjectsWithTag FAILED"); 409 410 msg("change the now escaped instance' bVal"); 411 ABBox abBox = result[0]; 412 abBox.bVal = 3; 413 terminateEndlessLoop(); 414 415 msg("wait until target thread has set testMethod_result"); 416 while (testMethod_result == 0) { 417 Thread.sleep(50); 418 } 419 msg("check if the modification of bVal is reflected in testMethod_result."); 420 Asserts.assertEQ(7, testMethod_result, " testMethod_result has wrong value"); 421 msg("ok."); 422 } finally { 423 terminateEndlessLoop(); 424 } 425 } finally { 426 t1.join(); 427 } 428 } 429 430 @Override 431 public void dontinline_testMethod() { 432 ABBox ab = new ABBox(); // can be scalar replaced 433 ab.aVal = 4; 434 ab.bVal = 2; 435 dontinline_endlessLoop(null); // JVMTI agent acquires reference to ab and changes bVal 436 testMethod_result = ab.aVal + ab.bVal; 437 } 438 } 439 440 /** 441 * {@link #dontinline_testMethod()} creates an ArgEscape instance of {@link TestCaseBase#taggedClass} on stack. 442 * The jvmti agent tags all instances of this class using one of the {@link TaggingAndCountingMethods}. Then it gets the tagged 443 * instances using <code>GetObjectsWithTags()</code>. This is where the ArgEscape globally escapes. 444 * It happens at a location without eliminated locking, but there is 445 * eliminated locking following, so the compiled frame must be deoptimized. This is checked by letting the agent call the 446 * synchronized method {@link ABBox#check()} on the escaped instance. 447 */ 448 public static class TestCase02a extends TestCaseBase { 449 450 public long instanceTag; 451 452 public TestCase02a(long classTag) { 453 super(classTag, ABBox.class); 454 instanceTag = classTag + 1; 455 } 456 457 public void run() { 458 try { 459 msgHL(getClass().getName() + ": test if owning frame is deoptimized if ArgEscape escapes globally"); 460 setUp(); 461 warmUp(); 462 for (TaggingAndCountingMethods m : TaggingAndCountingMethods.values()) { 463 msgHL(getClass().getName() + ": Tag and Get of ArgEscapes using " + m.name()); 464 waitingForCheck = false; 465 checkingNow = false; 466 WB.deflateIdleMonitors(); 467 WB.fullGC(); // get rid of dead instances from previous test cases 468 runTest(m); 469 } 470 } catch (Exception e) { 471 Asserts.fail("Unexpected Exception", e); 472 } 473 } 474 475 public void runTest(TaggingAndCountingMethods m) throws Exception { 476 loopCount = 1L << 62; // endless loop 477 doLoop = true; 478 Thread t1 = new Thread(() -> dontinline_testMethod(), "Target Thread (" + getClass().getName() + ")"); 479 try { 480 t1.start(); 481 try { 482 waitUntilTargetThreadHasEnteredEndlessLoop(); 483 msg("count and tag instances of " + taggedClass.getName() + " with tag " + instanceTag + " using JVMTI " + m.name()); 484 int count = countAndTagInstancesOfClass(taggedClass, classTag, instanceTag, m); 485 msg("Done. Count is " + count); 486 Asserts.assertGreaterThanOrEqual(count, 0, "countAndTagInstancesOfClass FAILED"); 487 Asserts.assertEQ(count, 1, "unexpected number of instances"); 488 } finally { 489 terminateEndlessLoop(); 490 } 491 492 ABBox[] result = new ABBox[1]; 493 msg("get instances tagged with " + instanceTag); 494 int err = getObjectsWithTag(instanceTag, result); 495 msg("Done."); 496 Asserts.assertEQ(0, err, "getObjectsWithTag FAILED"); 497 498 ABBox abBoxArgEscape = result[0]; 499 while (!waitingForCheck) { 500 Thread.yield(); 501 } 502 msg("Check abBoxArgEscape's state is consistent"); 503 checkingNow = true; 504 Asserts.assertTrue(abBoxArgEscape.check(), "Detected inconsistent state. abBoxArgEscape.aVal != abBoxArgEscape.bVal"); 505 msg("Ok."); 506 } finally { 507 checkingNow = true; 508 t1.join(); 509 } 510 } 511 512 @Override 513 public void dontinline_testMethod() { 514 ABBox ab = new ABBox(this); 515 dontinline_endlessLoop(ab); 516 ab.synchronizedSlowInc(); 517 } 518 } 519 520 /** 521 * Like {@link TestCase02a}, with the exception that at the location in {@link #dontinline_testMethod()} where the 522 * ArgEscape escapes it is not referenced by a local variable. 523 */ 524 public static class TestCase02b extends TestCaseBase { 525 526 public long instanceTag; 527 528 public TestCase02b(long classTag) { 529 super(classTag, ABBox.class); 530 instanceTag = classTag + 1; 531 } 532 533 public void run() { 534 try { 535 msgHL(getClass().getName() + ": test if owning frame is deoptimized if ArgEscape escapes globally"); 536 setUp(); 537 warmUp(); 538 for (TaggingAndCountingMethods m : TaggingAndCountingMethods.values()) { 539 msgHL(getClass().getName() + ": Tag and Get of ArgEscapes using " + m.name()); 540 waitingForCheck = false; 541 checkingNow = false; 542 WB.deflateIdleMonitors(); 543 WB.fullGC(); // get rid of dead instances from previous test cases 544 runTest(m); 545 } 546 } catch (Exception e) { 547 Asserts.fail("Unexpected Exception", e); 548 } 549 } 550 551 public void runTest(TaggingAndCountingMethods m) throws Exception { 552 loopCount = 1L << 62; // endless loop 553 doLoop = true; 554 Thread t1 = new Thread(() -> dontinline_testMethod(), "Target Thread (" + getClass().getName() + ")"); 555 try { 556 t1.start(); 557 try { 558 waitUntilTargetThreadHasEnteredEndlessLoop(); 559 msg("count and tag instances of " + taggedClass.getName() + " with tag " + instanceTag + " using JVMTI " + m.name()); 560 int count = countAndTagInstancesOfClass(taggedClass, classTag, instanceTag, m); 561 msg("Done. Count is " + count); 562 Asserts.assertGreaterThanOrEqual(count, 0, "countAndTagInstancesOfClass FAILED"); 563 Asserts.assertEQ(count, 1, "unexpected number of instances"); 564 } finally { 565 terminateEndlessLoop(); 566 } 567 568 ABBox[] result = new ABBox[1]; 569 msg("get instances tagged with " + instanceTag); 570 int err = getObjectsWithTag(instanceTag, result); 571 msg("Done."); 572 Asserts.assertEQ(0, err, "getObjectsWithTag FAILED"); 573 574 ABBox abBoxArgEscape = result[0]; 575 while (!waitingForCheck) { 576 Thread.yield(); 577 } 578 msg("Check abBoxArgEscape's state is consistent"); 579 checkingNow = true; 580 Asserts.assertTrue(abBoxArgEscape.check(), "Detected inconsistent state. abBoxArgEscape.aVal != abBoxArgEscape.bVal"); 581 msg("Ok."); 582 } finally { 583 checkingNow = true; 584 t1.join(); 585 } 586 } 587 588 @Override 589 public void dontinline_testMethod() { 590 // The new instance is an ArgEscape instance and escapes to the JVMTI agent 591 // while the target thread is in the call to dontinline_endlessLoop(). At this 592 // location there is no local variable that references the ArgEscape. 593 ((ABBox) dontinline_endlessLoop(new ABBox(this))).synchronizedSlowInc();; 594 } 595 } 596 597 public static void msg(String m) { 598 System.out.println(); 599 System.out.println("### " + m); 600 System.out.println(); 601 } 602 603 public static void msgHL(String m) { 604 System.out.println(); System.out.println(); System.out.println(); 605 System.out.println("#####################################################"); 606 System.out.println("### " + m); 607 System.out.println("###"); 608 System.out.println(); 609 } 610 }