0b467e902d
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
640 lines
23 KiB
Java
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);
|
|
}
|
|
}
|
|
}
|