From 38e11169b85e5869440261e197ab7239a7626bf4 Mon Sep 17 00:00:00 2001 From: Theresa Mammarella Date: Fri, 27 Sep 2024 12:08:49 -0400 Subject: [PATCH] Allow arrayCopy between null-restricted and nullable Signed-off-by: Theresa Mammarella --- runtime/vm/BytecodeInterpreter.hpp | 8 +++- runtime/vm/createramclass.cpp | 7 ++- .../lworld/ValueTypeSystemArraycopyTests.java | 45 +++++++++++++++---- .../test/lworld/ValueTypeUnsafeTests.java | 10 +++-- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/runtime/vm/BytecodeInterpreter.hpp b/runtime/vm/BytecodeInterpreter.hpp index d2ee898b3df..f61601104ba 100644 --- a/runtime/vm/BytecodeInterpreter.hpp +++ b/runtime/vm/BytecodeInterpreter.hpp @@ -1234,9 +1234,13 @@ class INTERPRETER_CLASS } } else if (J9_IS_J9CLASS_FLATTENED(srcClazz) || J9_IS_J9CLASS_FLATTENED(destClazz) - || J9_IS_J9CLASS_ALLOW_DEFAULT_VALUE(destComponentClass) + || J9_IS_J9ARRAYCLASS_NULL_RESTRICTED(destClazz) ) { - /* VM_ArrayCopyHelpers::referenceArrayCopy cannot handle flattened arrays or null elements being copied into arrays of primitive value types, so for those cases use copyFlattenableArray instead */ + /* VM_ArrayCopyHelpers::referenceArrayCopy cannot handle + * flattened arrays or null elements being copied into + * arrays of null-restricted value types, so for those + * cases use copyFlattenableArray instead. + */ updateVMStruct(REGISTER_ARGS); I_32 value = VM_ValueTypeHelpers::copyFlattenableArray(_currentThread, _objectAccessBarrier, _objectAllocate, srcObject, destObject, srcStart, destStart, elementCount); VMStructHasBeenUpdated(REGISTER_ARGS); diff --git a/runtime/vm/createramclass.cpp b/runtime/vm/createramclass.cpp index 773fc956630..bf643391153 100644 --- a/runtime/vm/createramclass.cpp +++ b/runtime/vm/createramclass.cpp @@ -3451,10 +3451,9 @@ internalCreateRAMClassFromROMClassImpl(J9VMThread *vmThread, J9ClassLoader *clas * elements may be flattened arrays. */ U_32 arrayFlags = J9ClassLargestAlignmentConstraintReference | J9ClassLargestAlignmentConstraintDouble; - if (J9_ARE_ALL_BITS_SET(javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_VT_ARRAY_FLATTENING)) { - /* TODO restrict this flag to be set only for null-restricted - * arrays once value type command line tests are updated. - */ + if (J9_ARE_ALL_BITS_SET(options, J9_FINDCLASS_FLAG_CLASS_OPTION_NULL_RESTRICTED_ARRAY) + && J9_ARE_ALL_BITS_SET(javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_VT_ARRAY_FLATTENING) + ) { arrayFlags |= J9ClassIsFlattened; } ramArrayClass->classFlags |= (elementClass->classFlags & arrayFlags); diff --git a/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeSystemArraycopyTests.java b/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeSystemArraycopyTests.java index 9e31a1a8bd7..5292ac66d3e 100644 --- a/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeSystemArraycopyTests.java +++ b/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeSystemArraycopyTests.java @@ -26,7 +26,6 @@ import org.testng.annotations.Test; import org.testng.annotations.BeforeClass; -import jdk.internal.value.NullRestrictedCheckedType; import jdk.internal.value.ValueClass; import jdk.internal.vm.annotation.ImplicitlyConstructible; import jdk.internal.vm.annotation.NullRestricted; @@ -60,6 +59,7 @@ public static class SomeIdentityClass2 implements SomeInterface { } } + @ImplicitlyConstructible public value static class SomeValueClass implements SomeInterface { double val1; long val2; @@ -117,12 +117,14 @@ public static value class SomePrimitiveValueClass2 implements SomeInterface { public static SomeValueClass[] vtArrayDst = new SomeValueClass[ARRAY_SIZE]; public static SomeValueClass[] vtArraySrc = new SomeValueClass[ARRAY_SIZE]; public static SomePrimitiveValueClass[] primitiveVtArrayDst = - (SomePrimitiveValueClass[])ValueClass.newArrayInstance( - NullRestrictedCheckedType.of(SomePrimitiveValueClass.class), ARRAY_SIZE); + (SomePrimitiveValueClass[])ValueClass.newNullRestrictedArray(SomePrimitiveValueClass.class, ARRAY_SIZE); public static SomePrimitiveValueClass[] primitiveVtArraySrc = - (SomePrimitiveValueClass[])ValueClass.newArrayInstance( - NullRestrictedCheckedType.of(SomePrimitiveValueClass.class), ARRAY_SIZE); - + (SomePrimitiveValueClass[])ValueClass.newNullRestrictedArray(SomePrimitiveValueClass.class, ARRAY_SIZE); + /* These arrays should be used instead of primitiveVTArrayDst/Src once javac supports null-restricted classes. */ + public static SomeValueClass[] nullRestrictedVtArraySrc = + (SomeValueClass[])ValueClass.newNullRestrictedArray(SomeValueClass.class, ARRAY_SIZE); + public static SomeValueClass[] nullRestrictedVtArrayDst = + (SomeValueClass[])ValueClass.newNullRestrictedArray(SomeValueClass.class, ARRAY_SIZE); public static SomeInterface[] ifIdArrayDst = new SomeIdentityClass[ARRAY_SIZE]; public static SomeInterface[] ifIdArraySrc = new SomeIdentityClass[ARRAY_SIZE]; public static SomeInterface[] ifVtArrayDst = new SomeValueClass[ARRAY_SIZE]; @@ -135,8 +137,7 @@ public static value class SomePrimitiveValueClass2 implements SomeInterface { public static SomeIdentityClass[] idArrayDstCheckForException = new SomeIdentityClass[ARRAY_SIZE]; public static SomePrimitiveValueClass[] primitiveVtArrayDstCheckForException = - (SomePrimitiveValueClass[])ValueClass.newArrayInstance( - NullRestrictedCheckedType.of(SomePrimitiveValueClass.class), ARRAY_SIZE); + (SomePrimitiveValueClass[])ValueClass.newNullRestrictedArray(SomePrimitiveValueClass.class, ARRAY_SIZE); static private void initArrays() { for (int i=0; i < ARRAY_SIZE; i++) { @@ -162,6 +163,9 @@ static private void initArrays() { ifArray1[i] = new SomeIdentityClass(i*13); ifArray2[i] = new SomeValueClass(i*14); ifArray3[i] = new SomePrimitiveValueClass(i*15); + + nullRestrictedVtArrayDst[i] = new SomeValueClass(i*16); + nullRestrictedVtArraySrc[i] = new SomeValueClass(i*17); } } @@ -197,6 +201,13 @@ static private void initArraysForArrayStoreChkExceptionTest() { } } + static private void initArraysToCopyNullToNullRestrictedArray() { + for (int i=0; i < ARRAY_SIZE; i++) { + vtArraySrc[i] = null; + nullRestrictedVtArrayDst[i] = new SomeValueClass(i); + } + } + static private void checkResults(Object[] arr1, Object[] arr2) { for (int i=0; i < arr1.length; ++i) { assertEquals(arr1[i], arr2[i]); @@ -821,4 +832,22 @@ static public void testSystemArrayCopy26() throws Throwable { Assert.fail("Expect a ArrayStoreException. No exception or wrong kind of exception thrown"); } + + @Test(priority=1) + static public void testSystemArrayCopy27() throws Throwable { + initArrays(); + testVTVT(vtArraySrc, nullRestrictedVtArrayDst); + } + + @Test(priority=1) + static public void testSystemArrayCopy28() throws Throwable { + initArrays(); + testVTVT(nullRestrictedVtArraySrc, vtArrayDst); + } + + @Test(priority=1, expectedExceptions=ArrayStoreException.class) + static public void testSystemArrayCopy29() throws Throwable { + initArraysToCopyNullToNullRestrictedArray(); + testVTVT(vtArraySrc, nullRestrictedVtArrayDst); + } } diff --git a/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeUnsafeTests.java b/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeUnsafeTests.java index 7a41c249c10..390813f9259 100644 --- a/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeUnsafeTests.java +++ b/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeUnsafeTests.java @@ -23,6 +23,7 @@ import jdk.internal.misc.Unsafe; +import jdk.internal.value.ValueClass; import jdk.internal.vm.annotation.ImplicitlyConstructible; import java.lang.reflect.Field; import java.lang.reflect.Method; @@ -93,10 +94,11 @@ static private long arrayElementSize(T[] array) { @BeforeMethod static public void setUp() { vtPoint = new ValueTypePoint2D(new ValueTypeInt(7), new ValueTypeInt(8)); - vtPointAry = new ValueTypePoint2D[] { - new ValueTypePoint2D(new ValueTypeInt(5), new ValueTypeInt(10)), - new ValueTypePoint2D(new ValueTypeInt(10), new ValueTypeInt(20)) - }; + + vtPointAry = (ValueTypePoint2D[])ValueClass.newNullRestrictedArray(ValueTypePoint2D.class, 2); + vtPointAry[0] = new ValueTypePoint2D(new ValueTypeInt(5), new ValueTypeInt(10)); + vtPointAry[1] = new ValueTypePoint2D(new ValueTypeInt(10), new ValueTypeInt(20)); + vtPointAryOffset1 = vtPointAryOffset0 + arrayElementSize(vtPointAry); vtIntAry = new ValueTypeInt[] { new ValueTypeInt(1), new ValueTypeInt(2) }; vtIntAryOffset1 = vtIntAryOffset0 + arrayElementSize(vtIntAry);