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