Skip to content

Conversation

@AditiS11
Copy link

@AditiS11 AditiS11 commented Dec 10, 2025

Related: #22642
These changes aim to align the code with JEP 401 strict field initialization. It includes:
-Remove the J9ClassContainsUnflattenedFlattenables flag.
-Remove default value initialization.
-Re-enable disabled tests.

Signed-off-by: Aditi Srinivas M Aditi.Srini@ibm.com

@AditiS11 AditiS11 requested a review from dsouzai as a code owner December 10, 2025 11:35
@AditiS11 AditiS11 marked this pull request as draft December 10, 2025 17:34
@AditiS11 AditiS11 marked this pull request as ready for review December 11, 2025 06:14
@hangshao0 hangshao0 added comp:vm project:valhalla Used to track Project Valhalla related work comp:test labels Dec 11, 2025
@hangshao0 hangshao0 requested review from theresa-m and removed request for dsouzai December 11, 2025 15:24
@hzongaro hzongaro added comp:jit comp:jit:aot comp:jitserver Artifacts related to JIT-as-a-Service project labels Dec 12, 2025
@hzongaro hzongaro requested review from a7ehuo and hzongaro December 12, 2025 18:03
return "TR_VirtualRamMethodConst";
case TR_ClassAddress:
return "TR_ClassAddress";
case TR_StaticDefaultValueInstance:
Copy link
Contributor

@theresa-m theresa-m Dec 11, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see some uses of TR_StaticDefaultValueInstance in OMR as well that should be removed. You can do this in a pull request after this one has been merged to avoid compilation issues.

TR::SymbolReference * findOrFabricateFlattenedArrayElementFieldShadowSymbol(TR_OpaqueClassBlock *arrayComponentClass, TR::DataType type, int32_t fieldOffset, bool isPrivate, const char *fieldName, const char *fieldSignature);

