Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add hiddenInstanceFields to the VM snapshot #20759

Merged
merged 1 commit into from
Dec 5, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions runtime/oti/SnapshotFileFormat.h
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ typedef struct SavedJ9JavaVMStructures {
J9ClassLoader *systemClassLoader;
J9ClassLoader *extensionClassLoader;
J9ClassLoader *applicationClassLoader;
J9HiddenInstanceField *hiddenInstanceFields;
} SavedJ9JavaVMStructures;

/*
Expand Down
27 changes: 27 additions & 0 deletions runtime/vm/VMSnapshotImpl.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,6 +374,19 @@ VMSnapshotImpl::isImmortalClassLoader(J9ClassLoader *classLoader)
return isImmortal;
}

void
VMSnapshotImpl::saveHiddenInstanceFields()
{
_snapshotHeader->savedJavaVMStructs.hiddenInstanceFields = _vm->hiddenInstanceFields;
ThanHenderson marked this conversation as resolved.
Show resolved Hide resolved
}

void
VMSnapshotImpl::restoreHiddenInstanceFields()
{
_vm->hiddenInstanceFields = _snapshotHeader->savedJavaVMStructs.hiddenInstanceFields;
}


void
printAllSegments(J9MemorySegmentList *segmentList, J9JavaVM *_vm)
{
Expand Down Expand Up @@ -806,6 +819,7 @@ VMSnapshotImpl::saveJ9JavaVMStructures()
saveClassLoaderBlocks();
saveMemorySegments();
savePrimitiveAndArrayClasses();
saveHiddenInstanceFields();
_snapshotHeader->vm = _vm;
}

Expand All @@ -821,6 +835,7 @@ VMSnapshotImpl::restoreJ9JavaVMStructures()
restoreClassLoaderBlocks();
restoreMemorySegments();
restorePrimitiveAndArrayClasses();
restoreHiddenInstanceFields();

if (omrthread_monitor_init_with_name(&_vm->classMemorySegments->segmentMutex, 0, "VM class mem segment list")) {
success = false;
Expand All @@ -833,6 +848,17 @@ VMSnapshotImpl::restoreJ9JavaVMStructures()
return success;
}

/**
* Some data written to the snapshot cannot be freed at their usual points during VM shutdown.
* This function handles those data to ensure that they are freed after they are written to
* the snapshot.
*/
void
VMSnapshotImpl::freeJ9JavaVMStructures()
{
freeHiddenInstanceFieldsList(_vm);
}

bool
VMSnapshotImpl::writeSnapshotToFile()
{
Expand Down Expand Up @@ -1083,6 +1109,7 @@ teardownVMSnapshotImpl(J9JavaVM *javaVM)
} else {
vmSnapshotImpl->saveMemorySegments();
}
vmSnapshotImpl->freeJ9JavaVMStructures();
}

extern "C" void
Expand Down
3 changes: 3 additions & 0 deletions runtime/vm/VMSnapshotImpl.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,8 @@ class VMSnapshotImpl
bool restoreJ9JavaVMStructures();
void savePrimitiveAndArrayClasses();
bool isImmortalClassLoader(J9ClassLoader *classLoader);
void saveHiddenInstanceFields();
void restoreHiddenInstanceFields();
J9MemorySegmentList *copyUnPersistedMemorySegmentsToNewList(J9MemorySegmentList *oldMemorySegmentList);

protected:
Expand All @@ -118,6 +120,7 @@ class VMSnapshotImpl
void fixupJITVtable(J9Class *ramClass);
void fixupVMStructures();
void writeSnapshot();
void freeJ9JavaVMStructures();

void *subAllocateMemory(uintptr_t byteAmount, bool sub4G);
void *reallocateMemory(void *address, uintptr_t byteAmount, bool sub4G);
Expand Down
4 changes: 3 additions & 1 deletion runtime/vm/jvminit.c
Original file line number Diff line number Diff line change
Expand Up @@ -768,7 +768,9 @@ freeJavaVM(J9JavaVM * vm)
#endif /* J9VM_INTERP_ATOMIC_FREE_JNI_USES_FLUSH */

freeNativeMethodBindTable(vm);
freeHiddenInstanceFieldsList(vm);
if (!IS_SNAPSHOTTING_ENABLED(vm)) {
freeHiddenInstanceFieldsList(vm);
}
cleanupLockwordConfig(vm);
cleanupEnsureHashedConfig(vm);

