1 /* 2 * Copyright (c) 2024, 2025, Oracle and/or its affiliates. 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 package compiler.gcbarriers; 25 26 import compiler.lib.ir_framework.*; 27 import java.lang.invoke.VarHandle; 28 import java.lang.invoke.MethodHandles; 29 import java.lang.ref.Reference; 30 import java.lang.ref.ReferenceQueue; 31 import java.lang.ref.SoftReference; 32 import java.lang.ref.WeakReference; 33 import java.util.concurrent.ThreadLocalRandom; 34 import jdk.test.lib.Asserts; 35 36 /** 37 * @test 38 * @summary Test that G1 barriers are generated and optimized as expected. 39 * @library /test/lib / 40 * @requires vm.gc.G1 41 * @run driver compiler.gcbarriers.TestG1BarrierGeneration 42 */ 43 44 public class TestG1BarrierGeneration { 45 static final String PRE_ONLY = "pre"; 46 static final String POST_ONLY = "post"; 47 static final String POST_ONLY_NOT_NULL = "post notnull"; 48 static final String PRE_AND_POST = "pre post"; 49 static final String PRE_AND_POST_NOT_NULL = "pre post notnull"; 50 static final String ANY = ".*"; 51 52 static class Outer { 53 Object f; 54 } 55 56 static class OuterWithVolatileField { 57 volatile Object f; 58 } 59 60 static class OuterWithFewFields implements Cloneable { 61 Object f1; 62 Object f2; 63 public Object clone() throws CloneNotSupportedException { 64 return super.clone(); 65 } 66 } 67 68 static class OuterWithManyFields implements Cloneable { 69 Object f1; 70 Object f2; 71 Object f3; 72 Object f4; 73 Object f5; 74 Object f6; 75 Object f7; 76 Object f8; 77 Object f9; 78 Object f10; 79 public Object clone() throws CloneNotSupportedException { 80 return super.clone(); 81 } 82 } 83 84 static final VarHandle fVarHandle; 85 static { 86 MethodHandles.Lookup l = MethodHandles.lookup(); 87 try { 88 fVarHandle = l.findVarHandle(Outer.class, "f", Object.class); 89 } catch (Exception e) { 90 throw new Error(e); 91 } 92 } 93 94 @DontInline 95 static void nonInlinedMethod() {} 96 97 public static void main(String[] args) { 98 TestFramework framework = new TestFramework(); 99 Scenario[] scenarios = new Scenario[2*2]; 100 int scenarioIndex = 0; 101 for (int i = 0; i < 2; i++) { 102 for (int j = 0; j < 2; j++) { 103 scenarios[scenarioIndex] = 104 new Scenario(scenarioIndex, 105 "-XX:CompileCommand=inline,java.lang.ref.*::*", 106 "-XX:" + (i == 0 ? "-" : "+") + "UseCompressedOops", 107 "-XX:" + (j == 0 ? "-" : "+") + "ReduceInitialCardMarks"); 108 scenarioIndex++; 109 } 110 } 111 framework.addScenarios(scenarios); 112 framework.start(); 113 } 114 115 @Test 116 @IR(applyIf = {"UseCompressedOops", "false"}, 117 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 118 phase = CompilePhase.FINAL_CODE) 119 @IR(applyIf = {"UseCompressedOops", "true"}, 120 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 121 phase = CompilePhase.FINAL_CODE) 122 public static void testStore(Outer o, Object o1) { 123 o.f = o1; 124 } 125 126 @Test 127 @IR(applyIf = {"UseCompressedOops", "false"}, 128 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"}, 129 phase = CompilePhase.FINAL_CODE) 130 @IR(applyIf = {"UseCompressedOops", "true"}, 131 counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"}, 132 phase = CompilePhase.FINAL_CODE) 133 public static void testStoreNull(Outer o) { 134 o.f = null; 135 } 136 137 @Test 138 @IR(applyIf = {"UseCompressedOops", "false"}, 139 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"}, 140 phase = CompilePhase.FINAL_CODE) 141 @IR(applyIf = {"UseCompressedOops", "true"}, 142 counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"}, 143 phase = CompilePhase.FINAL_CODE) 144 public static void testStoreObfuscatedNull(Outer o, Object o1) { 145 Object o2 = o1; 146 for (int i = 0; i < 4; i++) { 147 if ((i % 2) == 0) { 148 o2 = null; 149 } 150 } 151 // o2 is null here, but this is only known to C2 after applying some 152 // optimizations (loop unrolling, IGVN). 153 o.f = o2; 154 } 155 156 @Test 157 @IR(applyIf = {"UseCompressedOops", "false"}, 158 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"}, 159 phase = CompilePhase.FINAL_CODE) 160 @IR(applyIf = {"UseCompressedOops", "true"}, 161 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"}, 162 phase = CompilePhase.FINAL_CODE) 163 public static void testStoreNotNull(Outer o, Object o1) { 164 if (o1.hashCode() == 42) { 165 return; 166 } 167 o.f = o1; 168 } 169 170 @Test 171 @IR(applyIf = {"UseCompressedOops", "false"}, 172 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "2"}, 173 phase = CompilePhase.FINAL_CODE) 174 @IR(applyIf = {"UseCompressedOops", "true"}, 175 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "2"}, 176 phase = CompilePhase.FINAL_CODE) 177 public static void testStoreTwice(Outer o, Outer p, Object o1) { 178 o.f = o1; 179 p.f = o1; 180 } 181 182 @Test 183 @IR(applyIf = {"UseCompressedOops", "false"}, 184 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 185 phase = CompilePhase.FINAL_CODE) 186 @IR(applyIf = {"UseCompressedOops", "true"}, 187 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 188 phase = CompilePhase.FINAL_CODE) 189 public static void testStoreVolatile(OuterWithVolatileField o, Object o1) { 190 o.f = o1; 191 } 192 193 @Test 194 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 195 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 196 phase = CompilePhase.FINAL_CODE) 197 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 198 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 199 phase = CompilePhase.FINAL_CODE) 200 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 201 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY}, 202 phase = CompilePhase.FINAL_CODE) 203 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 204 failOn = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY, 205 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY}, 206 phase = CompilePhase.FINAL_CODE) 207 public static Outer testStoreOnNewObject(Object o1) { 208 Outer o = new Outer(); 209 o.f = o1; 210 return o; 211 } 212 213 @Test 214 @IR(failOn = {IRNode.STORE_P, IRNode.STORE_N}, 215 phase = CompilePhase.BEFORE_MACRO_EXPANSION) 216 public static Outer testStoreNullOnNewObject() { 217 Outer o = new Outer(); 218 o.f = null; 219 return o; 220 } 221 222 @Test 223 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 224 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY_NOT_NULL, "1"}, 225 phase = CompilePhase.FINAL_CODE) 226 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 227 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY_NOT_NULL, "1"}, 228 phase = CompilePhase.FINAL_CODE) 229 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 230 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY}, 231 phase = CompilePhase.FINAL_CODE) 232 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 233 failOn = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY, 234 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY}, 235 phase = CompilePhase.FINAL_CODE) 236 public static Outer testStoreNotNullOnNewObject(Object o1) { 237 if (o1.hashCode() == 42) { 238 return null; 239 } 240 Outer o = new Outer(); 241 o.f = o1; 242 return o; 243 } 244 245 @Test 246 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 247 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "2"}, 248 phase = CompilePhase.FINAL_CODE) 249 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 250 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "2"}, 251 phase = CompilePhase.FINAL_CODE) 252 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 253 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY}, 254 phase = CompilePhase.FINAL_CODE) 255 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 256 failOn = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY, 257 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY}, 258 phase = CompilePhase.FINAL_CODE) 259 public static Outer testStoreOnNewObjectInTwoPaths(Object o1, boolean c) { 260 Outer o; 261 if (c) { 262 o = new Outer(); 263 o.f = o1; 264 } else { 265 o = new Outer(); 266 o.f = o1; 267 } 268 return o; 269 } 270 271 @Test 272 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 273 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 274 phase = CompilePhase.FINAL_CODE) 275 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 276 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 277 phase = CompilePhase.FINAL_CODE) 278 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 279 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY}, 280 phase = CompilePhase.FINAL_CODE) 281 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 282 failOn = {IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY}, 283 phase = CompilePhase.FINAL_CODE) 284 public static Outer testStoreConditionallyOnNewObject(Object o1, boolean c) { 285 Outer o = new Outer(); 286 if (c) { 287 o.f = o1; 288 } 289 return o; 290 } 291 292 @Test 293 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 294 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 295 phase = CompilePhase.FINAL_CODE) 296 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 297 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 298 phase = CompilePhase.FINAL_CODE) 299 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 300 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY}, 301 phase = CompilePhase.FINAL_CODE) 302 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 303 failOn = {IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY}, 304 phase = CompilePhase.FINAL_CODE) 305 public static Outer testStoreOnNewObjectAfterException(Object o1, boolean c) throws Exception { 306 Outer o = new Outer(); 307 if (c) { 308 throw new Exception(""); 309 } 310 o.f = o1; 311 return o; 312 } 313 314 @Test 315 @IR(applyIf = {"UseCompressedOops", "false"}, 316 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 317 phase = CompilePhase.FINAL_CODE) 318 @IR(applyIf = {"UseCompressedOops", "true"}, 319 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 320 phase = CompilePhase.FINAL_CODE) 321 public static Outer testStoreOnNewObjectAfterCall(Object o1) { 322 Outer o = new Outer(); 323 nonInlinedMethod(); 324 o.f = o1; 325 return o; 326 } 327 328 @Run(test = {"testStore", 329 "testStoreNull", 330 "testStoreObfuscatedNull", 331 "testStoreNotNull", 332 "testStoreTwice", 333 "testStoreVolatile", 334 "testStoreOnNewObject", 335 "testStoreNullOnNewObject", 336 "testStoreNotNullOnNewObject", 337 "testStoreOnNewObjectInTwoPaths", 338 "testStoreConditionallyOnNewObject", 339 "testStoreOnNewObjectAfterException", 340 "testStoreOnNewObjectAfterCall"}) 341 public void runStoreTests() { 342 { 343 Outer o = new Outer(); 344 Object o1 = new Object(); 345 testStore(o, o1); 346 Asserts.assertEquals(o1, o.f); 347 } 348 { 349 Outer o = new Outer(); 350 testStoreNull(o); 351 Asserts.assertNull(o.f); 352 } 353 { 354 Outer o = new Outer(); 355 Object o1 = new Object(); 356 testStoreObfuscatedNull(o, o1); 357 Asserts.assertNull(o.f); 358 } 359 { 360 Outer o = new Outer(); 361 Object o1 = new Object(); 362 testStoreNotNull(o, o1); 363 Asserts.assertEquals(o1, o.f); 364 } 365 { 366 Outer o = new Outer(); 367 Outer p = new Outer(); 368 Object o1 = new Object(); 369 testStoreTwice(o, p, o1); 370 Asserts.assertEquals(o1, o.f); 371 Asserts.assertEquals(o1, p.f); 372 } 373 { 374 OuterWithVolatileField o = new OuterWithVolatileField(); 375 Object o1 = new Object(); 376 testStoreVolatile(o, o1); 377 Asserts.assertEquals(o1, o.f); 378 } 379 { 380 Object o1 = new Object(); 381 Outer o = testStoreOnNewObject(o1); 382 Asserts.assertEquals(o1, o.f); 383 } 384 { 385 Outer o = testStoreNullOnNewObject(); 386 Asserts.assertNull(o.f); 387 } 388 { 389 Object o1 = new Object(); 390 Outer o = testStoreNotNullOnNewObject(o1); 391 Asserts.assertEquals(o1, o.f); 392 } 393 { 394 Object o1 = new Object(); 395 Outer o = testStoreOnNewObjectInTwoPaths(o1, ThreadLocalRandom.current().nextBoolean()); 396 Asserts.assertEquals(o1, o.f); 397 } 398 { 399 Object o1 = new Object(); 400 boolean c = ThreadLocalRandom.current().nextBoolean(); 401 Outer o = testStoreConditionallyOnNewObject(o1, c); 402 Asserts.assertTrue(o.f == (c ? o1 : null)); 403 } 404 { 405 Object o1 = new Object(); 406 boolean c = ThreadLocalRandom.current().nextBoolean(); 407 try { 408 Outer o = testStoreOnNewObjectAfterException(o1, c); 409 } catch (Exception e) {} 410 } 411 { 412 Object o1 = new Object(); 413 Outer o = testStoreOnNewObjectAfterCall(o1); 414 Asserts.assertEquals(o1, o.f); 415 } 416 } 417 418 @Test 419 @IR(applyIf = {"UseCompressedOops", "false"}, 420 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 421 phase = CompilePhase.FINAL_CODE) 422 @IR(applyIf = {"UseCompressedOops", "true"}, 423 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 424 phase = CompilePhase.FINAL_CODE) 425 public static void testArrayStore(Object[] a, int index, Object o1) { 426 a[index] = o1; 427 } 428 429 @Test 430 @IR(applyIf = {"UseCompressedOops", "false"}, 431 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"}, 432 phase = CompilePhase.FINAL_CODE) 433 @IR(applyIf = {"UseCompressedOops", "true"}, 434 counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"}, 435 phase = CompilePhase.FINAL_CODE) 436 public static void testArrayStoreNull(Object[] a, int index) { 437 a[index] = null; 438 } 439 440 @Test 441 @IR(applyIf = {"UseCompressedOops", "false"}, 442 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"}, 443 phase = CompilePhase.FINAL_CODE) 444 @IR(applyIf = {"UseCompressedOops", "true"}, 445 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"}, 446 phase = CompilePhase.FINAL_CODE) 447 public static void testArrayStoreNotNull(Object[] a, int index, Object o1) { 448 if (o1.hashCode() == 42) { 449 return; 450 } 451 a[index] = o1; 452 } 453 454 @Test 455 @IR(applyIf = {"UseCompressedOops", "false"}, 456 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "2"}, 457 phase = CompilePhase.FINAL_CODE) 458 @IR(applyIf = {"UseCompressedOops", "true"}, 459 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "2"}, 460 phase = CompilePhase.FINAL_CODE) 461 public static void testArrayStoreTwice(Object[] a, Object[] b, int index, Object o1) { 462 a[index] = o1; 463 b[index] = o1; 464 } 465 466 @Test 467 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 468 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 469 phase = CompilePhase.FINAL_CODE) 470 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 471 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 472 phase = CompilePhase.FINAL_CODE) 473 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 474 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY}, 475 phase = CompilePhase.FINAL_CODE) 476 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 477 failOn = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY, 478 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY}, 479 phase = CompilePhase.FINAL_CODE) 480 public static Object[] testStoreOnNewArrayAtKnownIndex(Object o1) { 481 Object[] a = new Object[10]; 482 a[4] = o1; 483 return a; 484 } 485 486 @Test 487 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 488 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 489 phase = CompilePhase.FINAL_CODE) 490 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 491 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 492 phase = CompilePhase.FINAL_CODE) 493 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 494 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY}, 495 phase = CompilePhase.FINAL_CODE) 496 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 497 failOn = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY, 498 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY}, 499 phase = CompilePhase.FINAL_CODE) 500 public static Object[] testStoreOnNewArrayAtUnknownIndex(Object o1, int index) { 501 Object[] a = new Object[10]; 502 a[index] = o1; 503 return a; 504 } 505 506 @Test 507 @IR(failOn = IRNode.SAFEPOINT) 508 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 509 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 510 phase = CompilePhase.FINAL_CODE) 511 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 512 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 513 phase = CompilePhase.FINAL_CODE) 514 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 515 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY}, 516 phase = CompilePhase.FINAL_CODE) 517 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 518 failOn = {IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY}, 519 phase = CompilePhase.FINAL_CODE) 520 public static Object[] testStoreAllOnNewSmallArray(Object o1) { 521 Object[] a = new Object[64]; 522 for (int i = 0; i < a.length; i++) { 523 a[i] = o1; 524 } 525 return a; 526 } 527 528 @Test 529 @IR(counts = {IRNode.SAFEPOINT, "1"}) 530 @IR(applyIf = {"UseCompressedOops", "false"}, 531 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 532 phase = CompilePhase.FINAL_CODE) 533 @IR(applyIf = {"UseCompressedOops", "true"}, 534 counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 535 phase = CompilePhase.FINAL_CODE) 536 public static Object[] testStoreAllOnNewLargeArray(Object o1) { 537 Object[] a = new Object[1024]; 538 for (int i = 0; i < a.length; i++) { 539 a[i] = o1; 540 } 541 return a; 542 } 543 544 @Run(test = {"testArrayStore", 545 "testArrayStoreNull", 546 "testArrayStoreNotNull", 547 "testArrayStoreTwice", 548 "testStoreOnNewArrayAtKnownIndex", 549 "testStoreOnNewArrayAtUnknownIndex", 550 "testStoreAllOnNewSmallArray", 551 "testStoreAllOnNewLargeArray"}) 552 @Warmup(5000) 553 public void runArrayStoreTests() { 554 { 555 Object[] a = new Object[10]; 556 Object o1 = new Object(); 557 testArrayStore(a, 4, o1); 558 Asserts.assertEquals(o1, a[4]); 559 } 560 { 561 Object[] a = new Object[10]; 562 testArrayStoreNull(a, 4); 563 Asserts.assertNull(a[4]); 564 } 565 { 566 Object[] a = new Object[10]; 567 Object o1 = new Object(); 568 testArrayStoreNotNull(a, 4, o1); 569 Asserts.assertEquals(o1, a[4]); 570 } 571 { 572 Object[] a = new Object[10]; 573 Object[] b = new Object[10]; 574 Object o1 = new Object(); 575 testArrayStoreTwice(a, b, 4, o1); 576 Asserts.assertEquals(o1, a[4]); 577 Asserts.assertEquals(o1, b[4]); 578 } 579 { 580 Object o1 = new Object(); 581 Object[] a = testStoreOnNewArrayAtKnownIndex(o1); 582 Asserts.assertEquals(o1, a[4]); 583 } 584 { 585 Object o1 = new Object(); 586 Object[] a = testStoreOnNewArrayAtUnknownIndex(o1, 5); 587 Asserts.assertEquals(o1, a[5]); 588 } 589 { 590 Object o1 = new Object(); 591 Object[] a = testStoreAllOnNewSmallArray(o1); 592 for (int i = 0; i < a.length; i++) { 593 Asserts.assertEquals(o1, a[i]); 594 } 595 } 596 { 597 Object o1 = new Object(); 598 Object[] a = testStoreAllOnNewLargeArray(o1); 599 for (int i = 0; i < a.length; i++) { 600 Asserts.assertEquals(o1, a[i]); 601 } 602 } 603 } 604 605 @Test 606 public static Object[] testCloneArrayOfObjects(Object[] a) { 607 Object[] a1 = null; 608 try { 609 a1 = a.clone(); 610 } catch (Exception e) {} 611 return a1; 612 } 613 614 @Test 615 @IR(applyIf = {"ReduceInitialCardMarks", "true"}, 616 failOn = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, ANY, 617 IRNode.G1_STORE_N_WITH_BARRIER_FLAG, ANY, 618 IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, ANY}, 619 phase = CompilePhase.FINAL_CODE) 620 @IR(applyIfAnd = {"ReduceInitialCardMarks", "false", "UseCompressedOops", "false"}, 621 counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "2"}, 622 phase = CompilePhase.FINAL_CODE) 623 @IR(applyIfAnd = {"ReduceInitialCardMarks", "false", "UseCompressedOops", "true"}, 624 counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "2"}, 625 phase = CompilePhase.FINAL_CODE) 626 public static OuterWithFewFields testCloneObjectWithFewFields(OuterWithFewFields o) { 627 Object o1 = null; 628 try { 629 o1 = o.clone(); 630 } catch (Exception e) {} 631 return (OuterWithFewFields)o1; 632 } 633 634 @Test 635 @IR(applyIf = {"ReduceInitialCardMarks", "true"}, 636 counts = {IRNode.CALL_OF, "jlong_disjoint_arraycopy", "1"}) 637 @IR(applyIf = {"ReduceInitialCardMarks", "false"}, 638 counts = {IRNode.CALL_OF, "G1BarrierSetRuntime::clone", "1"}) 639 public static OuterWithManyFields testCloneObjectWithManyFields(OuterWithManyFields o) { 640 Object o1 = null; 641 try { 642 o1 = o.clone(); 643 } catch (Exception e) {} 644 return (OuterWithManyFields)o1; 645 } 646 647 @Run(test = {"testCloneArrayOfObjects", 648 "testCloneObjectWithFewFields", 649 "testCloneObjectWithManyFields"}) 650 public void runCloneTests() { 651 { 652 Object o1 = new Object(); 653 Object[] a = new Object[4]; 654 for (int i = 0; i < 4; i++) { 655 a[i] = o1; 656 } 657 Object[] a1 = testCloneArrayOfObjects(a); 658 for (int i = 0; i < 4; i++) { 659 Asserts.assertEquals(o1, a1[i]); 660 } 661 } 662 { 663 Object a = new Object(); 664 Object b = new Object(); 665 OuterWithFewFields o = new OuterWithFewFields(); 666 o.f1 = a; 667 o.f2 = b; 668 OuterWithFewFields o1 = testCloneObjectWithFewFields(o); 669 Asserts.assertEquals(a, o1.f1); 670 Asserts.assertEquals(b, o1.f2); 671 } 672 { 673 Object a = new Object(); 674 Object b = new Object(); 675 Object c = new Object(); 676 Object d = new Object(); 677 Object e = new Object(); 678 Object f = new Object(); 679 Object g = new Object(); 680 Object h = new Object(); 681 Object i = new Object(); 682 Object j = new Object(); 683 OuterWithManyFields o = new OuterWithManyFields(); 684 o.f1 = a; 685 o.f2 = b; 686 o.f3 = c; 687 o.f4 = d; 688 o.f5 = e; 689 o.f6 = f; 690 o.f7 = g; 691 o.f8 = h; 692 o.f9 = i; 693 o.f10 = j; 694 OuterWithManyFields o1 = testCloneObjectWithManyFields(o); 695 Asserts.assertEquals(a, o1.f1); 696 Asserts.assertEquals(b, o1.f2); 697 Asserts.assertEquals(c, o1.f3); 698 Asserts.assertEquals(d, o1.f4); 699 Asserts.assertEquals(e, o1.f5); 700 Asserts.assertEquals(f, o1.f6); 701 Asserts.assertEquals(g, o1.f7); 702 Asserts.assertEquals(h, o1.f8); 703 Asserts.assertEquals(i, o1.f9); 704 Asserts.assertEquals(j, o1.f10); 705 } 706 } 707 708 @Test 709 @IR(applyIf = {"UseCompressedOops", "false"}, 710 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 711 phase = CompilePhase.FINAL_CODE) 712 @IR(applyIf = {"UseCompressedOops", "true"}, 713 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 714 phase = CompilePhase.FINAL_CODE) 715 static Object testCompareAndExchange(Outer o, Object oldVal, Object newVal) { 716 return fVarHandle.compareAndExchange(o, oldVal, newVal); 717 } 718 719 @Test 720 @IR(applyIf = {"UseCompressedOops", "false"}, 721 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 722 phase = CompilePhase.FINAL_CODE) 723 @IR(applyIf = {"UseCompressedOops", "true"}, 724 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 725 phase = CompilePhase.FINAL_CODE) 726 static boolean testCompareAndSwap(Outer o, Object oldVal, Object newVal) { 727 return fVarHandle.compareAndSet(o, oldVal, newVal); 728 } 729 730 @Test 731 @IR(applyIf = {"UseCompressedOops", "false"}, 732 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 733 phase = CompilePhase.FINAL_CODE) 734 @IR(applyIf = {"UseCompressedOops", "true"}, 735 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 736 phase = CompilePhase.FINAL_CODE) 737 static Object testGetAndSet(Outer o, Object newVal) { 738 return fVarHandle.getAndSet(o, newVal); 739 } 740 741 // IR checks are disabled for s390 because barriers are not elided (to be investigated). 742 @Test 743 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 744 applyIfPlatform = {"s390", "false"}, 745 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 746 phase = CompilePhase.FINAL_CODE) 747 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 748 applyIfPlatform = {"s390", "false"}, 749 counts = {IRNode.G1_COMPARE_AND_EXCHANGE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 750 phase = CompilePhase.FINAL_CODE) 751 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 752 applyIfPlatform = {"s390", "false"}, 753 failOn = {IRNode.G1_COMPARE_AND_EXCHANGE_P_WITH_BARRIER_FLAG, ANY}, 754 phase = CompilePhase.FINAL_CODE) 755 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 756 applyIfPlatform = {"s390", "false"}, 757 failOn = {IRNode.G1_COMPARE_AND_EXCHANGE_N_WITH_BARRIER_FLAG, ANY}, 758 phase = CompilePhase.FINAL_CODE) 759 static Object testCompareAndExchangeOnNewObject(Object oldVal, Object newVal) { 760 Outer o = new Outer(); 761 o.f = oldVal; 762 return fVarHandle.compareAndExchange(o, oldVal, newVal); 763 } 764 765 // IR checks are disabled for s390 when OOPs compression is disabled 766 // because barriers are not elided in this configuration (to be investigated). 767 @Test 768 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 769 applyIfPlatform = {"s390", "false"}, 770 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 771 phase = CompilePhase.FINAL_CODE) 772 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 773 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 774 phase = CompilePhase.FINAL_CODE) 775 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 776 applyIfPlatform = {"s390", "false"}, 777 failOn = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, ANY}, 778 phase = CompilePhase.FINAL_CODE) 779 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 780 failOn = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, ANY}, 781 phase = CompilePhase.FINAL_CODE) 782 static boolean testCompareAndSwapOnNewObject(Object oldVal, Object newVal) { 783 Outer o = new Outer(); 784 o.f = oldVal; 785 return fVarHandle.compareAndSet(o, oldVal, newVal); 786 } 787 788 @Test 789 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 790 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 791 phase = CompilePhase.FINAL_CODE) 792 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 793 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 794 phase = CompilePhase.FINAL_CODE) 795 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 796 failOn = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, ANY}, 797 phase = CompilePhase.FINAL_CODE) 798 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 799 failOn = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, ANY}, 800 phase = CompilePhase.FINAL_CODE) 801 static Object testGetAndSetOnNewObject(Object oldVal, Object newVal) { 802 Outer o = new Outer(); 803 o.f = oldVal; 804 return fVarHandle.getAndSet(o, newVal); 805 } 806 807 @Test 808 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 809 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 810 phase = CompilePhase.FINAL_CODE) 811 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 812 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 813 phase = CompilePhase.FINAL_CODE) 814 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 815 failOn = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, ANY}, 816 phase = CompilePhase.FINAL_CODE) 817 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 818 failOn = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, ANY}, 819 phase = CompilePhase.FINAL_CODE) 820 static Object testGetAndSetConditionallyOnNewObject(Object oldVal, Object newVal, boolean c) { 821 Outer o = new Outer(); 822 o.f = oldVal; 823 if (c) { 824 return fVarHandle.getAndSet(o, newVal); 825 } 826 return oldVal; 827 } 828 829 @Test 830 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"}, 831 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 832 phase = CompilePhase.FINAL_CODE) 833 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"}, 834 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, POST_ONLY, "1"}, 835 phase = CompilePhase.FINAL_CODE) 836 @IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"}, 837 failOn = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, ANY}, 838 phase = CompilePhase.FINAL_CODE) 839 @IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"}, 840 failOn = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, ANY}, 841 phase = CompilePhase.FINAL_CODE) 842 static Object testGetAndSetOnNewObjectAfterException(Object oldVal, Object newVal, boolean c) throws Exception { 843 Outer o = new Outer(); 844 if (c) { 845 throw new Exception(""); 846 } 847 o.f = oldVal; 848 return fVarHandle.getAndSet(o, newVal); 849 } 850 851 @Test 852 @IR(applyIf = {"UseCompressedOops", "false"}, 853 counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 854 phase = CompilePhase.FINAL_CODE) 855 @IR(applyIf = {"UseCompressedOops", "true"}, 856 counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"}, 857 phase = CompilePhase.FINAL_CODE) 858 static Object testGetAndSetOnNewObjectAfterCall(Object oldVal, Object newVal) { 859 Outer o = new Outer(); 860 nonInlinedMethod(); 861 o.f = oldVal; 862 return fVarHandle.getAndSet(o, newVal); 863 } 864 865 @Run(test = {"testCompareAndExchange", 866 "testCompareAndSwap", 867 "testGetAndSet", 868 "testCompareAndExchangeOnNewObject", 869 "testCompareAndSwapOnNewObject", 870 "testGetAndSetOnNewObject", 871 "testGetAndSetConditionallyOnNewObject", 872 "testGetAndSetOnNewObjectAfterException", 873 "testGetAndSetOnNewObjectAfterCall"}) 874 public void runAtomicTests() { 875 { 876 Outer o = new Outer(); 877 Object oldVal = new Object(); 878 o.f = oldVal; 879 Object newVal = new Object(); 880 Object oldVal2 = testCompareAndExchange(o, oldVal, newVal); 881 Asserts.assertEquals(oldVal, oldVal2); 882 Asserts.assertEquals(o.f, newVal); 883 } 884 { 885 Outer o = new Outer(); 886 Object oldVal = new Object(); 887 o.f = oldVal; 888 Object newVal = new Object(); 889 boolean b = testCompareAndSwap(o, oldVal, newVal); 890 Asserts.assertTrue(b); 891 Asserts.assertEquals(o.f, newVal); 892 } 893 { 894 Outer o = new Outer(); 895 Object oldVal = new Object(); 896 o.f = oldVal; 897 Object newVal = new Object(); 898 Object oldVal2 = testGetAndSet(o, newVal); 899 Asserts.assertEquals(oldVal, oldVal2); 900 Asserts.assertEquals(o.f, newVal); 901 } 902 { 903 Object oldVal = new Object(); 904 Object newVal = new Object(); 905 Object oldVal2 = testCompareAndExchangeOnNewObject(oldVal, newVal); 906 Asserts.assertEquals(oldVal, oldVal2); 907 } 908 { 909 Object oldVal = new Object(); 910 Object newVal = new Object(); 911 boolean b = testCompareAndSwapOnNewObject(oldVal, newVal); 912 Asserts.assertTrue(b); 913 } 914 { 915 Object oldVal = new Object(); 916 Object newVal = new Object(); 917 Object oldVal2 = testGetAndSetOnNewObject(oldVal, newVal); 918 Asserts.assertEquals(oldVal, oldVal2); 919 } 920 { 921 Object oldVal = new Object(); 922 Object newVal = new Object(); 923 boolean c = ThreadLocalRandom.current().nextBoolean(); 924 Object oldVal2 = testGetAndSetConditionallyOnNewObject(oldVal, newVal, c); 925 Asserts.assertEquals(oldVal, oldVal2); 926 } 927 { 928 Object oldVal = new Object(); 929 Object newVal = new Object(); 930 boolean c = ThreadLocalRandom.current().nextBoolean(); 931 try { 932 Object oldVal2 = testGetAndSetOnNewObjectAfterException(oldVal, newVal, c); 933 } catch (Exception e) {} 934 } 935 { 936 Object oldVal = new Object(); 937 Object newVal = new Object(); 938 Object oldVal2 = testGetAndSetOnNewObjectAfterCall(oldVal, newVal); 939 Asserts.assertEquals(oldVal, oldVal2); 940 } 941 } 942 943 @Test 944 @IR(applyIf = {"UseCompressedOops", "false"}, 945 counts = {IRNode.G1_LOAD_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"}, 946 phase = CompilePhase.FINAL_CODE) 947 @IR(applyIf = {"UseCompressedOops", "true"}, 948 counts = {IRNode.G1_LOAD_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"}, 949 phase = CompilePhase.FINAL_CODE) 950 static Object testLoadSoftReference(SoftReference<Object> ref) { 951 return ref.get(); 952 } 953 954 @Test 955 @IR(applyIf = {"UseCompressedOops", "false"}, 956 counts = {IRNode.G1_LOAD_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"}, 957 phase = CompilePhase.FINAL_CODE) 958 @IR(applyIf = {"UseCompressedOops", "true"}, 959 counts = {IRNode.G1_LOAD_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"}, 960 phase = CompilePhase.FINAL_CODE) 961 static Object testLoadWeakReference(WeakReference<Object> ref) { 962 return ref.get(); 963 } 964 965 @Run(test = {"testLoadSoftReference", 966 "testLoadWeakReference"}) 967 public void runReferenceTests() { 968 { 969 Object o1 = new Object(); 970 SoftReference<Object> sref = new SoftReference<Object>(o1); 971 Object o2 = testLoadSoftReference(sref); 972 Asserts.assertTrue(o2 == o1 || o2 == null); 973 } 974 { 975 Object o1 = new Object(); 976 WeakReference<Object> wref = new WeakReference<Object>(o1); 977 Object o2 = testLoadWeakReference(wref); 978 Asserts.assertTrue(o2 == o1 || o2 == null); 979 } 980 } 981 }