/** \brief
* Returns a symbol reference for default value instance of value class.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The comment for this method can also be removed.

TR::SymbolReference *
J9::SymbolReferenceTable::findOrCreateDefaultValueSymbolRef(void *defaultValueSlotAddress, int32_t cpIndex)
{
ListIterator<TR::SymbolReference> i(&_defaultValueAddressSlotSymbolRefs);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove other references to _defaultValueAddressSlotSymbolRefs

{
auto recv = client->getRecvData<TR_OpaqueClassBlock *>();
auto clazz = std::get<0>(recv);
client->write(response, TR::Compiler->cls.getDefaultValueSlotAddress(comp, clazz));
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Remove getDefaultValueSlotAddress from J9ClassEnv.hpp.

if (clazz->initializeStatus != 1)
return false;

// Cannot inline the allocation if the class is an interface, abstract,
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please update this comment.

if (skipUnflattenedFlattenableCheck || J9_ARE_NO_BITS_SET(clazz->classFlags, J9ClassContainsUnflattenedFlattenables))
#endif /* J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES */
{
instance = _objectAllocate.inlineAllocateObject(_currentThread, clazz, initializeSlots, memoryBarrier);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is still needed.

if (J9_ARE_NO_BITS_SET(arrayClass->classFlags, J9ClassContainsUnflattenedFlattenables))
#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */
{
instance = VM_VMHelpers::inlineAllocateIndexableObject(_currentThread, &_objectAllocate, arrayClass, size, initializeSlots, memoryBarrier, sizeCheck);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line is still needed.

if (J9_ARE_NO_BITS_SET(resolvedClass->classFlags, J9ClassContainsUnflattenedFlattenables))
#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */
{
instance = _objectAllocate.inlineAllocateObject(_currentThread, resolvedClass);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line can stay.

if (J9_ARE_NO_BITS_SET(arrayClass->classFlags, J9ClassContainsUnflattenedFlattenables))
#endif /* defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES) */
{
instance = VM_VMHelpers::inlineAllocateIndexableObject(_currentThread, &_objectAllocate, arrayClass, (U_32) size);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line can stay.

if (NULL != obj && NULL != clz) {
J9Class *clzJ9Class = J9VM_J9CLASS_FROM_HEAPCLASS(_currentThread, clz);

if (J9_IS_J9CLASS_PRIMITIVE_VALUETYPE(clzJ9Class)) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please leave this and line 4546 unchanged for now. getFlattenedFieldAtOffset only handles flattened cases and with the introduction of null-restricted types we can't tell if its flattened just from the J9Class.

Copy link
Author

@AditiS11 AditiS11 Dec 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I made this change as several ValueTypeUnsafe tests (eg: testGetValuesOfObject) were failing with a NullPointerException as Unsafe.getValue currently returns null for non-primitive value types.
Broadening the check to J9_IS_J9CLASS_VALUETYPE allows the tests to pass.

For eg:

FAILED: testGetValuesOfObject
java.lang.NullPointerException
	at org.openj9.test.lworld.ValueTypeUnsafeTests.testGetValuesOfObject(ValueTypeUnsafeTests.java:306)
	at java.base/jdk.internal.reflect.DirectMethodHandleAccessor.invoke(DirectMethodHandleAccessor.java:104)
	at java.base/java.lang.reflect.Method.invoke(Method.java:571)
	at org.testng.internal.MethodInvocationHelper.invokeMethod(MethodInvocationHelper.java:124)
	at org.testng.internal.Invoker.invokeMethod(Invoker.java:580)
	at org.testng.internal.Invoker.invokeTestMethod(Invoker.java:716)
	at org.testng.internal.Invoker.invokeTestMethods(Invoker.java:988)
	at org.testng.internal.TestMethodWorker.invokeTestMethods(TestMethodWorker.java:125)
	at org.testng.internal.TestMethodWorker.run(TestMethodWorker.java:109)
	at org.testng.TestRunner.privateRun(TestRunner.java:648)
	at org.testng.TestRunner.run(TestRunner.java:505)
	at org.testng.SuiteRunner.runTest(SuiteRunner.java:455)
	at org.testng.SuiteRunner.runSequentially(SuiteRunner.java:450)
	at org.testng.SuiteRunner.privateRun(SuiteRunner.java:415)
	at org.testng.SuiteRunner.run(SuiteRunner.java:364)
	at org.testng.SuiteRunnerWorker.runSuite(SuiteRunnerWorker.java:52)
	at org.testng.SuiteRunnerWorker.run(SuiteRunnerWorker.java:84)
	at org.testng.TestNG.runSuitesSequentially(TestNG.java:1208)
	at org.testng.TestNG.runSuitesLocally(TestNG.java:1137)
	at org.testng.TestNG.runSuites(TestNG.java:1049)
	at org.testng.TestNG.run(TestNG.java:1017)
	at org.testng.TestNG.privateMain(TestNG.java:1354)
	at org.testng.TestNG.main(TestNG.java:1323)
	```

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I see, this was passing before because J9ClassAllowsInitialDefaultValue and J9ClassIsPrimitiveValueType flags shared the same value.

VM_ValueTypeHelpers::getFlattenedFieldAtOffset says it should only be used with flattened fields but it clearly hasn't been used that way for a while. I don't see why it needs to be used for only flattened fields though is there something I'm missing @hangshao0 ?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like getValue is replaced now upstream https://bugs.openjdk.org/browse/JDK-8373374

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't see why it needs to be used for only flattened fields though is there something I'm missing @hangshao0 ?

getFlattenedFieldAtOffset() calls copyObjectFields() to copy the data. It copies from the given offset for X bytes, where X is the size of the field type when it is flattened. So it can only been used on flattened fields.

UDATA limit = J9CLASS_UNPADDED_INSTANCE_SIZE(objectClass);

#define J9CLASS_UNPADDED_INSTANCE_SIZE(clazz) J9_VALUETYPE_FLATTENED_SIZE(clazz)

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Okay. I think for now the getValue and putValue code should remain the same and the tests that use it should be disabled. Once the extensions repo has been updated to include getFlatValue/putFlatValue instead of getValue/putValue the api and tests can be updated.

Do you mind creating an issue for this @AditiS11 ?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sure will do it.

Copy link
Contributor

@a7ehuo a7ehuo left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for the change @AditiS11! I took a look at files under runtime/compiler.

Here are my comments. Meanwhile, the commit message should follow the format stated in OpenJ9 CONTRIBUTING.md and it is especially missing Signed-off-by: Full Name <email>.

openj9/CONTRIBUTING.md

Lines 116 to 136 in ec64be7

When a commit has related issues or commits, explain the relation in the message
body. When appropriate, use the keywords described in the following help article
to automatically close issues.
https://help.github.com/articles/closing-issues-using-keywords/
For example:
```
Correct race in frobnicator
This patch eliminates the race condition in issue #1234.
Fixes: #1234
```
Sign off on your commit in the footer. By doing this, you assert original
authorship of the commit and that you are permitted to contribute it. This can
be automatically added to your commit by passing `-s` to `git commit`, or by
manually adding the following line to the footer of the commit.
```
Signed-off-by: Full Name <email>

if (candidate->_kind == TR::New)
{
TR_OpaqueClassBlock *clazz = (TR_OpaqueClassBlock *)candidate->_node->getFirstChild()->getSymbol()->getStaticSymbol()->getStaticAddress();

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I believe this whole if branch should be removed.

         // Primitive value type fields of objects created with a NEW bytecode must be initialized
         // with their default values.  EA is not yet set up to perform such iniitialization
         // if the value type's own fields have not been inlined into the class that
         // has a field of that type, so remove the candidate from consideration.
         if (candidate->_kind == TR::New)
            {
            TR_OpaqueClassBlock *clazz = (TR_OpaqueClassBlock *)candidate->_node->getFirstChild()->getSymbol()->getStaticSymbol()->getStaticAddress();

            if (!TR::Compiler->cls.isZeroInitializable(clazz))
               {
               logprintf(trace(), log,
                  "   Fail [%p] because the candidate is not zero initializable (that is, it has a field of a primitive value type whose fields have not been inlined into this candidate's class)\n",
                  candidate->_node);
               rememoize(candidate);
               _candidates.remove(candidate);
               continue;
               }
            }

if(!(std::get<0>(classInfoTuple).empty()))
{
romClass = JITServerHelpers::romClassFromString(std::get<0>(classInfoTuple), std::get<25>(classInfoTuple), clientSession->persistentMemory());
romClass = JITServerHelpers::romClassFromString(std::get<0>(classInfoTuple), std::get<24>(classInfoTuple), clientSession->persistentMemory());
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These changes in JITServer would require to update MINOR_NUMBER in CommunicationStream.hpp

* `false` otherwise (that is, if the class has value type fields whose fields have not
* been inlined)
*/
bool isZeroInitializable(TR_OpaqueClassBlock *clazz);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getDefaultValueSlotAddress needs to be removed in this file too

return "TR_VirtualRamMethodConst";
case TR_ClassAddress:
return "TR_ClassAddress";
case TR_StaticDefaultValueInstance:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The reference to isStaticDefaultValueInstance() in J9SymbolReference.cpp can be removed

Comment on lines -6368 to -6369
if ((clazz->romClass->modifiers & (J9AccAbstract | J9AccInterface))
|| (clazz->classFlags & J9ClassContainsUnflattenedFlattenables))
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

extra bracket

if (clazz->romClass->modifiers & (J9AccAbstract | J9AccInterface))

The comments above the code should be updated to reflect the removed code

    // Can not inline the allocation if the class is an interface or abstract

{
uintptr_t classFlags = 0;
JITServerHelpers::getAndCacheRAMClassInfo((J9Class*)clazz, _compInfoPT->getClientData(), stream, JITServerHelpers::CLASSINFO_CLASS_FLAGS, (void*)&classFlags);
return (classFlags & J9ClassContainsUnflattenedFlattenables) ? false : true;
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Maybe something as below after removing the check on J9ClassContainsUnflattenedFlattenables:

    if (isClassInitialized)
       return ((modifiers & (J9AccAbstract | J9AccInterface )) ? false : true);

@AditiS11 AditiS11 force-pushed the implicit_3 branch 2 times, most recently from 5a1c307 to 39c0cd0 Compare December 23, 2025 11:43
break;
}

return NULL;
Copy link
Contributor

@theresa-m theresa-m Dec 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This whole iterator can be removed since it will never return a value.

allocateObject(REGISTER_ARGS_LIST, J9Class *clazz, bool initializeSlots = true, bool memoryBarrier = true)
{
j9object_t instance = NULL;
#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line and line 1140 can be removed.

allocateIndexableObject(REGISTER_ARGS_LIST, J9Class *arrayClass, U_32 size, bool initializeSlots = true, bool memoryBarrier = true, bool sizeCheck = true)
{
j9object_t instance = NULL;
#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This line and 1169 can be removed.

if ((NULL != resolvedClass) && J9ROMCLASS_ALLOCATES_VIA_NEW(resolvedClass->romClass)) {
if (!VM_VMHelpers::classRequiresInitialization(_currentThread, resolvedClass)) {
j9object_t instance = NULL;
#if defined(J9VM_OPT_VALHALLA_FLATTENABLE_VALUE_TYPES)
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Also here and line 8918.

Related: eclipse-openj9#22642
Remove the J9ClassContainsUnflattenedFlattenables flag
Remove default value initialization.
Re-enable disabled tests

Signed-off-by: Aditi Srinivas M <Aditi.Srini@ibm.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

comp:jit:aot comp:jit comp:jitserver Artifacts related to JIT-as-a-Service project comp:test comp:vm project:valhalla Used to track Project Valhalla related work

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants