1 /* 2 * Copyright (c) 2018, Red Hat, Inc. 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 * common code to run and validate tests of code generation for 26 * volatile ops on AArch64 27 * 28 * incoming args are <testclass> <testtype> 29 * 30 * where <testclass> in {TestVolatileLoad, 31 * TestVolatileStore, 32 * TestUnsafeVolatileLoad, 33 * TestUnsafeVolatileStore, 34 * TestUnsafeVolatileCAS, 35 * TestUnsafeVolatileWeakCAS, 36 * TestUnsafeVolatileCAE, 37 * TestUnsafeVolatileGAS} 38 * and <testtype> in {G1, 39 * Serial, 40 * Parallel, 41 * Shenandoah} 42 */ 43 44 45 package compiler.c2.aarch64; 46 47 import java.util.List; 48 import java.util.ListIterator; 49 import java.util.Iterator; 50 import java.util.regex.Pattern; 51 import java.io.*; 52 53 import jdk.test.lib.Asserts; 54 import jdk.test.lib.compiler.InMemoryJavaCompiler; 55 import jdk.test.lib.process.OutputAnalyzer; 56 import jdk.test.lib.process.ProcessTools; 57 import sun.hotspot.WhiteBox; 58 59 // runner class that spawns a new JVM to exercises a combination of 60 // volatile MemOp and GC. The ops are compiled with the dmb --> 61 // ldar/stlr transforms either enabled or disabled. this runner parses 62 // the PrintOptoAssembly output checking that the generated code is 63 // correct. 64 65 public class TestVolatiles { 66 public void runtest(String classname, String testType) throws Throwable { 67 // n.b. clients omit the package name for the class 68 String fullclassname = "compiler.c2.aarch64." + classname; 69 // build up a command line for the spawned JVM 70 String[] procArgs; 71 int argcount; 72 // add one or two extra arguments according to test type 73 // i.e. GC type plus GC conifg 74 switch(testType) { 75 case "G1": 76 argcount = 9; 77 procArgs = new String[argcount]; 78 procArgs[argcount - 2] = "-XX:+UseG1GC"; 79 break; 80 case "Parallel": 81 argcount = 9; 82 procArgs = new String[argcount]; 83 procArgs[argcount - 2] = "-XX:+UseParallelGC"; 84 break; 85 case "Serial": 86 argcount = 9; 87 procArgs = new String[argcount]; 88 procArgs[argcount - 2] = "-XX:+UseSerialGC"; 89 break; 90 case "Shenandoah": 91 argcount = 10; 92 procArgs = new String[argcount]; 93 procArgs[argcount - 3] = "-XX:+UnlockExperimentalVMOptions"; 94 procArgs[argcount - 2] = "-XX:+UseShenandoahGC"; 95 break; 96 default: 97 throw new RuntimeException("unexpected test type " + testType); 98 } 99 100 // fill in arguments common to all cases 101 102 // the first round of test enables transform of barriers to 103 // use acquiring loads and releasing stores by setting arg 104 // zero appropriately. this arg is reset in the second run to 105 // disable the transform. 106 107 procArgs[0] = "-XX:-UseBarriersForVolatile"; 108 procArgs[1] = "-XX:+UseCompressedOops"; 109 110 procArgs[2] = "-XX:-TieredCompilation"; 111 procArgs[3] = "-XX:+PrintOptoAssembly"; 112 procArgs[4] = "-XX:CompileCommand=compileonly," + fullclassname + "::" + "test*"; 113 procArgs[5] = "--add-exports"; 114 procArgs[6] = "java.base/jdk.internal.misc=ALL-UNNAMED"; 115 procArgs[argcount - 1] = fullclassname; 116 117 runtest(classname, testType, false, true, procArgs); 118 // rerun the test class without the transform applied and 119 // check the alternative generation is as expected 120 121 procArgs[0] = "-XX:+UseBarriersForVolatile"; 122 runtest(classname, testType, true, true, procArgs); 123 124 if (!classname.equals("TestUnsafeVolatileGAA")) { 125 procArgs[0] = "-XX:-UseBarriersForVolatile"; 126 procArgs[1] = "-XX:-UseCompressedOops"; 127 runtest(classname, testType, false, false, procArgs); 128 129 procArgs[0] = "-XX:+UseBarriersForVolatile"; 130 runtest(classname, testType, true, false, procArgs); 131 } 132 } 133 134 135 public void runtest(String classname, String testType, boolean useBarriersForVolatile, boolean useCompressedOops, String[] procArgs) throws Throwable { 136 ProcessBuilder pb = ProcessTools.createJavaProcessBuilder(procArgs); 137 OutputAnalyzer output = new OutputAnalyzer(pb.start()); 138 139 output.stderrShouldBeEmptyIgnoreVMWarnings(); 140 output.stdoutShouldNotBeEmpty(); 141 output.shouldHaveExitValue(0); 142 143 // check the output for the correct asm sequence as 144 // appropriate to test class, test type and whether transform 145 // was applied 146 147 checkoutput(output, classname, testType, useBarriersForVolatile, useCompressedOops); 148 } 149 150 // skip through output returning a line containing the desireed 151 // substring or null 152 private String skipTo(Iterator<String> iter, String substring) 153 { 154 while (iter.hasNext()) { 155 String nextLine = iter.next(); 156 if (nextLine.matches(".*" + substring + ".*")) { 157 return nextLine; 158 } 159 } 160 return null; 161 } 162 163 // locate the start of compiler output for the desired method and 164 // then check that each expected instruction occurs in the output 165 // in the order supplied. throw an excpetion if not found. 166 // n.b. the spawned JVM's output is included in the exception 167 // message to make it easeir to identify what is missing. 168 169 private boolean checkCompile(Iterator<String> iter, String methodname, String[] expected, OutputAnalyzer output, boolean do_throw) 170 { 171 // trace call to allow eyeball check of what we are checking against 172 System.out.println("checkCompile(" + methodname + ","); 173 String sepr = " { "; 174 for (String s : expected) { 175 System.out.print(sepr); 176 System.out.print(s); 177 sepr = ",\n "; 178 } 179 System.out.println(" })"); 180 181 // look for the start of an opto assembly print block 182 String match = skipTo(iter, Pattern.quote("{method}")); 183 if (match == null) { 184 if (do_throw) { 185 throw new RuntimeException("Missing compiler output for " + methodname + "!\n\n" + output.getOutput()); 186 } 187 return false; 188 } 189 // check the compiled method name is right 190 match = skipTo(iter, Pattern.quote("- name:")); 191 if (match == null) { 192 if (do_throw) { 193 throw new RuntimeException("Missing compiled method name!\n\n" + output.getOutput()); 194 } 195 return false; 196 } 197 if (!match.contains(methodname)) { 198 if (do_throw) { 199 throw new RuntimeException("Wrong method " + match + "!\n -- expecting " + methodname + "\n\n" + output.getOutput()); 200 } 201 return false; 202 } 203 // make sure we can match each expected term in order 204 for (String s : expected) { 205 match = skipTo(iter, s); 206 if (match == null) { 207 if (do_throw) { 208 throw new RuntimeException("Missing expected output " + s + "!\n\n" + output.getOutput()); 209 } 210 return false; 211 } 212 } 213 return true; 214 } 215 216 // check for expected asm output from a volatile load 217 218 private void checkload(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable 219 { 220 Iterator<String> iter = output.asLines().listIterator(); 221 222 // we shoud see this same sequence for normal or unsafe volatile load 223 // for both int and Object fields 224 225 String[] matches; 226 227 if (!useBarriersForVolatile) { 228 matches = new String[] { 229 "ldarw", 230 "membar_acquire \\(elided\\)", 231 "ret" 232 }; 233 } else { 234 matches = new String[] { 235 "ldrw", 236 "membar_acquire", 237 "dmb ish", 238 "ret" 239 }; 240 } 241 242 checkCompile(iter, "testInt", matches, output, true); 243 244 if (!useBarriersForVolatile) { 245 matches = new String[] { 246 useCompressedOops ? "ldarw?" : "ldar", 247 "membar_acquire \\(elided\\)", 248 "ret" 249 }; 250 } else { 251 matches = new String[] { 252 useCompressedOops ? "ldrw?" : "ldr", 253 "membar_acquire", 254 "dmb ish", 255 "ret" 256 }; 257 } 258 259 checkCompile(iter, "testObj", matches, output, true); 260 261 } 262 263 // check for expected asm output from a volatile store 264 265 private void checkstore(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable 266 { 267 Iterator<String> iter = output.asLines().listIterator(); 268 269 String[] matches; 270 271 // non object stores are straightforward 272 if (!useBarriersForVolatile) { 273 // this is the sequence of instructions for all cases 274 matches = new String[] { 275 "membar_release \\(elided\\)", 276 "stlrw", 277 "membar_volatile \\(elided\\)", 278 "ret" 279 }; 280 } else { 281 // this is the alternative sequence of instructions 282 matches = new String[] { 283 "membar_release", 284 "dmb ish", 285 "strw", 286 "membar_volatile", 287 "dmb ish", 288 "ret" 289 }; 290 } 291 292 checkCompile(iter, "testInt", matches, output, true); 293 294 // object stores will be as above except for when the GC 295 // introduces barriers for card marking 296 297 if (!useBarriersForVolatile) { 298 switch (testType) { 299 default: 300 // this is the basic sequence of instructions 301 matches = new String[] { 302 "membar_release \\(elided\\)", 303 useCompressedOops ? "stlrw?" : "stlr", 304 "membar_volatile \\(elided\\)", 305 "ret" 306 }; 307 break; 308 case "G1": 309 // a card mark volatile barrier should be generated 310 // before the card mark strb 311 // 312 // following the fix for 8225776 the G1 barrier is now 313 // scheduled out of line after the membar volatile and 314 // and subsequent return 315 matches = new String[] { 316 "membar_release \\(elided\\)", 317 useCompressedOops ? "stlrw?" : "stlr", 318 "membar_volatile \\(elided\\)", 319 "ret", 320 "membar_volatile", 321 "dmb ish", 322 "strb" 323 }; 324 break; 325 case "Shenandoah": 326 // Shenandoah generates normal object graphs for 327 // volatile stores 328 matches = new String[] { 329 "membar_release \\(elided\\)", 330 useCompressedOops ? "stlrw?" : "stlr", 331 "membar_volatile \\(elided\\)", 332 "ret" 333 }; 334 break; 335 } 336 } else { 337 switch (testType) { 338 default: 339 // this is the basic sequence of instructions 340 matches = new String[] { 341 "membar_release", 342 "dmb ish", 343 useCompressedOops ? "strw?" : "str", 344 "membar_volatile", 345 "dmb ish", 346 "ret" 347 }; 348 break; 349 case "G1": 350 // a card mark volatile barrier should be generated 351 // before the card mark strb 352 // 353 // following the fix for 8225776 the G1 barrier is now 354 // scheduled out of line after the membar volatile and 355 // and subsequent return 356 matches = new String[] { 357 "membar_release", 358 "dmb ish", 359 useCompressedOops ? "strw?" : "str", 360 "membar_volatile", 361 "dmb ish", 362 "ret", 363 "membar_volatile", 364 "dmb ish", 365 "strb" 366 }; 367 break; 368 case "CMSCondMark": 369 // a card mark volatile barrier should be generated 370 // before the card mark strb from the StoreCM and the 371 // storestore barrier from the StoreCM should be elided 372 matches = new String[] { 373 "membar_release", 374 "dmb ish", 375 useCompressedOops ? "strw?" : "str", 376 "membar_volatile", 377 "dmb ish", 378 "storestore \\(elided\\)", 379 "strb", 380 "membar_volatile", 381 "dmb ish", 382 "ret" 383 }; 384 break; 385 case "CMS": 386 // a volatile card mark membar should not be generated 387 // before the card mark strb from the StoreCM and the 388 // storestore barrier from the StoreCM should be generated 389 // as "dmb ishst" 390 matches = new String[] { 391 "membar_release", 392 "dmb ish", 393 useCompressedOops ? "strw?" : "str", 394 "storestore", 395 "dmb ishst", 396 "strb", 397 "membar_volatile", 398 "dmb ish", 399 "ret" 400 }; 401 break; 402 403 case "Shenandoah": 404 // Shenandoah generates normal object graphs for 405 // volatile stores 406 matches = new String[] { 407 "membar_release", 408 "dmb ish", 409 useCompressedOops ? "strw?" : "str", 410 "membar_volatile", 411 "dmb ish", 412 "ret" 413 }; 414 break; 415 } 416 } 417 418 checkCompile(iter, "testObj", matches, output, true); 419 } 420 421 // check for expected asm output from a volatile cas 422 423 private void checkcas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable 424 { 425 Iterator<String> iter = output.asLines().listIterator(); 426 427 String[] matches; 428 String[][] tests = { 429 { "testInt", "cmpxchgw" }, 430 { "testLong", "cmpxchg" }, 431 { "testByte", "cmpxchgb" }, 432 { "testShort", "cmpxchgs" }, 433 }; 434 435 for (String[] test : tests) { 436 // non object stores are straightforward 437 if (!useBarriersForVolatile) { 438 // this is the sequence of instructions for all cases 439 matches = new String[] { 440 "membar_release \\(elided\\)", 441 test[1] + "_acq", 442 "membar_acquire \\(elided\\)", 443 "ret" 444 }; 445 } else { 446 // this is the alternative sequence of instructions 447 matches = new String[] { 448 "membar_release", 449 "dmb ish", 450 test[1] + " ", 451 "membar_acquire", 452 "dmb ish", 453 "ret" 454 }; 455 } 456 457 checkCompile(iter, test[0], matches, output, true); 458 } 459 460 // object stores will be as above except for when the GC 461 // introduces barriers for card marking 462 463 if (!useBarriersForVolatile) { 464 switch (testType) { 465 default: 466 // this is the basic sequence of instructions 467 matches = new String[] { 468 "membar_release \\(elided\\)", 469 useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", 470 "strb", 471 "membar_acquire \\(elided\\)", 472 "ret" 473 }; 474 break; 475 case "G1": 476 // a card mark volatile barrier should be generated 477 // before the card mark strb 478 // 479 // following the fix for 8225776 the G1 barrier is now 480 // scheduled out of line after the membar acquire and 481 // and subsequent return 482 matches = new String[] { 483 "membar_release \\(elided\\)", 484 useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", 485 "membar_acquire \\(elided\\)", 486 "ret", 487 "membar_volatile", 488 "dmb ish", 489 "strb" 490 }; 491 break; 492 case "Shenandoah": 493 // For volatile CAS, Shenanodoah generates normal 494 // graphs with a shenandoah-specific cmpxchg 495 matches = new String[] { 496 "membar_release \\(elided\\)", 497 useCompressedOops ? "cmpxchgw?_acq_shenandoah" : "cmpxchg_acq_shenandoah", 498 "membar_acquire \\(elided\\)", 499 "ret" 500 }; 501 break; 502 } 503 } else { 504 switch (testType) { 505 default: 506 // this is the basic sequence of instructions 507 matches = new String[] { 508 "membar_release", 509 "dmb ish", 510 useCompressedOops ? "cmpxchgw? " : "cmpxchg ", 511 "membar_acquire", 512 "dmb ish", 513 "ret" 514 }; 515 break; 516 case "G1": 517 // a card mark volatile barrier should be generated 518 // before the card mark strb 519 // 520 // following the fix for 8225776 the G1 barrier is now 521 // scheduled out of line after the membar acquire and 522 // and subsequent return 523 matches = new String[] { 524 "membar_release", 525 "dmb ish", 526 useCompressedOops ? "cmpxchgw? " : "cmpxchg ", 527 "membar_acquire", 528 "dmb ish", 529 "ret", 530 "membar_volatile", 531 "dmb ish", 532 "strb" 533 }; 534 break; 535 case "CMSCondMark": 536 // a card mark volatile barrier should be generated 537 // before the card mark strb from the StoreCM and the 538 // storestore barrier from the StoreCM should be elided 539 matches = new String[] { 540 "membar_release", 541 "dmb ish", 542 useCompressedOops ? "cmpxchgw? " : "cmpxchg ", 543 "membar_volatile", 544 "dmb ish", 545 "storestore \\(elided\\)", 546 "strb", 547 "membar_acquire", 548 "dmb ish", 549 "ret" 550 }; 551 break; 552 case "CMS": 553 // a volatile card mark membar should not be generated 554 // before the card mark strb from the StoreCM and the 555 // storestore barrier from the StoreCM should be generated 556 // as "dmb ishst" 557 matches = new String[] { 558 "membar_release", 559 "dmb ish", 560 useCompressedOops ? "cmpxchgw? " : "cmpxchg ", 561 "storestore", 562 "dmb ishst", 563 "strb", 564 "membar_acquire", 565 "dmb ish", 566 "ret" 567 }; 568 break; 569 case "Shenandoah": 570 // For volatile CAS, Shenanodoah generates normal 571 // graphs with a shenandoah-specific cmpxchg 572 matches = new String[] { 573 "membar_release", 574 "dmb ish", 575 useCompressedOops ? "cmpxchgw?_shenandoah" : "cmpxchg_shenandoah", 576 "membar_acquire", 577 "dmb ish", 578 "ret" 579 }; 580 break; 581 } 582 } 583 584 checkCompile(iter, "testObj", matches, output, true); 585 } 586 587 private void checkcae(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable 588 { 589 ListIterator<String> iter = output.asLines().listIterator(); 590 591 String[] matches; 592 String[][] tests = { 593 { "testInt", "cmpxchgw" }, 594 { "testLong", "cmpxchg" }, 595 { "testByte", "cmpxchgb" }, 596 { "testShort", "cmpxchgs" }, 597 }; 598 599 for (String[] test : tests) { 600 // non object stores are straightforward 601 if (!useBarriersForVolatile) { 602 // this is the sequence of instructions for all cases 603 matches = new String[] { 604 "membar_release \\(elided\\)", 605 test[1] + "_acq", 606 "membar_acquire \\(elided\\)", 607 "ret" 608 }; 609 } else { 610 // this is the alternative sequence of instructions 611 matches = new String[] { 612 "membar_release", 613 "dmb ish", 614 test[1] + " ", 615 "membar_acquire", 616 "dmb ish", 617 "ret" 618 }; 619 } 620 621 checkCompile(iter, test[0], matches, output, true); 622 } 623 624 // object stores will be as above except for when the GC 625 // introduces barriers for card marking 626 627 if (!useBarriersForVolatile) { 628 switch (testType) { 629 default: 630 // this is the basic sequence of instructions 631 matches = new String[] { 632 "membar_release \\(elided\\)", 633 "strb", 634 useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", 635 "membar_acquire \\(elided\\)", 636 "ret" 637 }; 638 639 // card marking store may be scheduled before or after 640 // the cmpxchg so try both sequences. 641 int idx = iter.nextIndex(); 642 if (!checkCompile(iter, "testObj", matches, output, false)) { 643 iter = output.asLines().listIterator(idx); 644 645 matches = new String[] { 646 "membar_release \\(elided\\)", 647 useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", 648 "strb", 649 "membar_acquire \\(elided\\)", 650 "ret" 651 }; 652 653 checkCompile(iter, "testObj", matches, output, true); 654 } 655 return; 656 657 case "G1": 658 // a card mark volatile barrier should be generated 659 // before the card mark strb 660 // 661 // following the fix for 8225776 the G1 barrier is now 662 // scheduled out of line after the membar acquire and 663 // and subsequent return 664 matches = new String[] { 665 "membar_release \\(elided\\)", 666 useCompressedOops ? "cmpxchgw?_acq" : "cmpxchg_acq", 667 "membar_acquire \\(elided\\)", 668 "ret", 669 "membar_volatile", 670 "dmb ish", 671 "strb" 672 }; 673 break; 674 case "Shenandoah": 675 // For volatile CAS, Shenanodoah generates normal 676 // graphs with a shenandoah-specific cmpxchg 677 matches = new String[] { 678 "membar_release \\(elided\\)", 679 useCompressedOops ? "cmpxchgw?_acq_shenandoah" : "cmpxchg_acq_shenandoah", 680 "membar_acquire \\(elided\\)", 681 "ret" 682 }; 683 break; 684 } 685 } else { 686 switch (testType) { 687 default: 688 // this is the basic sequence of instructions 689 matches = new String[] { 690 "membar_release", 691 "dmb ish", 692 useCompressedOops ? "cmpxchgw? " : "cmpxchg ", 693 "membar_acquire", 694 "dmb ish", 695 "ret" 696 }; 697 break; 698 case "G1": 699 // a card mark volatile barrier should be generated 700 // before the card mark strb 701 // 702 // following the fix for 8225776 the G1 barrier is now 703 // scheduled out of line after the membar acquire and 704 // and subsequent return 705 matches = new String[] { 706 "membar_release", 707 "dmb ish", 708 useCompressedOops ? "cmpxchgw? " : "cmpxchg ", 709 "membar_acquire", 710 "dmb ish", 711 "ret", 712 "membar_volatile", 713 "dmb ish", 714 "strb" 715 }; 716 break; 717 case "CMSCondMark": 718 // a card mark volatile barrier should be generated 719 // before the card mark strb from the StoreCM and the 720 // storestore barrier from the StoreCM should be elided 721 matches = new String[] { 722 "membar_release", 723 "dmb ish", 724 useCompressedOops ? "cmpxchgw? " : "cmpxchg ", 725 "membar_volatile", 726 "dmb ish", 727 "storestore \\(elided\\)", 728 "strb", 729 "membar_acquire", 730 "dmb ish", 731 "ret" 732 }; 733 break; 734 case "CMS": 735 // a volatile card mark membar should not be generated 736 // before the card mark strb from the StoreCM and the 737 // storestore barrier from the StoreCM should be generated 738 // as "dmb ishst" 739 matches = new String[] { 740 "membar_release", 741 "dmb ish", 742 useCompressedOops ? "cmpxchgw? " : "cmpxchg ", 743 "storestore", 744 "dmb ishst", 745 "strb", 746 "membar_acquire", 747 "dmb ish", 748 "ret" 749 }; 750 break; 751 case "Shenandoah": 752 // For volatile CAS, Shenanodoah generates normal 753 // graphs with a shenandoah-specific cmpxchg 754 matches = new String[] { 755 "membar_release", 756 "dmb ish", 757 useCompressedOops ? "cmpxchgw?_shenandoah" : "cmpxchg_shenandoah", 758 "membar_acquire", 759 "dmb ish", 760 "ret" 761 }; 762 break; 763 } 764 } 765 766 checkCompile(iter, "testObj", matches, output, true); 767 } 768 769 private void checkgas(OutputAnalyzer output, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable 770 { 771 Iterator<String> iter = output.asLines().listIterator(); 772 773 String[] matches; 774 String[][] tests = { 775 { "testInt", "atomic_xchgw" }, 776 { "testLong", "atomic_xchg" }, 777 }; 778 779 for (String[] test : tests) { 780 // non object stores are straightforward 781 if (!useBarriersForVolatile) { 782 // this is the sequence of instructions for all cases 783 matches = new String[] { 784 "membar_release \\(elided\\)", 785 test[1] + "_acq", 786 "membar_acquire \\(elided\\)", 787 "ret" 788 }; 789 } else { 790 // this is the alternative sequence of instructions 791 matches = new String[] { 792 "membar_release", 793 "dmb ish", 794 test[1] + " ", 795 "membar_acquire", 796 "dmb ish", 797 "ret" 798 }; 799 } 800 801 checkCompile(iter, test[0], matches, output, true); 802 } 803 804 // object stores will be as above except for when the GC 805 // introduces barriers for card marking 806 807 if (!useBarriersForVolatile) { 808 switch (testType) { 809 default: 810 // this is the basic sequence of instructions 811 matches = new String[] { 812 "membar_release \\(elided\\)", 813 useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", 814 "strb", 815 "membar_acquire \\(elided\\)", 816 "ret" 817 }; 818 break; 819 case "G1": 820 // a card mark volatile barrier should be generated 821 // before the card mark strb 822 // 823 // following the fix for 8225776 the G1 barrier is now 824 // scheduled out of line after the membar acquire and 825 // and subsequent return 826 matches = new String[] { 827 "membar_release \\(elided\\)", 828 useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", 829 "membar_acquire \\(elided\\)", 830 "ret", 831 "membar_volatile", 832 "dmb ish", 833 "strb" 834 }; 835 break; 836 case "Shenandoah": 837 matches = new String[] { 838 "membar_release \\(elided\\)", 839 useCompressedOops ? "atomic_xchgw?_acq" : "atomic_xchg_acq", 840 "membar_acquire \\(elided\\)", 841 "ret" 842 }; 843 break; 844 } 845 } else { 846 switch (testType) { 847 default: 848 // this is the basic sequence of instructions 849 matches = new String[] { 850 "membar_release", 851 "dmb ish", 852 useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", 853 "membar_acquire", 854 "dmb ish", 855 "ret" 856 }; 857 break; 858 case "G1": 859 // a card mark volatile barrier should be generated 860 // before the card mark strb 861 // 862 // following the fix for 8225776 the G1 barrier is now 863 // scheduled out of line after the membar acquire and 864 // and subsequent return 865 matches = new String[] { 866 "membar_release", 867 "dmb ish", 868 useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", 869 "membar_acquire", 870 "dmb ish", 871 "ret", 872 "membar_volatile", 873 "dmb ish", 874 "strb" 875 }; 876 break; 877 case "CMSCondMark": 878 // a card mark volatile barrier should be generated 879 // before the card mark strb from the StoreCM and the 880 // storestore barrier from the StoreCM should be elided 881 matches = new String[] { 882 "membar_release", 883 "dmb ish", 884 useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", 885 "membar_volatile", 886 "dmb ish", 887 "storestore \\(elided\\)", 888 "strb", 889 "membar_acquire", 890 "dmb ish", 891 "ret" 892 }; 893 break; 894 case "CMS": 895 // a volatile card mark membar should not be generated 896 // before the card mark strb from the StoreCM and the 897 // storestore barrier from the StoreCM should be generated 898 // as "dmb ishst" 899 matches = new String[] { 900 "membar_release", 901 "dmb ish", 902 useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", 903 "storestore", 904 "dmb ishst", 905 "strb", 906 "membar_acquire", 907 "dmb ish", 908 "ret" 909 }; 910 break; 911 case "Shenandoah": 912 matches = new String[] { 913 "membar_release", 914 "dmb ish", 915 useCompressedOops ? "atomic_xchgw? " : "atomic_xchg ", 916 "membar_acquire", 917 "dmb ish", 918 "ret" 919 }; 920 break; 921 } 922 } 923 924 checkCompile(iter, "testObj", matches, output, true); 925 } 926 927 private void checkgaa(OutputAnalyzer output, String testType, boolean useBarriersForVolatile) throws Throwable 928 { 929 Iterator<String> iter = output.asLines().listIterator(); 930 931 String[] matches; 932 String[][] tests = { 933 { "testInt", "get_and_addI" }, 934 { "testLong", "get_and_addL" }, 935 }; 936 937 for (String[] test : tests) { 938 // non object stores are straightforward 939 if (!useBarriersForVolatile) { 940 // this is the sequence of instructions for all cases 941 matches = new String[] { 942 "membar_release \\(elided\\)", 943 test[1] + "_acq", 944 "membar_acquire \\(elided\\)", 945 "ret" 946 }; 947 } else { 948 // this is the alternative sequence of instructions 949 matches = new String[] { 950 "membar_release", 951 "dmb ish", 952 test[1] + " ", 953 "membar_acquire", 954 "dmb ish", 955 "ret" 956 }; 957 } 958 959 checkCompile(iter, test[0], matches, output, true); 960 } 961 962 } 963 964 // perform a check appropriate to the classname 965 966 private void checkoutput(OutputAnalyzer output, String classname, String testType, boolean useBarriersForVolatile, boolean useCompressedOops) throws Throwable 967 { 968 // trace call to allow eyeball check of what is being checked 969 System.out.println("checkoutput(" + 970 classname + ", " + 971 testType + ", " + 972 useBarriersForVolatile + ")\n" + 973 output.getOutput()); 974 975 switch (classname) { 976 case "TestVolatileLoad": 977 checkload(output, testType, useBarriersForVolatile, useCompressedOops); 978 break; 979 case "TestVolatileStore": 980 checkstore(output, testType, useBarriersForVolatile, useCompressedOops); 981 break; 982 case "TestUnsafeVolatileLoad": 983 checkload(output, testType, useBarriersForVolatile, useCompressedOops); 984 break; 985 case "TestUnsafeVolatileStore": 986 checkstore(output, testType, useBarriersForVolatile, useCompressedOops); 987 break; 988 case "TestUnsafeVolatileCAS": 989 case "TestUnsafeVolatileWeakCAS": 990 checkcas(output, testType, useBarriersForVolatile, useCompressedOops); 991 break; 992 case "TestUnsafeVolatileCAE": 993 checkcae(output, testType, useBarriersForVolatile, useCompressedOops); 994 break; 995 case "TestUnsafeVolatileGAS": 996 checkgas(output, testType, useBarriersForVolatile, useCompressedOops); 997 break; 998 case "TestUnsafeVolatileGAA": 999 checkgaa(output, testType, useBarriersForVolatile); 1000 break; 1001 } 1002 } 1003 }