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