Skip to content

Commit

Permalink
Add hiddenInstanceFields to the VM snapshot
Browse files Browse the repository at this point in the history
On restore runs, hidden instance fields have already been added.
This patch adds the JavaVM::hiddenInstanceFields to the snapshot
and adds the functionality to find and fill-in the hidden
instance field's correct offset during restore runs.

Related: eclipse-openj9#20612
Signed-off-by: Nathan Henderson <[email protected]>
  • Loading branch information
ThanHenderson committed Dec 4, 2024
1 parent 249921b commit 12e8004
Show file tree
Hide file tree
Showing 5 changed files with 97 additions and 6 deletions.
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;
}

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
68 changes: 63 additions & 5 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,41 @@ 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 +525,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 +555,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 +626,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 +654,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

0 comments on commit 12e8004

Please sign in to comment.