jdk-24/test/hotspot/jtreg/compiler/gcbarriers/TestG1BarrierGeneration.java
Roberto Castañeda Lozano 0b467e902d 8334060: Implementation of Late Barrier Expansion for G1
Co-authored-by: Roberto Castañeda Lozano <rcastanedalo@openjdk.org>
Co-authored-by: Erik Österlund <eosterlund@openjdk.org>
Co-authored-by: Siyao Liu <siyao.l.liu@oracle.com>
Co-authored-by: Kim Barrett <kbarrett@openjdk.org>
Co-authored-by: Amit Kumar <amitkumar@openjdk.org>
Co-authored-by: Martin Doerr <mdoerr@openjdk.org>
Co-authored-by: Feilong Jiang <fjiang@openjdk.org>
Co-authored-by: Sergey Nazarkin <snazarki@openjdk.org>
Reviewed-by: kvn, tschatzl, fyang, ayang, kbarrett
2024-10-03 08:36:33 +00:00

640 lines
23 KiB
Java

/*
* Copyright (c) 2024, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
package compiler.gcbarriers;
import compiler.lib.ir_framework.*;
import java.lang.invoke.VarHandle;
import java.lang.invoke.MethodHandles;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
import java.util.concurrent.ThreadLocalRandom;
import jdk.test.lib.Asserts;
/**
* @test
* @summary Test that G1 barriers are generated and optimized as expected.
* @library /test/lib /
* @requires vm.gc.G1
* @run driver compiler.gcbarriers.TestG1BarrierGeneration
*/
public class TestG1BarrierGeneration {
static final String PRE_ONLY = "pre";
static final String POST_ONLY = "post";
static final String POST_ONLY_NOT_NULL = "post notnull";
static final String PRE_AND_POST = "pre post";
static final String PRE_AND_POST_NOT_NULL = "pre post notnull";
static class Outer {
Object f;
}
static class OuterWithVolatileField {
volatile Object f;
}
static class OuterWithFewFields implements Cloneable {
Object f1;
Object f2;
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static class OuterWithManyFields implements Cloneable {
Object f1;
Object f2;
Object f3;
Object f4;
Object f5;
Object f6;
Object f7;
Object f8;
Object f9;
Object f10;
public Object clone() throws CloneNotSupportedException {
return super.clone();
}
}
static final VarHandle fVarHandle;
static {
MethodHandles.Lookup l = MethodHandles.lookup();
try {
fVarHandle = l.findVarHandle(Outer.class, "f", Object.class);
} catch (Exception e) {
throw new Error(e);
}
}
public static void main(String[] args) {
TestFramework framework = new TestFramework();
Scenario[] scenarios = new Scenario[2*2];
int scenarioIndex = 0;
for (int i = 0; i < 2; i++) {
for (int j = 0; j < 2; j++) {
scenarios[scenarioIndex] =
new Scenario(scenarioIndex,
"-XX:CompileCommand=inline,java.lang.ref.*::*",
"-XX:" + (i == 0 ? "-" : "+") + "UseCompressedOops",
"-XX:" + (j == 0 ? "-" : "+") + "ReduceInitialCardMarks");
scenarioIndex++;
}
}
framework.addScenarios(scenarios);
framework.start();
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
public static void testStore(Outer o, Object o1) {
o.f = o1;
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
public static void testStoreNull(Outer o) {
o.f = null;
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
public static void testStoreObfuscatedNull(Outer o, Object o1) {
Object o2 = o1;
for (int i = 0; i < 4; i++) {
if ((i % 2) == 0) {
o2 = null;
}
}
// o2 is null here, but this is only known to C2 after applying some
// optimizations (loop unrolling, IGVN).
o.f = o2;
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"},
phase = CompilePhase.FINAL_CODE)
public static void testStoreNotNull(Outer o, Object o1) {
if (o1.hashCode() == 42) {
return;
}
o.f = o1;
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "2"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "2"},
phase = CompilePhase.FINAL_CODE)
public static void testStoreTwice(Outer o, Outer p, Object o1) {
o.f = o1;
p.f = o1;
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
public static void testStoreVolatile(OuterWithVolatileField o, Object o1) {
o.f = o1;
}
@Test
@IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
failOn = {IRNode.G1_STORE_P},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
failOn = {IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N},
phase = CompilePhase.FINAL_CODE)
public static Outer testStoreOnNewObject(Object o1) {
Outer o = new Outer();
o.f = o1;
return o;
}
@Test
@IR(failOn = {IRNode.STORE_P, IRNode.STORE_N},
phase = CompilePhase.BEFORE_MACRO_EXPANSION)
public static Outer testStoreNullOnNewObject() {
Outer o = new Outer();
o.f = null;
return o;
}
@Test
@IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY_NOT_NULL, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY_NOT_NULL, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
failOn = {IRNode.G1_STORE_P},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
failOn = {IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N},
phase = CompilePhase.FINAL_CODE)
public static Outer testStoreNotNullOnNewObject(Object o1) {
if (o1.hashCode() == 42) {
return null;
}
Outer o = new Outer();
o.f = o1;
return o;
}
@Test
@IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "2"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "false"},
counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "2"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
failOn = {IRNode.G1_STORE_P},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
failOn = {IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N},
phase = CompilePhase.FINAL_CODE)
public static Outer testStoreOnNewObjectInTwoPaths(Object o1, boolean c) {
Outer o;
if (c) {
o = new Outer();
o.f = o1;
} else {
o = new Outer();
o.f = o1;
}
return o;
}
@Run(test = {"testStore",
"testStoreNull",
"testStoreObfuscatedNull",
"testStoreNotNull",
"testStoreTwice",
"testStoreVolatile",
"testStoreOnNewObject",
"testStoreNullOnNewObject",
"testStoreNotNullOnNewObject",
"testStoreOnNewObjectInTwoPaths"})
public void runStoreTests() {
{
Outer o = new Outer();
Object o1 = new Object();
testStore(o, o1);
Asserts.assertEquals(o1, o.f);
}
{
Outer o = new Outer();
testStoreNull(o);
Asserts.assertNull(o.f);
}
{
Outer o = new Outer();
Object o1 = new Object();
testStoreObfuscatedNull(o, o1);
Asserts.assertNull(o.f);
}
{
Outer o = new Outer();
Object o1 = new Object();
testStoreNotNull(o, o1);
Asserts.assertEquals(o1, o.f);
}
{
Outer o = new Outer();
Outer p = new Outer();
Object o1 = new Object();
testStoreTwice(o, p, o1);
Asserts.assertEquals(o1, o.f);
Asserts.assertEquals(o1, p.f);
}
{
OuterWithVolatileField o = new OuterWithVolatileField();
Object o1 = new Object();
testStoreVolatile(o, o1);
Asserts.assertEquals(o1, o.f);
}
{
Object o1 = new Object();
Outer o = testStoreOnNewObject(o1);
Asserts.assertEquals(o1, o.f);
}
{
Outer o = testStoreNullOnNewObject();
Asserts.assertNull(o.f);
}
{
Object o1 = new Object();
Outer o = testStoreNotNullOnNewObject(o1);
Asserts.assertEquals(o1, o.f);
}
{
Object o1 = new Object();
Outer o = testStoreOnNewObjectInTwoPaths(o1, ThreadLocalRandom.current().nextBoolean());
Asserts.assertEquals(o1, o.f);
}
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
public static void testArrayStore(Object[] a, int index, Object o1) {
a[index] = o1;
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
public static void testArrayStoreNull(Object[] a, int index) {
a[index] = null;
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST_NOT_NULL, "1"},
phase = CompilePhase.FINAL_CODE)
public static void testArrayStoreNotNull(Object[] a, int index, Object o1) {
if (o1.hashCode() == 42) {
return;
}
a[index] = o1;
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "2"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_ENCODE_P_AND_STORE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "2"},
phase = CompilePhase.FINAL_CODE)
public static void testArrayStoreTwice(Object[] a, Object[] b, int index, Object o1) {
a[index] = o1;
b[index] = o1;
}
@Test
@IR(applyIfAnd = {"UseCompressedOops", "false", "ReduceInitialCardMarks", "true"},
failOn = {IRNode.G1_STORE_P},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"UseCompressedOops", "true", "ReduceInitialCardMarks", "true"},
failOn = {IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N},
phase = CompilePhase.FINAL_CODE)
public static Object[] testStoreOnNewArray(Object o1) {
Object[] a = new Object[10];
// The index needs to be concrete for C2 to detect that it is safe to
// remove the pre-barrier.
a[4] = o1;
return a;
}
@Run(test = {"testArrayStore",
"testArrayStoreNull",
"testArrayStoreNotNull",
"testArrayStoreTwice",
"testStoreOnNewArray"})
public void runArrayStoreTests() {
{
Object[] a = new Object[10];
Object o1 = new Object();
testArrayStore(a, 4, o1);
Asserts.assertEquals(o1, a[4]);
}
{
Object[] a = new Object[10];
testArrayStoreNull(a, 4);
Asserts.assertNull(a[4]);
}
{
Object[] a = new Object[10];
Object o1 = new Object();
testArrayStoreNotNull(a, 4, o1);
Asserts.assertEquals(o1, a[4]);
}
{
Object[] a = new Object[10];
Object[] b = new Object[10];
Object o1 = new Object();
testArrayStoreTwice(a, b, 4, o1);
Asserts.assertEquals(o1, a[4]);
Asserts.assertEquals(o1, b[4]);
}
{
Object o1 = new Object();
Object[] a = testStoreOnNewArray(o1);
Asserts.assertEquals(o1, a[4]);
}
}
@Test
public static Object[] testCloneArrayOfObjects(Object[] a) {
Object[] a1 = null;
try {
a1 = a.clone();
} catch (Exception e) {}
return a1;
}
@Test
@IR(applyIf = {"ReduceInitialCardMarks", "true"},
failOn = {IRNode.G1_STORE_P, IRNode.G1_STORE_N, IRNode.G1_ENCODE_P_AND_STORE_N},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"ReduceInitialCardMarks", "false", "UseCompressedOops", "false"},
counts = {IRNode.G1_STORE_P_WITH_BARRIER_FLAG, POST_ONLY, "2"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIfAnd = {"ReduceInitialCardMarks", "false", "UseCompressedOops", "true"},
counts = {IRNode.G1_STORE_N_WITH_BARRIER_FLAG, POST_ONLY, "2"},
phase = CompilePhase.FINAL_CODE)
public static OuterWithFewFields testCloneObjectWithFewFields(OuterWithFewFields o) {
Object o1 = null;
try {
o1 = o.clone();
} catch (Exception e) {}
return (OuterWithFewFields)o1;
}
@Test
@IR(applyIf = {"ReduceInitialCardMarks", "true"},
counts = {IRNode.CALL_OF, "jlong_disjoint_arraycopy", "1"})
@IR(applyIf = {"ReduceInitialCardMarks", "false"},
counts = {IRNode.CALL_OF, "G1BarrierSetRuntime::clone", "1"})
public static OuterWithManyFields testCloneObjectWithManyFields(OuterWithManyFields o) {
Object o1 = null;
try {
o1 = o.clone();
} catch (Exception e) {}
return (OuterWithManyFields)o1;
}
@Run(test = {"testCloneArrayOfObjects",
"testCloneObjectWithFewFields",
"testCloneObjectWithManyFields"})
public void runCloneTests() {
{
Object o1 = new Object();
Object[] a = new Object[4];
for (int i = 0; i < 4; i++) {
a[i] = o1;
}
Object[] a1 = testCloneArrayOfObjects(a);
for (int i = 0; i < 4; i++) {
Asserts.assertEquals(o1, a1[i]);
}
}
{
Object a = new Object();
Object b = new Object();
OuterWithFewFields o = new OuterWithFewFields();
o.f1 = a;
o.f2 = b;
OuterWithFewFields o1 = testCloneObjectWithFewFields(o);
Asserts.assertEquals(a, o1.f1);
Asserts.assertEquals(b, o1.f2);
}
{
Object a = new Object();
Object b = new Object();
Object c = new Object();
Object d = new Object();
Object e = new Object();
Object f = new Object();
Object g = new Object();
Object h = new Object();
Object i = new Object();
Object j = new Object();
OuterWithManyFields o = new OuterWithManyFields();
o.f1 = a;
o.f2 = b;
o.f3 = c;
o.f4 = d;
o.f5 = e;
o.f6 = f;
o.f7 = g;
o.f8 = h;
o.f9 = i;
o.f10 = j;
OuterWithManyFields o1 = testCloneObjectWithManyFields(o);
Asserts.assertEquals(a, o1.f1);
Asserts.assertEquals(b, o1.f2);
Asserts.assertEquals(c, o1.f3);
Asserts.assertEquals(d, o1.f4);
Asserts.assertEquals(e, o1.f5);
Asserts.assertEquals(f, o1.f6);
Asserts.assertEquals(g, o1.f7);
Asserts.assertEquals(h, o1.f8);
Asserts.assertEquals(i, o1.f9);
Asserts.assertEquals(j, o1.f10);
}
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_COMPARE_AND_EXCHANGE_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_COMPARE_AND_EXCHANGE_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
static Object testCompareAndExchange(Outer o, Object oldVal, Object newVal) {
return fVarHandle.compareAndExchange(o, oldVal, newVal);
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_COMPARE_AND_SWAP_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_COMPARE_AND_SWAP_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
static boolean testCompareAndSwap(Outer o, Object oldVal, Object newVal) {
return fVarHandle.compareAndSet(o, oldVal, newVal);
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_GET_AND_SET_P_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_GET_AND_SET_N_WITH_BARRIER_FLAG, PRE_AND_POST, "1"},
phase = CompilePhase.FINAL_CODE)
static Object testGetAndSet(Outer o, Object newVal) {
return fVarHandle.getAndSet(o, newVal);
}
@Run(test = {"testCompareAndExchange",
"testCompareAndSwap",
"testGetAndSet"})
public void runAtomicTests() {
{
Outer o = new Outer();
Object oldVal = new Object();
o.f = oldVal;
Object newVal = new Object();
Object oldVal2 = testCompareAndExchange(o, oldVal, newVal);
Asserts.assertEquals(oldVal, oldVal2);
Asserts.assertEquals(o.f, newVal);
}
{
Outer o = new Outer();
Object oldVal = new Object();
o.f = oldVal;
Object newVal = new Object();
boolean b = testCompareAndSwap(o, oldVal, newVal);
Asserts.assertTrue(b);
Asserts.assertEquals(o.f, newVal);
}
{
Outer o = new Outer();
Object oldVal = new Object();
o.f = oldVal;
Object newVal = new Object();
Object oldVal2 = testGetAndSet(o, newVal);
Asserts.assertEquals(oldVal, oldVal2);
Asserts.assertEquals(o.f, newVal);
}
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_LOAD_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_LOAD_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
static Object testLoadSoftReference(SoftReference<Object> ref) {
return ref.get();
}
@Test
@IR(applyIf = {"UseCompressedOops", "false"},
counts = {IRNode.G1_LOAD_P_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
@IR(applyIf = {"UseCompressedOops", "true"},
counts = {IRNode.G1_LOAD_N_WITH_BARRIER_FLAG, PRE_ONLY, "1"},
phase = CompilePhase.FINAL_CODE)
static Object testLoadWeakReference(WeakReference<Object> ref) {
return ref.get();
}
@Run(test = {"testLoadSoftReference",
"testLoadWeakReference"})
public void runReferenceTests() {
{
Object o1 = new Object();
SoftReference<Object> sref = new SoftReference<Object>(o1);
Object o2 = testLoadSoftReference(sref);
Asserts.assertTrue(o2 == o1 || o2 == null);
}
{
Object o1 = new Object();
WeakReference<Object> wref = new WeakReference<Object>(o1);
Object o2 = testLoadWeakReference(wref);
Asserts.assertTrue(o2 == o1 || o2 == null);
}
}
}