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