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