Expand Down
67 changes: 63 additions & 4 deletions runtime/vm/resolvefield.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,9 @@ static J9ROMFieldShape* findFieldInTable(J9VMThread *vmThread, J9Class *clazz, U
static J9ROMFieldShape * findFieldInClass (J9VMThread *vmStruct, J9Class *clazz, U_8 *fieldName, UDATA fieldNameLength, U_8 *signature, UDATA signatureLength, UDATA *offsetOrAddress, J9Class **definingClass);
static J9ROMFieldShape* findFieldAndCheckVisibility (J9VMThread *vmStruct, J9Class *clazz, U_8 *fieldName, UDATA fieldNameLength, U_8 *signature, UDATA signatureLength, J9Class **definingClass, UDATA *offsetOrAddress, UDATA options, J9Class *sourceClass);
static J9ROMFieldShape* findField (J9VMThread *vmStruct, J9Class *clazz, U_8 *fieldName, UDATA fieldNameLength, U_8 *signature, UDATA signatureLength, J9Class **definingClass, UDATA *offsetOrAddress, UDATA options);
#if defined(J9VM_OPT_SNAPSHOTS)
static UDATA findHiddenInstanceFieldOffset(J9JavaVM *javaVM, const char *className, const char *fieldName, const char *signature);
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
VMINLINE static UDATA calculateJ9UTFSize(UDATA stringLength);
VMINLINE static UDATA calculateFakeJ9ROMFieldShapeSize(UDATA nameLength, UDATA signatureLength);
static void initFakeJ9ROMFieldShape(J9ROMFieldShape *shape, U_16 nameLength, U_8 *nameData, U_16 signatureLength, U_8 *signatureData);
Expand Down Expand Up @@ -238,7 +241,42 @@ findFieldInClass(J9VMThread *vmStruct, J9Class *clazz, U_8 *fieldName, UDATA fie
return shape;
}

#if defined(J9VM_OPT_SNAPSHOTS)
static UDATA
findHiddenInstanceFieldOffset(J9JavaVM *javaVM, const char *className, const char *fieldName, const char *signature)
{
J9HiddenInstanceField *field = javaVM->hiddenInstanceFields;
UDATA offset = UDATA_MAX;
const UDATA classNameLength = strlen(className);
const UDATA fieldNameLength = strlen(fieldName);
const UDATA signatureLength = strlen(signature);

while (NULL != field) {
J9UTF8 *currentClassName = field->className;
J9UTF8 *currentFieldName = J9ROMFIELDSHAPE_NAME(field->shape);
J9UTF8 *currentFieldSig = J9ROMFIELDSHAPE_SIGNATURE(field->shape);
const UDATA currentClassNameLength = J9UTF8_LENGTH(currentClassName);
const UDATA currentFieldNameLength = J9UTF8_LENGTH(currentFieldName);
const UDATA currentSignatureLength = J9UTF8_LENGTH(currentFieldSig);

if ((classNameLength == currentClassNameLength)
&& (fieldNameLength == currentFieldNameLength)
&& (signatureLength == currentSignatureLength)
) {
if (J9UTF8_DATA_EQUALS(J9UTF8_DATA(currentClassName), currentClassNameLength, className, classNameLength)
&& J9UTF8_DATA_EQUALS(J9UTF8_DATA(currentFieldName), currentFieldNameLength, fieldName, fieldNameLength)
&& J9UTF8_DATA_EQUALS(J9UTF8_DATA(currentFieldSig), currentSignatureLength, signature, signatureLength)
) {
offset = field->fieldOffset;
break;
}
}
field = field->next;
}

return offset;
}
#endif /* defined(J9VM_OPT_SNAPSHOTS) */

IDATA
instanceFieldOffset(J9VMThread *vmStruct, J9Class *clazz, U_8 *fieldName, UDATA fieldNameLength, U_8 *signature, UDATA signatureLength, J9Class **definingClass, UDATA *instanceField, UDATA options)
Expand Down Expand Up @@ -488,7 +526,9 @@ initializeHiddenInstanceFieldsList(J9JavaVM *vm)
goto destroyMutexAndCleanup;
}

vm->hiddenInstanceFields = NULL;
if (!IS_RESTORE_RUN(vm)) {
vm->hiddenInstanceFields = NULL;
}

exit:
return rc;
Expand Down Expand Up @@ -516,7 +556,15 @@ freeHiddenInstanceFieldsList(J9JavaVM *vm)
while (NULL != field) {
J9HiddenInstanceField *next = field->next;

j9mem_free_memory(field);
#if defined(J9VM_OPT_SNAPSHOTS)
if (IS_SNAPSHOT_RUN(vm)) {
VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(vm);
vmsnapshot_free_memory(field);
} else if (!IS_RESTORE_RUN(vm))
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
j9mem_free_memory(field);
}
field = next;
}
vm->hiddenInstanceFields = NULL;
Expand Down Expand Up @@ -579,10 +627,13 @@ addHiddenInstanceField(J9JavaVM *vm, const char *className, const char *fieldNam
if ((NULL != vm->systemClassLoader)
&& (NULL != hashClassTableAt(vm->systemClassLoader, (U_8*)className, classNameLength))
) {
/* By this point during a restore run, the hidden field is already added. */
#if defined(J9VM_OPT_SNAPSHOTS)
/* By this point during a restore run, the hidden field is already added. Just fill in the offset. */
if (IS_RESTORE_RUN(vm)) {
*offsetReturn = findHiddenInstanceFieldOffset(vm, className, fieldName, fieldSignature);
return 0;
}
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
return 2;
}

Expand All @@ -604,7 +655,15 @@ addHiddenInstanceField(J9JavaVM *vm, const char *className, const char *fieldNam
}

/* All is good - proceed to add the entry to the start of the list. */
field = (J9HiddenInstanceField *) j9mem_allocate_memory(neededSize, OMRMEM_CATEGORY_VM);
#if defined(J9VM_OPT_SNAPSHOTS)
if (IS_SNAPSHOT_RUN(vm)) {
VMSNAPSHOTIMPLPORT_ACCESS_FROM_JAVAVM(vm);
field = (J9HiddenInstanceField *)vmsnapshot_allocate_memory(neededSize, OMRMEM_CATEGORY_VM);
} else
#endif /* defined(J9VM_OPT_SNAPSHOTS) */
{
field = (J9HiddenInstanceField *)j9mem_allocate_memory(neededSize, OMRMEM_CATEGORY_VM);
}
if (NULL == field) {
omrthread_monitor_exit(vm->hiddenInstanceFieldsMutex);
return 4;
Expand Down