diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat b/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat index 1e15c4dd0e2..d5dc634fc65 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/AuxFieldInfo29.dat @@ -71,6 +71,7 @@ J9AVLTreeNode.leftChild = required J9AVLTreeNode.rightChild = required J9AbstractThread.library = required J9ArrayClass.arity = required +J9ArrayClass.companionArray = J9Class* J9ArrayClass.componentType = required J9ArrayClass.flattenedElementSize = UDATA J9ArrayClass.leafComponentType = required diff --git a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/gc/GCClassArrayClassSlotIterator.java b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/gc/GCClassArrayClassSlotIterator.java index 00d2f08da2b..95a7c3bb4bc 100644 --- a/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/gc/GCClassArrayClassSlotIterator.java +++ b/debugtools/DDR_VM/src/com/ibm/j9ddr/vm29/j9/gc/GCClassArrayClassSlotIterator.java @@ -27,6 +27,7 @@ import com.ibm.j9ddr.CorruptDataException; import com.ibm.j9ddr.vm29.pointer.VoidPointer; import com.ibm.j9ddr.vm29.pointer.generated.J9ArrayClassPointer; +import com.ibm.j9ddr.vm29.pointer.generated.J9BuildFlags; import com.ibm.j9ddr.vm29.pointer.generated.J9ClassPointer; import static com.ibm.j9ddr.vm29.structure.J9JavaAccessFlags.J9AccClassArray; @@ -43,19 +44,30 @@ protected GCClassArrayClassSlotIterator(J9ClassPointer clazz) throws CorruptData J9ClassPointer slot; slot = clazz.arrayClass(); - if(slot.notNull()) { + if (slot.notNull()) { slots.add(slot); addresses.add(VoidPointer.cast(clazz.arrayClassEA())); } - if(clazz.romClass().modifiers().allBitsIn(J9AccClassArray)) { + if (clazz.romClass().modifiers().allBitsIn(J9AccClassArray)) { J9ArrayClassPointer arrayClass = J9ArrayClassPointer.cast(clazz); + if (J9BuildFlags.J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) { + try { + slot = arrayClass.companionArray(); + if (slot.notNull()) { + slots.add(slot); + addresses.add(VoidPointer.cast(arrayClass.companionArrayEA())); + } + } catch (NoSuchFieldException e) { + throw new CorruptDataException("J9ArrayClass.companionArray field does not exist", e); + } + } slot = arrayClass.componentType(); - if(slot.notNull()) { + if (slot.notNull()) { slots.add(slot); addresses.add(VoidPointer.cast(arrayClass.componentTypeEA())); } slot = arrayClass.leafComponentType(); - if(slot.notNull()) { + if (slot.notNull()) { slots.add(slot); addresses.add(VoidPointer.cast(arrayClass.leafComponentTypeEA())); } diff --git a/runtime/codert_vm/cnathelp.cpp b/runtime/codert_vm/cnathelp.cpp index 1594d1b9e80..fde7a7f0dee 100644 --- a/runtime/codert_vm/cnathelp.cpp +++ b/runtime/codert_vm/cnathelp.cpp @@ -1001,7 +1001,7 @@ old_fast_jitLoadFlattenableArrayElement(J9VMThread *currentThread) value = (j9object_t) currentThread->javaVM->internalVMFunctions->loadFlattenableArrayElement(currentThread, arrayObject, index, true); if (NULL == value) { J9ArrayClass *arrayObjectClass = (J9ArrayClass *)J9OBJECT_CLAZZ(currentThread, arrayObject); - if (J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(arrayObjectClass->componentType)) { + if (J9_IS_J9ARRAYCLASS_NULL_RESTRICTED(arrayObjectClass)) { goto slow; } } @@ -1067,10 +1067,6 @@ old_fast_jitStoreFlattenableArrayElement(J9VMThread *currentThread) if (false == VM_VMHelpers::objectArrayStoreAllowed(currentThread, arrayref, value)) { goto slow; } - arrayrefClass = (J9ArrayClass *) J9OBJECT_CLAZZ(currentThread, arrayref); - if ((J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(arrayrefClass->componentType)) && (NULL == value)) { - goto slow; - } currentThread->javaVM->internalVMFunctions->storeFlattenableArrayElement(currentThread, arrayref, index, value); done: return slowPath; @@ -1474,11 +1470,10 @@ old_fast_jitCheckCast(J9VMThread *currentThread) slowPath = (void*)old_slow_jitCheckCast; } } -#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) - else if (J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(castClass)) { - slowPath = (void*)old_slow_jitThrowNullPointerException; - } -#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ + /* In the future, Valhalla checkcast must throw an exception on + * null-restricted checkedType if object is null. + * See issue https://github.com/eclipse-openj9/openj9/issues/19764. + */ return slowPath; } @@ -3610,11 +3605,10 @@ fast_jitCheckCast(J9VMThread *currentThread, J9Class *castClass, j9object_t obje slowPath = (void*)old_slow_jitCheckCast; } } -#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) - else if (J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(castClass)) { - slowPath = (void*)old_slow_jitThrowNullPointerException; - } -#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ + /* In the future, Valhalla checkcast must throw an exception on + * null-restricted checkedType if object is null. + * See issue https://github.com/eclipse-openj9/openj9/issues/19764. + */ return slowPath; } diff --git a/runtime/gc_structs/ClassArrayClassSlotIterator.cpp b/runtime/gc_structs/ClassArrayClassSlotIterator.cpp index 219e70a7a40..6f91adda39b 100644 --- a/runtime/gc_structs/ClassArrayClassSlotIterator.cpp +++ b/runtime/gc_structs/ClassArrayClassSlotIterator.cpp @@ -50,6 +50,12 @@ GC_ClassArrayClassSlotIterator::nextSlot() _state += 1; } break; +#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) + case classArrayClassSlotIterator_state_companionArray: + classPtr = ((J9ArrayClass *)_iterateClazz)->companionArray; + _state += 1; + break; +#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ case classArrayClassSlotIterator_state_componentType: classPtr = ((J9ArrayClass *)_iterateClazz)->componentType; _state += 1; diff --git a/runtime/gc_structs/ClassArrayClassSlotIterator.hpp b/runtime/gc_structs/ClassArrayClassSlotIterator.hpp index f40434acb60..83f519c76cb 100644 --- a/runtime/gc_structs/ClassArrayClassSlotIterator.hpp +++ b/runtime/gc_structs/ClassArrayClassSlotIterator.hpp @@ -46,6 +46,9 @@ class GC_ClassArrayClassSlotIterator enum { classArrayClassSlotIterator_state_arrayClass = 0, +#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) + classArrayClassSlotIterator_state_companionArray, +#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ classArrayClassSlotIterator_state_componentType, classArrayClassSlotIterator_state_leafComponentType, classArrayClassSlotIterator_state_done diff --git a/runtime/gc_structs/ClassLoaderClassesIterator.cpp b/runtime/gc_structs/ClassLoaderClassesIterator.cpp index e22d9028d5b..fc08f677f7e 100644 --- a/runtime/gc_structs/ClassLoaderClassesIterator.cpp +++ b/runtime/gc_structs/ClassLoaderClassesIterator.cpp @@ -36,12 +36,15 @@ GC_ClassLoaderClassesIterator::GC_ClassLoaderClassesIterator(MM_GCExtensionsBase ,_vmSegmentIterator(classLoader, MEMORY_TYPE_RAM_CLASS) ,_vmClassSlotIterator((J9JavaVM* )extensions->getOmrVM()->_language_vm) ,_mode(TABLE_CLASSES) + ,_iterateArrayClazz(NULL) + ,_arrayState(STATE_VALUETYPEARRAY) { if ((classLoader->flags & J9CLASSLOADER_ANON_CLASS_LOADER) != 0) { _mode = ANONYMOUS_CLASSES; } _nextClass = firstClass(); + _startingClass = _nextClass; } J9Class * @@ -99,6 +102,58 @@ GC_ClassLoaderClassesIterator::switchToSystemMode() return isSystemClassLoader; } +J9Class * +GC_ClassLoaderClassesIterator::nextArrayClass() +{ + while (_arrayState != STATE_DONE) { + switch (_arrayState) { + case STATE_VALUETYPEARRAY: + { +#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) + J9Class *nullRestrictedArray = J9CLASS_GET_NULLRESTRICTED_ARRAY(_startingClass); + if (NULL != nullRestrictedArray) { + _iterateArrayClazz = nullRestrictedArray; + _arrayState = STATE_VALUETYPEARRAYLIST; + } else +#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ + { + _arrayState = STATE_ARRAY; + } + } + break; + case STATE_VALUETYPEARRAYLIST: + if (NULL != _iterateArrayClazz) { + _iterateArrayClazz = _iterateArrayClazz->arrayClass; + } else { + _arrayState = STATE_ARRAY; + } + break; + case STATE_ARRAY: + if (NULL != _startingClass->arrayClass) { + _iterateArrayClazz = _startingClass->arrayClass; + _arrayState = STATE_ARRAYLIST; + } else { + _arrayState = STATE_DONE; + } + break; + case STATE_ARRAYLIST: + if (NULL != _iterateArrayClazz) { + _iterateArrayClazz = _iterateArrayClazz->arrayClass; + } else { + _arrayState = STATE_DONE; + } + break; + case STATE_DONE: + default: + break; + } + if (NULL != _iterateArrayClazz) { + break; + } + } + return _iterateArrayClazz; +} + J9Class * GC_ClassLoaderClassesIterator::nextClass() { @@ -108,13 +163,18 @@ GC_ClassLoaderClassesIterator::nextClass() if (ANONYMOUS_CLASSES == _mode) { _nextClass = nextAnonymousClass(); } else { - if ( (result->classLoader == _classLoader) && (NULL != result->arrayClass) ) { + J9Class *array = nextArrayClass(); + if ((result->classLoader == _classLoader) && (NULL != array)) { /* this class is defined in the loader, so follow its array classes */ - _nextClass = result->arrayClass; + _nextClass = array; } else if (TABLE_CLASSES == _mode) { _nextClass = nextTableClass(); + _startingClass = _nextClass; + _arrayState = STATE_VALUETYPEARRAY; } else { _nextClass = nextSystemClass(); + _startingClass = _nextClass; + _arrayState = STATE_VALUETYPEARRAY; } } } diff --git a/runtime/gc_structs/ClassLoaderClassesIterator.hpp b/runtime/gc_structs/ClassLoaderClassesIterator.hpp index f2e925a1e3f..111aa0fbde2 100644 --- a/runtime/gc_structs/ClassLoaderClassesIterator.hpp +++ b/runtime/gc_structs/ClassLoaderClassesIterator.hpp @@ -62,6 +62,16 @@ class GC_ClassLoaderClassesIterator ANONYMOUS_CLASSES }; ScanModes _mode; /**< indicate type of classes to be iterated */ + J9Class *_iterateArrayClazz; /**< current array walk class */ + J9Class *_startingClass; /**< the most recent table or system class which is the starting point for each array walk */ + enum ArrayClassState { + STATE_VALUETYPEARRAY = 0, /**< setup value type array list walk */ + STATE_VALUETYPEARRAYLIST, /**< value type array list walk */ + STATE_ARRAY, /**< setup array list walk */ + STATE_ARRAYLIST, /**< array list walk */ + STATE_DONE + }; + ArrayClassState _arrayState; /**< array walk state */ protected: public: @@ -99,6 +109,16 @@ class GC_ClassLoaderClassesIterator * @return true if this is the system class loader, false otherwise */ bool switchToSystemMode(); + + /** + * Iterate through all array classes of _nextClass. A base class may have + * a list of array classes starting at the J9Class fields nullRestrictedArrayClass + * and arrayClass. nullRestrictedArrayClass can only exist as a field of a value class + * and can only be an array of arity 1. + * After that its list will continue in the arrayClass field. + * @return the next array class, or NULL if finished + */ + J9Class *nextArrayClass(); protected: diff --git a/runtime/j9vm/javanextvmi.cpp b/runtime/j9vm/javanextvmi.cpp index 6308573ea75..75bda5efb7c 100644 --- a/runtime/j9vm/javanextvmi.cpp +++ b/runtime/j9vm/javanextvmi.cpp @@ -764,15 +764,67 @@ JVM_IsImplicitlyConstructibleClass(JNIEnv *env, jclass cls) JNIEXPORT jboolean JNICALL JVM_IsNullRestrictedArray(JNIEnv *env, jobject obj) { - // TODO implement this with https://github.com/eclipse-openj9/openj9/issues/19460 - return JNI_FALSE; + jboolean result = JNI_FALSE; + J9VMThread *currentThread = (J9VMThread *)env; + J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions; + vmFuncs->internalEnterVMFromJNI(currentThread); + if (NULL == obj) { + vmFuncs->setCurrentException(currentThread, J9VMCONSTANTPOOL_JAVALANGNULLPOINTEREXCEPTION, NULL); + } else { + J9Class *j9clazz = J9OBJECT_CLAZZ(currentThread, J9_JNI_UNWRAP_REFERENCE(obj)); + if (J9_IS_J9ARRAYCLASS_NULL_RESTRICTED(j9clazz)) { + result = JNI_TRUE; + } + } + vmFuncs->internalExitVMToJNI(currentThread); + return result; } JNIEXPORT jarray JNICALL -JVM_NewNullRestrictedArray(JNIEnv *env, jclass cls, jint length) +JVM_NewNullRestrictedArray(JNIEnv *env, jclass componentType, jint length) { - assert(!"JVM_NewNullRestrictedArray unimplemented"); - return NULL; + J9VMThread *currentThread = (J9VMThread *)env; + J9JavaVM *vm = currentThread->javaVM; + J9InternalVMFunctions *vmFuncs = currentThread->javaVM->internalVMFunctions; + J9Class *ramClass = NULL; + j9object_t newArray = NULL; + jarray arrayRef = NULL; + + vmFuncs->internalEnterVMFromJNI(currentThread); + ramClass = J9VMJAVALANGCLASS_VMREF(currentThread, J9_JNI_UNWRAP_REFERENCE(componentType)); + + if (length < 0) { + vmFuncs->setCurrentException(currentThread, J9VMCONSTANTPOOL_JAVALANGNEGATIVEARRAYSIZEEXCEPTION, NULL); + goto done; + } + + if (!(J9_IS_J9CLASS_VALUETYPE(ramClass) && J9_IS_J9CLASS_ALLOW_DEFAULT_VALUE(ramClass))) { + vmFuncs->setCurrentException(currentThread, J9VMCONSTANTPOOL_JAVALANGILLEGALARGUMENTEXCEPTION, NULL); + goto done; + } + + if (NULL == J9CLASS_GET_NULLRESTRICTED_ARRAY(ramClass)) { + J9ROMArrayClass *arrayOfObjectsROMClass = (J9ROMArrayClass *)J9ROMIMAGEHEADER_FIRSTCLASS(vm->arrayROMClasses); + vmFuncs->internalCreateArrayClassWithOptions( + currentThread, arrayOfObjectsROMClass, ramClass, J9_FINDCLASS_FLAG_CLASS_OPTION_NULL_RESTRICTED_ARRAY); + if (NULL != currentThread->currentException) { + goto done; + } + ramClass = VM_VMHelpers::currentClass(ramClass); + } + + newArray = vm->memoryManagerFunctions->J9AllocateIndexableObject( + currentThread, J9CLASS_GET_NULLRESTRICTED_ARRAY(ramClass), length, J9_GC_ALLOCATE_OBJECT_NON_INSTRUMENTABLE); + + if (NULL == newArray) { + vmFuncs->setHeapOutOfMemoryError(currentThread); + goto done; + } + + arrayRef = (jarray)vmFuncs->j9jni_createLocalRef(env, newArray); +done: + vmFuncs->internalExitVMToJNI(currentThread); + return arrayRef; } #endif /* defined(J9VM_OPT_VALHALLA_VALUE_TYPES) */ diff --git a/runtime/oti/VMHelpers.hpp b/runtime/oti/VMHelpers.hpp index c630b49c834..6f6d368e99c 100644 --- a/runtime/oti/VMHelpers.hpp +++ b/runtime/oti/VMHelpers.hpp @@ -1786,9 +1786,10 @@ class VM_VMHelpers objectArrayStoreAllowed(J9VMThread const *currentThread, j9object_t array, j9object_t storeValue) { bool rc = true; + J9ArrayClass *arrayClass = (J9ArrayClass *)J9OBJECT_CLAZZ(currentThread, array); if (NULL != storeValue) { J9Class *valueClass = J9OBJECT_CLAZZ(currentThread, storeValue); - J9Class *componentType = ((J9ArrayClass*)J9OBJECT_CLAZZ(currentThread, array))->componentType; + J9Class *componentType = arrayClass->componentType; /* quick check -- is this a store of a C into a C[]? */ if (valueClass != componentType) { /* quick check -- is this a store of a C into a java.lang.Object[]? */ @@ -1796,6 +1797,10 @@ class VM_VMHelpers rc = inlineCheckCast(valueClass, componentType); } } +#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) + } else if (J9_IS_J9ARRAYCLASS_NULL_RESTRICTED(arrayClass)) { + rc = FALSE; +#endif /* if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ } return rc; } diff --git a/runtime/oti/j9.h b/runtime/oti/j9.h index c250f3cb880..1df71221bd0 100644 --- a/runtime/oti/j9.h +++ b/runtime/oti/j9.h @@ -331,7 +331,7 @@ static const struct { \ #if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) #define J9CLASS_UNPADDED_INSTANCE_SIZE(clazz) J9_VALUETYPE_FLATTENED_SIZE(clazz) -/* TODO replace with J9_IS_J9CLASS_ALLOW_DEFAULT_VALUE(clazz) J9_ARE_ALL_BITS_SET((clazz)->classFlags, J9ClassAllowsInitialDefaultValue)*/ +#define J9_IS_J9CLASS_ALLOW_DEFAULT_VALUE(clazz) J9_ARE_ALL_BITS_SET((clazz)->classFlags, J9ClassAllowsInitialDefaultValue) #define J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(clazz) J9_ARE_ALL_BITS_SET((clazz)->classFlags, J9ClassIsPrimitiveValueType) #define J9_IS_J9CLASS_FLATTENED(clazz) J9_ARE_ALL_BITS_SET((clazz)->classFlags, J9ClassIsFlattened) @@ -348,14 +348,18 @@ static const struct { \ J9_IS_J9CLASS_FLATTENED(fieldClazz) && \ (J9_ARE_NO_BITS_SET((romFieldShape)->modifiers, J9AccVolatile) || (J9CLASS_UNPADDED_INSTANCE_SIZE(fieldClazz) <= sizeof(U_64)))) #define J9_VALUETYPE_FLATTENED_SIZE(clazz) (J9CLASS_HAS_4BYTE_PREPADDING((clazz)) ? ((clazz)->totalInstanceSize - sizeof(U_32)) : (clazz)->totalInstanceSize) +#define J9_IS_J9ARRAYCLASS_NULL_RESTRICTED(clazz) J9_ARE_ALL_BITS_SET((clazz)->classFlags, J9ClassArrayIsNullRestricted) +#define J9CLASS_GET_NULLRESTRICTED_ARRAY(clazz) (J9_IS_J9CLASS_VALUETYPE(clazz) ? (clazz)->nullRestrictedArrayClass : NULL) #else /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ #define J9CLASS_UNPADDED_INSTANCE_SIZE(clazz) ((clazz)->totalInstanceSize) +#define J9_IS_J9CLASS_ALLOW_DEFAULT_VALUE(clazz) FALSE #define J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(clazz) FALSE #define J9_IS_J9CLASS_FLATTENED(clazz) FALSE #define J9ROMFIELD_IS_NULL_RESTRICTED(romField) FALSE #define J9_IS_FIELD_FLATTENED(fieldClazz, romFieldShape) FALSE #define J9_IS_NULL_RESTRICTED_FIELD_FLATTENED(fieldClazz, romFieldShape) FALSE #define J9_VALUETYPE_FLATTENED_SIZE(clazz)((UDATA) 0) /* It is not possible for this macro to be used since we always check J9_IS_J9CLASS_FLATTENED before ever using it. */ +#define J9_IS_J9ARRAYCLASS_NULL_RESTRICTED(clazz) FALSE #endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ #define IS_REF_OR_VAL_SIGNATURE(firstChar) ('L' == (firstChar)) diff --git a/runtime/oti/j9consts.h b/runtime/oti/j9consts.h index 52326ea1a95..17ae11ba9db 100644 --- a/runtime/oti/j9consts.h +++ b/runtime/oti/j9consts.h @@ -450,6 +450,7 @@ extern "C" { #define J9_FINDCLASS_FLAG_DO_NOT_SHARE 0x100000 #define J9_FINDCLASS_FLAG_LAMBDA 0x200000 #define J9_FINDCLASS_FLAG_LAMBDAFORM 0x400000 +#define J9_FINDCLASS_FLAG_CLASS_OPTION_NULL_RESTRICTED_ARRAY 0x800000 #define J9_FINDKNOWNCLASS_FLAG_INITIALIZE 0x1 #define J9_FINDKNOWNCLASS_FLAG_EXISTING_ONLY 0x2 diff --git a/runtime/oti/j9nonbuilder.h b/runtime/oti/j9nonbuilder.h index b655b7b8df7..987b6740dbc 100644 --- a/runtime/oti/j9nonbuilder.h +++ b/runtime/oti/j9nonbuilder.h @@ -96,6 +96,7 @@ #define J9ClassAllowsInitialDefaultValue 0x400000 #define J9ClassAllowsNonAtomicCreation 0x800000 #define J9ClassNeedToPruneMemberNames 0x1000000 +#define J9ClassArrayIsNullRestricted 0x2000000 /* @ddr_namespace: map_to_type=J9FieldFlags */ @@ -3391,6 +3392,9 @@ typedef struct J9Class { /* A linked list of weak global references to every resolved MemberName whose clazz is this class. */ J9MemberNameListNode *memberNames; #endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */ +#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) + struct J9Class *nullRestrictedArrayClass; +#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ } J9Class; /* Interface classes can never be instantiated, so the following fields in J9Class will not be used: @@ -3487,6 +3491,13 @@ typedef struct J9ArrayClass { /* A linked list of weak global references to every resolved MemberName whose clazz is this class. */ J9MemberNameListNode *memberNames; #endif /* defined(J9VM_OPT_OPENJDK_METHODHANDLE) */ +#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) + /* + * A nullable J9ArrayClass points to its null-restricted companion, if one exists. + * A null-restricted J9ArrayClass points to its nullable companion, if one exists. + */ + struct J9Class *companionArray; +#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ } J9ArrayClass; @@ -4800,6 +4811,7 @@ typedef struct J9InternalVMFunctions { void (JNICALL *sendInit)(struct J9VMThread *vmContext, j9object_t object, struct J9Class *senderClass, UDATA lookupOptions) ; void ( *internalAcquireVMAccessNoMutex)(struct J9VMThread * vmThread) ; struct J9Class* ( *internalCreateArrayClass)(struct J9VMThread* vmThread, struct J9ROMArrayClass* romClass, struct J9Class* elementClass) ; + struct J9Class *(*internalCreateArrayClassWithOptions)(struct J9VMThread *vmThread, struct J9ROMArrayClass *romClass, struct J9Class *elementClass, UDATA options); IDATA ( *attachSystemDaemonThread)(struct J9JavaVM * vm, struct J9VMThread ** p_env, const char * threadName) ; void ( *internalAcquireVMAccessClearStatus)(struct J9VMThread * vmThread, UDATA flags) ; #if defined(J9VM_OPT_REFLECT) diff --git a/runtime/oti/vm_api.h b/runtime/oti/vm_api.h index dfe6d80ff66..aa5513573a7 100644 --- a/runtime/oti/vm_api.h +++ b/runtime/oti/vm_api.h @@ -357,6 +357,19 @@ peekClassHashTable(J9VMThread* currentThread, J9ClassLoader* classLoader, U_8* c J9Class* internalCreateArrayClass(J9VMThread* vmThread, J9ROMArrayClass* romClass, J9Class* elementClass); +/** + * @brief Create a new J9Class to represent an array of elementClass. + * + * @param vmThread current VM thread + * @param romClass the ROM class associated with new RAM class (for arrays + * this is always the object array ROM class "[L") + * @param elementClass element or base class or array to be created + * @param options creation options such as J9_FINDCLASS_FLAG_CLASS_OPTION_NULL_RESTRICTED_ARRAY + * @return J9Class* J9Class of an elementClass array + */ +J9Class * +internalCreateArrayClassWithOptions(J9VMThread *vmThread, J9ROMArrayClass *romClass, J9Class *elementClass, UDATA options); + /** * Load the class with the specified name in a given module * diff --git a/runtime/vm/BytecodeInterpreter.hpp b/runtime/vm/BytecodeInterpreter.hpp index 45411a58905..d1b051aa534 100644 --- a/runtime/vm/BytecodeInterpreter.hpp +++ b/runtime/vm/BytecodeInterpreter.hpp @@ -6888,22 +6888,12 @@ class INTERPRETER_CLASS if (false == VM_VMHelpers::objectArrayStoreAllowed(_currentThread, arrayref, value)) { rc = THROW_ARRAY_STORE; } else { -#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) - J9ArrayClass *arrayrefClass = (J9ArrayClass *) J9OBJECT_CLAZZ(_currentThread, arrayref); - if (J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(arrayrefClass->componentType) && (NULL == value)) { - rc = THROW_NPE; - goto done; - } -#endif /* if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ VM_ValueTypeHelpers::storeFlattenableArrayElement(_currentThread, _objectAccessBarrier, arrayref, index, value); _pc += 1; _sp += 3; } } } -#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) -done: -#endif /* if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ return rc; } diff --git a/runtime/vm/ValueTypeHelpers.hpp b/runtime/vm/ValueTypeHelpers.hpp index 32490af20e6..4cb9f09c57f 100644 --- a/runtime/vm/ValueTypeHelpers.hpp +++ b/runtime/vm/ValueTypeHelpers.hpp @@ -512,7 +512,6 @@ class VM_ValueTypeHelpers { I_32 srcEndIndex = srcIndex + lengthInSlots; J9Class *srcClazz = J9OBJECT_CLAZZ(currentThread, srcObject); J9Class *destClazz = J9OBJECT_CLAZZ(currentThread, destObject); - J9Class *destComponentClass = ((J9ArrayClass *)destClazz)->componentType; /* Array elements must be copied backwards if source and destination overlap in memory and source is before destination */ if ((srcObject == destObject) && (srcIndex < destIndex) && ((srcIndex + lengthInSlots) > destIndex)) { @@ -566,10 +565,6 @@ class VM_ValueTypeHelpers { } if (typeChecksRequired) { - if (J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(destComponentClass) && (NULL == copyObject)) { - /* Null objects cannot be stored in an array of primitive value types */ - return -2; - } if (!VM_VMHelpers::objectArrayStoreAllowed(currentThread, destObject, copyObject)) { return -1; } diff --git a/runtime/vm/classsupport.c b/runtime/vm/classsupport.c index 82ae71455d6..322e59f402c 100644 --- a/runtime/vm/classsupport.c +++ b/runtime/vm/classsupport.c @@ -194,24 +194,31 @@ findPrimitiveArrayClass(J9JavaVM* vm, jchar sigChar) * * Allocates and fills in the relevant fields of an array class */ -J9Class* -internalCreateArrayClass(J9VMThread* vmThread, J9ROMArrayClass* romClass, J9Class* elementClass) +J9Class * +internalCreateArrayClass(J9VMThread *vmThread, J9ROMArrayClass *romClass, J9Class *elementClass) +{ + return internalCreateArrayClassWithOptions(vmThread, romClass, elementClass, 0); +} + +J9Class * +internalCreateArrayClassWithOptions(J9VMThread *vmThread, J9ROMArrayClass *romClass, J9Class *elementClass, UDATA options) { J9Class *result = NULL; j9object_t heapClass = J9VM_J9CLASS_TO_HEAPCLASS(elementClass); j9object_t protectionDomain = NULL; - J9ROMClass* arrayRomClass = (J9ROMClass*) romClass; + J9ROMClass *arrayRomClass = (J9ROMClass *)romClass; J9JavaVM *const javaVM = vmThread->javaVM; - UDATA options = 0; BOOLEAN elementInitSuccess = TRUE; #if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) - /* When creating an array of valuetype elements, the array elements are initialized to the defaultValue of the - * element type. As a result the element type must be fully initialized (if its a valuetype) before creating an - * instance of the array. Element class init must be done before the arrayClass is created so that in the case - * of an init failure the arrayClass is not temporarily exposed. + /* When creating an array of implicitly constructible valuetype elements, + * the array elements are initialized to the defaultValue of the element + * type. As a result, the element type must be fully initialized before + * creating an instance of the array. Element class init must be done + * before the arrayClass is created so that in the case of an init failure + * the arrayClass is not temporarily exposed. */ - if (J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(elementClass)) { + if (J9_IS_J9CLASS_ALLOW_DEFAULT_VALUE(elementClass)) { UDATA initStatus = elementClass->initializeStatus; if ((J9ClassInitSucceeded != initStatus) && ((UDATA)vmThread != initStatus)) { initializeClass(vmThread, elementClass); diff --git a/runtime/vm/createramclass.cpp b/runtime/vm/createramclass.cpp index a72ea536024..9d4b0ec60a2 100644 --- a/runtime/vm/createramclass.cpp +++ b/runtime/vm/createramclass.cpp @@ -197,6 +197,19 @@ static void initializeClassLinks(J9Class *ramClass, J9Class *superclass, J9Memor #define MAGIC_ACCESSOR_IMPL "jdk/internal/reflect/MagicAccessorImpl" #endif /* JAVA_SPEC_VERSION == 8 */ +static VMINLINE J9Class * +getArrayClass(J9Class *elementClass, UDATA options) +{ +#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) + if (J9_ARE_ALL_BITS_SET(options, J9_FINDCLASS_FLAG_CLASS_OPTION_NULL_RESTRICTED_ARRAY)) { + return elementClass->nullRestrictedArrayClass; + } else +#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ + { + return elementClass->arrayClass; + } +} + /** * Mark all of the interfaces supported by this class, including all interfaces * inherited by superinterfaces. Unmark all interfaces which are inherited from @@ -2175,7 +2188,7 @@ internalCreateRAMClassDone(J9VMThread *vmThread, J9ClassLoader *classLoader, J9C if (elementClass == NULL) { alreadyLoadedClass = hashClassTableAt(classLoader, J9UTF8_DATA(className), J9UTF8_LENGTH(className)); } else { - alreadyLoadedClass = elementClass->arrayClass; + alreadyLoadedClass = getArrayClass(elementClass, options); } if (alreadyLoadedClass != NULL) { /* We are discarding this class */ @@ -2374,7 +2387,7 @@ internalCreateRAMClassDone(J9VMThread *vmThread, J9ClassLoader *classLoader, J9C if (elementClass == NULL) { alreadyLoadedClass = hashClassTableAt(classLoader, J9UTF8_DATA(className), J9UTF8_LENGTH(className)); } else { - alreadyLoadedClass = elementClass->arrayClass; + alreadyLoadedClass = getArrayClass(elementClass, options); } if (alreadyLoadedClass != NULL) { goto alreadyLoaded; @@ -2388,7 +2401,20 @@ internalCreateRAMClassDone(J9VMThread *vmThread, J9ClassLoader *classLoader, J9C } } else { if (J9ROMCLASS_IS_ARRAY(romClass)) { - ((J9ArrayClass *)elementClass)->arrayClass = state->ramClass; +#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) + if (J9_ARE_ALL_BITS_SET(options, J9_FINDCLASS_FLAG_CLASS_OPTION_NULL_RESTRICTED_ARRAY)) { + elementClass->nullRestrictedArrayClass = state->ramClass; + } else +#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ + { + ((J9ArrayClass *)elementClass)->arrayClass = state->ramClass; + } +#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) + if ((NULL != elementClass->nullRestrictedArrayClass) && (NULL != elementClass->arrayClass)) { + ((J9ArrayClass *)elementClass->arrayClass)->companionArray = elementClass->nullRestrictedArrayClass; + ((J9ArrayClass *)elementClass->nullRestrictedArrayClass)->companionArray = elementClass->arrayClass; + } +#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ /* Assigning into the arrayClass field creates an implicit reference to the class from its class loader */ javaVM->memoryManagerFunctions->j9gc_objaccess_postStoreClassToClassLoader(vmThread, classLoader, state->ramClass); } @@ -2844,7 +2870,7 @@ internalCreateRAMClassFromROMClassImpl(J9VMThread *vmThread, J9ClassLoader *clas if (elementClass == NULL) { ramClass = hashClassTableAt(classLoader, J9UTF8_DATA(className), J9UTF8_LENGTH(className)); } else { - ramClass = elementClass->arrayClass; + ramClass = getArrayClass(elementClass, options); } state->ramClass = ramClass; @@ -3189,7 +3215,7 @@ internalCreateRAMClassFromROMClassImpl(J9VMThread *vmThread, J9ClassLoader *clas * + J9ClassAllowsNonAtomicCreation * * + J9ClassNeedToPruneMemberNames - * + Unused + * + J9ClassArrayIsNullRestricted * + Unused * + Unused * @@ -3419,14 +3445,7 @@ internalCreateRAMClassFromROMClassImpl(J9VMThread *vmThread, J9ClassLoader *clas arity = elementArrayClass->arity + 1; leafComponentType = elementArrayClass->leafComponentType; } else { - U_32 arrayFlags = J9ClassLargestAlignmentConstraintReference | J9ClassLargestAlignmentConstraintDouble; - - if (J9_ARE_ALL_BITS_SET(javaVM->extendedRuntimeFlags2, J9_EXTENDED_RUNTIME2_ENABLE_VT_ARRAY_FLATTENING)) { - arrayFlags |= J9ClassIsFlattened; - } - - arity = 1; - leafComponentType = elementClass; +#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) /* For arrays of valueType elements (where componentType is a valuetype), the arrays themselves are not * valuetypes but they should inherit the layout characteristics (ie. flattenable, etc.) * of the valuetype elements. A 2D (or more) array of valuetype elements (where leafComponentType is a Valuetype but @@ -3434,7 +3453,20 @@ internalCreateRAMClassFromROMClassImpl(J9VMThread *vmThread, J9ClassLoader *clas * properties from the leafComponentType. A 2D array is an array of references so it can never be flattened, however, its * 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. + */ + arrayFlags |= J9ClassIsFlattened; + } ramArrayClass->classFlags |= (elementClass->classFlags & arrayFlags); + if (J9_ARE_ALL_BITS_SET(options, J9_FINDCLASS_FLAG_CLASS_OPTION_NULL_RESTRICTED_ARRAY)) { + ramArrayClass->classFlags |= J9ClassArrayIsNullRestricted; + } +#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ + arity = 1; + leafComponentType = elementClass; } ramArrayClass->classFlags |= J9ClassHasIdentity; ramArrayClass->leafComponentType = leafComponentType; @@ -3458,7 +3490,7 @@ internalCreateRAMClassFromROMClassImpl(J9VMThread *vmThread, J9ClassLoader *clas J9ARRAYCLASS_SET_STRIDE(ramClass, J9_VALUETYPE_FLATTENED_SIZE(elementClass)); } } else { - if (J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(elementClass)) { + if (J9_IS_J9CLASS_ALLOW_DEFAULT_VALUE(elementClass)) { ramArrayClass->classFlags |= J9ClassContainsUnflattenedFlattenables; } J9ARRAYCLASS_SET_STRIDE(ramClass, (((UDATA) 1) << (((J9ROMArrayClass*)romClass)->arrayShape & 0x0000FFFF))); @@ -3651,7 +3683,7 @@ internalCreateRAMClassFromROMClass(J9VMThread *vmThread, J9ClassLoader *classLoa #endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ ) { #if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) - if (flattenedClassCache != (J9FlattenedClassCache *) flattenedClassCacheBuffer) { + if (flattenedClassCache != (J9FlattenedClassCache *)flattenedClassCacheBuffer) { j9mem_free_memory(flattenedClassCache); } #endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */ diff --git a/runtime/vm/intfunc.c b/runtime/vm/intfunc.c index 46a1395b9b2..a68b2b98c02 100644 --- a/runtime/vm/intfunc.c +++ b/runtime/vm/intfunc.c @@ -81,6 +81,7 @@ J9InternalVMFunctions J9InternalFunctions = { sendInit, internalAcquireVMAccessNoMutex, internalCreateArrayClass, + internalCreateArrayClassWithOptions, attachSystemDaemonThread, internalAcquireVMAccessClearStatus, #if defined(J9VM_OPT_REFLECT) diff --git a/test/functional/Valhalla/playlist.xml b/test/functional/Valhalla/playlist.xml index e6acf1c8c48..3225144ba63 100644 --- a/test/functional/Valhalla/playlist.xml +++ b/test/functional/Valhalla/playlist.xml @@ -63,14 +63,14 @@ -Xjit:count=0 -Xjit:count=1,disableAsyncCompilation -Xgcpolicy:optthruput + -Xjit:count=1,disableAsyncCompilation -Xgcpolicy:optthruput -XX:ValueTypeFlatteningThreshold=99999 -XX:-EnableArrayFlattening - -Xjit:count=1,disableAsyncCompilation -Xgcpolicy:gencon -XX:ValueTypeFlatteningThreshold=12 -XX:-EnableArrayFlattening -Xjit:count=1,disableAsyncCompilation -Xgcpolicy:gencon -XX:ValueTypeFlatteningThreshold=99999 -XX:-EnableArrayFlattening - -Xjit:count=1,disableAsyncCompilation -Xgcpolicy:gencon -XX:ValueTypeFlatteningThreshold=99999 -XX:+EnableArrayFlattening - -Xjit:count=1,disableAsyncCompilation -Xnocompressedrefs -Xgcpolicy:optthruput -XX:ValueTypeFlatteningThreshold=99999 -XX:+EnableArrayFlattening - -Xjit:count=1,disableAsyncCompilation -Xnocompressedrefs -Xgcpolicy:gencon -XX:ValueTypeFlatteningThreshold=99999 -XX:+EnableArrayFlattening--> + + + -Xjit:count=1,disableAsyncCompilation -Xnocompressedrefs -Xgcpolicy:gencon $(JAVA_COMMAND) $(JVM_OPTIONS) \ @@ -98,11 +98,6 @@ ValueTypeArrayTests - - - https://github.com/eclipse-openj9/openj9/issues/19460 - - -Xgcpolicy:optthruput -Xgcpolicy:optthruput -XX:ValueTypeFlatteningThreshold=99999 -XX:-EnableArrayFlattening @@ -142,7 +137,7 @@ ValueTypeArrayTestsJIT - https://github.com/eclipse-openj9/openj9/issues/19460 + https://github.com/eclipse-openj9/openj9/issues/19913 @@ -340,16 +335,12 @@ ValueTypeSystemArraycopyTests - - - https://github.com/eclipse-openj9/openj9/issues/19460 - - -Xint -Xint -Xgcpolicy:optthruput -XX:ValueTypeFlatteningThreshold=99999 -Xint -Xgcpolicy:optthruput -XX:ValueTypeFlatteningThreshold=99999 -XX:+EnableArrayFlattening - -Xjit:count=0 + + - -Xjit:count=1,disableAsyncCompilation,initialOptLevel=warm -Xgcpolicy:optthruput + $(JAVA_COMMAND) $(JVM_OPTIONS) \ --enable-preview \ diff --git a/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeArrayTests.java b/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeArrayTests.java index 86849f0a4c9..bf8719d7b8f 100644 --- a/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeArrayTests.java +++ b/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeArrayTests.java @@ -25,6 +25,8 @@ import static org.testng.Assert.*; import org.testng.annotations.Test; +import jdk.internal.value.CheckedType; +import jdk.internal.value.NormalCheckedType; import jdk.internal.value.NullRestrictedCheckedType; import jdk.internal.value.ValueClass; import jdk.internal.vm.annotation.ImplicitlyConstructible; @@ -228,7 +230,7 @@ static void assignDispatch(Object[] arr, int idx, Object src, int arrKind, int s new Class[] {null, null, null, null, null}, // All values can be assigned to Object[] new Class[] {null, ASE, null, null, null}, // ASE for SomeIface[] = Object new Class[] {null, ASE, ASE, null, ASE}, // ASE for PointV[] = PointPV, SomeIface - new Class[] {NPE, ASE, ASE, ASE, null}, // NPE for PointPV[] = null; ASE for PointPV[] = PointV + new Class[] {ASE, ASE, ASE, ASE, null}, // ASE for PointPV[] = null; ASE for PointPV[] = PointV }; /** @@ -328,7 +330,8 @@ static void runTest(Object[] arr, Object sourceVal, int staticArrayKind, int sta */ @Test(priority=1,invocationCount=2) static public void testValueTypeArrayAssignments() throws Throwable { - Object[][] testArrays = new Object[][] {new Object[2], new SomeIface[2], new PointV[2], new PointPV[2]}; + Object[][] testArrays = new Object[][] {new Object[2], new SomeIface[2], new PointV[2], + ValueClass.newArrayInstance(NullRestrictedCheckedType.of(PointPV.class), 2)}; int[] kinds = {OBJ_TYPE, IFACE_TYPE, VAL_TYPE, PRIM_TYPE}; Object[] vals = new Object[] {null, bogusIfaceObj, new PointV(1.0, 2.0), new PointPV(3.0, 4.0)}; @@ -753,11 +756,11 @@ static public void testStoreNullToNullRestrictedArrayElement1() throws Throwable try { arrayElementStoreNull(dstData, ARRAY_LENGTH/2); - } catch (NullPointerException npe) { + } catch (ArrayStoreException ase) { return; /* pass */ } - Assert.fail("Expect a NullPointerException. No exception or wrong kind of exception thrown"); + Assert.fail("Expect an ArrayStoreException. No exception or wrong kind of exception thrown"); } @Test(priority=1,invocationCount=2) @@ -769,10 +772,29 @@ static public void testStoreNullToNullRestrictedArrayElement2() throws Throwable try { arrayElementStore(dstData, ARRAY_LENGTH/2, obj); - } catch (NullPointerException npe) { + } catch (ArrayStoreException ase) { return; /* pass */ } - Assert.fail("Expect a NullPointerException. No exception or wrong kind of exception thrown"); + Assert.fail("Expect an ArrayStoreException. No exception or wrong kind of exception thrown"); + } + + @ImplicitlyConstructible + public static value class EmptyNullRestricted { + } + + /* This test passes with Xint, disable until all cases are passing. */ + /* Test JVM_IsNullRestrictedArray which is called by ValueClass.componentCheckedType */ + @Test + public static void testJVMIsNullRestrictedArray() { + EmptyNullRestricted[] nrArray = (EmptyNullRestricted[])ValueClass.newArrayInstance( + NullRestrictedCheckedType.of(EmptyNullRestricted.class), 4); + CheckedType nrType = ValueClass.componentCheckedType(nrArray); + assertTrue(nrType instanceof NullRestrictedCheckedType); + + EmptyNullRestricted[] normalArray = (EmptyNullRestricted[])ValueClass.newArrayInstance( + NormalCheckedType.of(EmptyNullRestricted.class), 4); + CheckedType normalType = ValueClass.componentCheckedType(normalArray); + assertTrue(normalType instanceof NormalCheckedType); } } 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 10a538fb3a2..9e31a1a8bd7 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 @@ -165,7 +165,7 @@ static private void initArrays() { } } - static private void initArraysForNPETest() { + static private void initArraysForASETest() { for (int i=0; i < ARRAY_SIZE; i++) { if (i >= ARRAY_SIZE/2) { ifArray3[i] = null; @@ -707,39 +707,39 @@ static public void testSystemArrayCopy21() throws Throwable { static public void testSystemArrayCopy22() throws Throwable { try { - initArraysForNPETest(); // ifArray3[ARRAY_SIZE/2] is NULL + initArraysForASETest(); // ifArray3[ARRAY_SIZE/2] is NULL testIFPVT(ifArray3, primitiveVtArrayDst); - } catch (java.lang.NullPointerException npe1) { + } catch (java.lang.ArrayStoreException ase1) { try { checkResultsPartial(ifArray3, primitiveVtArrayDst, ARRAY_SIZE/2); checkPVTArrayAfterException(ARRAY_SIZE/2); - initArraysForNPETest(); + initArraysForASETest(); testIFPVT(ifArray3, primitiveVtArrayDst); - } catch (java.lang.NullPointerException npe2) { + } catch (java.lang.ArrayStoreException ase2) { checkResultsPartial(ifArray3, primitiveVtArrayDst, ARRAY_SIZE/2); // pass return; } } - Assert.fail("Expect a NullPointerException. No exception or wrong kind of exception thrown"); + Assert.fail("Expect an ArrayStoreException. No exception or wrong kind of exception thrown"); } @Test(priority=1) static public void testSystemArrayCopy23() throws Throwable { try { - initArraysForNPETest(); // ifArray3[ARRAY_SIZE/2] is NULL + initArraysForASETest(); // ifArray3[ARRAY_SIZE/2] is NULL testIFIF(ifArray3, primitiveVtArrayDst); - } catch (java.lang.NullPointerException npe1) { + } catch (java.lang.ArrayStoreException ase1) { try { checkResultsPartial(ifArray3, primitiveVtArrayDst, ARRAY_SIZE/2); checkPVTArrayAfterException(ARRAY_SIZE/2); - initArraysForNPETest(); + initArraysForASETest(); testIFIF(ifArray3, primitiveVtArrayDst); - } catch (java.lang.NullPointerException npe2) { + } catch (java.lang.ArrayStoreException ase2) { checkResultsPartial(ifArray3, primitiveVtArrayDst, ARRAY_SIZE/2); checkPVTArrayAfterException(ARRAY_SIZE/2); // pass @@ -747,7 +747,7 @@ static public void testSystemArrayCopy23() throws Throwable { } } - Assert.fail("Expect a NullPointerException. No exception or wrong kind of exception thrown"); + Assert.fail("Expect a ArrayStoreException. No exception or wrong kind of exception thrown"); } @Test(priority=1) diff --git a/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeTests.java b/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeTests.java index 7e8b125200b..943ed42e8fe 100644 --- a/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeTests.java +++ b/test/functional/Valhalla/src_qtypes/org/openj9/test/lworld/ValueTypeTests.java @@ -572,22 +572,6 @@ static public void testDefaultValueWithNonValueType() throws Throwable { } catch (IncompatibleClassChangeError e) {} } - @Test(priority=4, invocationCount=2) - static public void testNullWritesOnNonNullableArrays() throws Throwable { - Object arrayObject = Array.newInstance(point2DClass, 3); - try { - Array.set(arrayObject, 1, null); - Assert.fail("Should throw NPE. Cant write null to arrays of valuetypes"); - } catch(NullPointerException e) {} - - Object arrayObject2 = Array.newInstance(String.class, 3); - try { - Array.set(arrayObject2, 1, null); - } catch(NullPointerException e) { - Assert.fail("Should not throw NPE. Can write null to arrays of identity types"); - } - } - @Test(priority=2, invocationCount=2) static public void testBasicACMPTestOnIdentityTypes() throws Throwable {