diff --git a/runtime/gc_base/ContinuationObjectList.cpp b/runtime/gc_base/ContinuationObjectList.cpp index 9467928f288..12adad0589a 100644 --- a/runtime/gc_base/ContinuationObjectList.cpp +++ b/runtime/gc_base/ContinuationObjectList.cpp @@ -46,13 +46,22 @@ MM_ContinuationObjectList::MM_ContinuationObjectList() } MM_ContinuationObjectList * -MM_ContinuationObjectList::newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElements) +MM_ContinuationObjectList::newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElementsTotal, MM_ContinuationObjectList *listsToCopy, uintptr_t arrayElementsToCopy) { - MM_ContinuationObjectList *continuationObjectLists; + MM_ContinuationObjectList *continuationObjectLists = NULL; - continuationObjectLists = (MM_ContinuationObjectList *)env->getForge()->allocate(sizeof(MM_ContinuationObjectList) * arrayElements, MM_AllocationCategory::FIXED, J9_GET_CALLSITE()); + continuationObjectLists = (MM_ContinuationObjectList *)env->getForge()->allocate(sizeof(MM_ContinuationObjectList) * arrayElementsTotal, MM_AllocationCategory::FIXED, J9_GET_CALLSITE()); if (NULL != continuationObjectLists) { - for (uintptr_t index = 0; index < arrayElements; index++) { + Assert_MM_true(arrayElementsTotal >= arrayElementsToCopy); + /* Check whether a new array instance in being created from an existing array. If so, copy over the elements first. */ + if (arrayElementsToCopy > 0) { + for (uintptr_t index = 0; index < arrayElementsToCopy; index++) { + continuationObjectLists[index] = listsToCopy[index]; + continuationObjectLists[index].initialize(env); + } + } + + for (uintptr_t index = arrayElementsToCopy; index < arrayElementsTotal; index++) { new(&continuationObjectLists[index]) MM_ContinuationObjectList(); continuationObjectLists[index].initialize(env); } diff --git a/runtime/gc_base/ContinuationObjectList.hpp b/runtime/gc_base/ContinuationObjectList.hpp index 58718605650..88d83e2b025 100644 --- a/runtime/gc_base/ContinuationObjectList.hpp +++ b/runtime/gc_base/ContinuationObjectList.hpp @@ -57,11 +57,13 @@ class MM_ContinuationObjectList : public MM_BaseNonVirtual * Allocate and initialize an array of MM_ContinuationObjectList instances, resembling the functionality of operator new[]. * * @param env the current thread - * @param arrayElements the number of lists to create + * @param arrayElementsTotal the number of lists to create + * @param listsToCopy existing MM_ContinuationObjectList array to use to construct a new array of lists + * @param arrayElementsToCopy the size of the list array to be copied * * @return a pointer to the first list in the array, or NULL if we failed to allocate/init the array */ - static MM_ContinuationObjectList *newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElements); + static MM_ContinuationObjectList *newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElementsTotal, MM_ContinuationObjectList *listsToCopy, uintptr_t arrayElementsToCopy); bool initialize(MM_EnvironmentBase *env); /** diff --git a/runtime/gc_base/OwnableSynchronizerObjectList.cpp b/runtime/gc_base/OwnableSynchronizerObjectList.cpp index 109452fc955..be49a480fac 100644 --- a/runtime/gc_base/OwnableSynchronizerObjectList.cpp +++ b/runtime/gc_base/OwnableSynchronizerObjectList.cpp @@ -46,13 +46,22 @@ MM_OwnableSynchronizerObjectList::MM_OwnableSynchronizerObjectList() } MM_OwnableSynchronizerObjectList * -MM_OwnableSynchronizerObjectList::newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElements) +MM_OwnableSynchronizerObjectList::newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElementsTotal, MM_OwnableSynchronizerObjectList *listsToCopy, uintptr_t arrayElementsToCopy) { - MM_OwnableSynchronizerObjectList *ownableSynchronizerObjectLists; + MM_OwnableSynchronizerObjectList *ownableSynchronizerObjectLists = NULL; - ownableSynchronizerObjectLists = (MM_OwnableSynchronizerObjectList *)env->getForge()->allocate(sizeof(MM_OwnableSynchronizerObjectList) * arrayElements, MM_AllocationCategory::FIXED, J9_GET_CALLSITE()); + ownableSynchronizerObjectLists = (MM_OwnableSynchronizerObjectList *)env->getForge()->allocate(sizeof(MM_OwnableSynchronizerObjectList) * arrayElementsTotal, MM_AllocationCategory::FIXED, J9_GET_CALLSITE()); if (NULL != ownableSynchronizerObjectLists) { - for (uintptr_t index = 0; index < arrayElements; index++) { + Assert_MM_true(arrayElementsTotal >= arrayElementsToCopy); + /* Check whether a new array instance in being created from an existing array. If so, copy over the elements first. */ + if (arrayElementsToCopy > 0) { + for (uintptr_t index = 0; index < arrayElementsToCopy; index++) { + ownableSynchronizerObjectLists[index] = listsToCopy[index]; + ownableSynchronizerObjectLists[index].initialize(env); + } + } + + for (uintptr_t index = arrayElementsToCopy; index < arrayElementsTotal; index++) { new(&ownableSynchronizerObjectLists[index]) MM_OwnableSynchronizerObjectList(); ownableSynchronizerObjectLists[index].initialize(env); } diff --git a/runtime/gc_base/OwnableSynchronizerObjectList.hpp b/runtime/gc_base/OwnableSynchronizerObjectList.hpp index 849f530caaf..368f3050dc5 100644 --- a/runtime/gc_base/OwnableSynchronizerObjectList.hpp +++ b/runtime/gc_base/OwnableSynchronizerObjectList.hpp @@ -58,11 +58,13 @@ class MM_OwnableSynchronizerObjectList : public MM_BaseNonVirtual * Allocate and initialize an array of MM_OwnableSynchronizerObjectList instances, resembling the functionality of operator new[]. * * @param env the current thread - * @param arrayElements the number of lists to create + * @param arrayElementsTotal the number of lists to create + * @param listsToCopy existing MM_OwnableSynchronizerObjectList array to use to construct a new array of lists + * @param arrayElementsToCopy the size of the list array to be copied * * @return a pointer to the first list in the array, or NULL if we failed to allocate/init the array */ - static MM_OwnableSynchronizerObjectList *newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElements); + static MM_OwnableSynchronizerObjectList *newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElementsTotal, MM_OwnableSynchronizerObjectList *listsToCopy, uintptr_t arrayElementsToCopy); bool initialize(MM_EnvironmentBase *env); /** diff --git a/runtime/gc_base/ReferenceObjectList.cpp b/runtime/gc_base/ReferenceObjectList.cpp index 31224977d5e..1e90c0feb5a 100644 --- a/runtime/gc_base/ReferenceObjectList.cpp +++ b/runtime/gc_base/ReferenceObjectList.cpp @@ -45,13 +45,22 @@ MM_ReferenceObjectList::MM_ReferenceObjectList() } MM_ReferenceObjectList * -MM_ReferenceObjectList::newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElements) +MM_ReferenceObjectList::newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElementsTotal, MM_ReferenceObjectList *listsToCopy, uintptr_t arrayElementsToCopy) { - MM_ReferenceObjectList *referenceObjectLists; + MM_ReferenceObjectList *referenceObjectLists = NULL; - referenceObjectLists = (MM_ReferenceObjectList *)env->getForge()->allocate(sizeof(MM_ReferenceObjectList) * arrayElements, MM_AllocationCategory::FIXED, J9_GET_CALLSITE()); + referenceObjectLists = (MM_ReferenceObjectList *)env->getForge()->allocate(sizeof(MM_ReferenceObjectList) * arrayElementsTotal, MM_AllocationCategory::FIXED, J9_GET_CALLSITE()); if (NULL != referenceObjectLists) { - for (uintptr_t index = 0; index < arrayElements; index++) { + Assert_MM_true(arrayElementsTotal >= arrayElementsToCopy); + /* Check whether a new array instance in being created from an existing array. If so, copy over the elements first. */ + if (arrayElementsToCopy > 0) { + for (uintptr_t index = 0; index < arrayElementsToCopy; index++) { + referenceObjectLists[index] = listsToCopy[index]; + referenceObjectLists[index].initialize(env); + } + } + + for (uintptr_t index = arrayElementsToCopy; index < arrayElementsTotal; index++) { new(&referenceObjectLists[index]) MM_ReferenceObjectList(); referenceObjectLists[index].initialize(env); } diff --git a/runtime/gc_base/ReferenceObjectList.hpp b/runtime/gc_base/ReferenceObjectList.hpp index 7cef0adeadd..69895f06ce4 100644 --- a/runtime/gc_base/ReferenceObjectList.hpp +++ b/runtime/gc_base/ReferenceObjectList.hpp @@ -55,11 +55,13 @@ class MM_ReferenceObjectList : public MM_BaseNonVirtual * Allocate and initialize an array of MM_ReferenceObjectList instances, resembling the functionality of operator new[]. * * @param env the current thread - * @param arrayElements the number of lists to create + * @param arrayElementsTotal the number of lists to create + * @param listsToCopy existing MM_ReferenceObjectList array to use to construct a new array of lists + * @param arrayElementsToCopy the size of the list array to be copied * * @return a pointer to the first list in the array, or NULL if we failed to allocate/init the array */ - static MM_ReferenceObjectList *newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElements); + static MM_ReferenceObjectList *newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElementsTotal, MM_ReferenceObjectList *listsToCopy, uintptr_t arrayElementsToCopy); bool initialize(MM_EnvironmentBase *env) { return true; } /** diff --git a/runtime/gc_base/UnfinalizedObjectList.cpp b/runtime/gc_base/UnfinalizedObjectList.cpp index d698e132d71..bb4a0b32d67 100644 --- a/runtime/gc_base/UnfinalizedObjectList.cpp +++ b/runtime/gc_base/UnfinalizedObjectList.cpp @@ -43,13 +43,22 @@ MM_UnfinalizedObjectList::MM_UnfinalizedObjectList() } MM_UnfinalizedObjectList * -MM_UnfinalizedObjectList::newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElements) +MM_UnfinalizedObjectList::newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElementsTotal, MM_UnfinalizedObjectList *listsToCopy, uintptr_t arrayElementsToCopy) { - MM_UnfinalizedObjectList *unfinalizedObjectLists; + MM_UnfinalizedObjectList *unfinalizedObjectLists = NULL; - unfinalizedObjectLists = (MM_UnfinalizedObjectList *)env->getForge()->allocate(sizeof(MM_UnfinalizedObjectList) * arrayElements, MM_AllocationCategory::FIXED, J9_GET_CALLSITE()); + unfinalizedObjectLists = (MM_UnfinalizedObjectList *)env->getForge()->allocate(sizeof(MM_UnfinalizedObjectList) * arrayElementsTotal, MM_AllocationCategory::FIXED, J9_GET_CALLSITE()); if (NULL != unfinalizedObjectLists) { - for (uintptr_t index = 0; index < arrayElements; index++) { + Assert_MM_true(arrayElementsTotal >= arrayElementsToCopy); + /* Check whether a new array instance in being created from an existing array. If so, copy over the elements first. */ + if (arrayElementsToCopy > 0) { + for (uintptr_t index = 0; index < arrayElementsToCopy; index++) { + unfinalizedObjectLists[index] = listsToCopy[index]; + unfinalizedObjectLists[index].initialize(env); + } + } + + for (uintptr_t index = arrayElementsToCopy; index < arrayElementsTotal; index++) { new(&unfinalizedObjectLists[index]) MM_UnfinalizedObjectList(); unfinalizedObjectLists[index].initialize(env); } diff --git a/runtime/gc_base/UnfinalizedObjectList.hpp b/runtime/gc_base/UnfinalizedObjectList.hpp index 7ded01e2fd1..68b499a9d19 100644 --- a/runtime/gc_base/UnfinalizedObjectList.hpp +++ b/runtime/gc_base/UnfinalizedObjectList.hpp @@ -54,11 +54,13 @@ class MM_UnfinalizedObjectList : public MM_BaseNonVirtual * Allocate and initialize an array of MM_UnfinalizedObjectList instances, resembling the functionality of operator new[]. * * @param env the current thread - * @param arrayElements the number of lists to create + * @param arrayElementsTotal the number of lists to create + * @param listsToCopy existing MM_UnfinalizedObjectList array to use to construct a new array of lists + * @param arrayElementsToCopy the size of the list array to be copied * * @return a pointer to the first list in the array, or NULL if we failed to allocate/init the array */ - static MM_UnfinalizedObjectList *newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElements); + static MM_UnfinalizedObjectList *newInstanceArray(MM_EnvironmentBase *env, uintptr_t arrayElementsTotal, MM_UnfinalizedObjectList *listsToCopy, uintptr_t arrayElementsToCopy); bool initialize(MM_EnvironmentBase *env); /** diff --git a/runtime/gc_glue_java/ConfigurationDelegate.hpp b/runtime/gc_glue_java/ConfigurationDelegate.hpp index 8995ce852e1..5313235d5d7 100644 --- a/runtime/gc_glue_java/ConfigurationDelegate.hpp +++ b/runtime/gc_glue_java/ConfigurationDelegate.hpp @@ -39,6 +39,7 @@ #include "HeapRegionDescriptor.hpp" #include "HeapRegionDescriptorStandardExtension.hpp" #include "HeapRegionManager.hpp" +#include "HeapRegionIterator.hpp" #include "ObjectAccessBarrier.hpp" #include "ObjectAllocationInterface.hpp" #include "StringTable.hpp" @@ -154,6 +155,40 @@ class MM_ConfigurationDelegate return regionExtension; } +#if defined(J9VM_OPT_CRIU_SUPPORT) + void + reinitializeGCParameters(MM_EnvironmentBase* env) + { + /* reinitialize the size of Local Object Buffers */ + uintptr_t objectListFragmentCount = (4 * _extensions->gcThreadCount) + 4; + _extensions->objectListFragmentCount = OMR_MAX(_extensions->objectListFragmentCount, objectListFragmentCount); + } + + bool + reinitializeForRestore(MM_EnvironmentBase* env) + { + Assert_MM_true(_extensions->isStandardGC()); + + reinitializeGCParameters(env); + + MM_HeapRegionDescriptor *region = NULL; + GC_HeapRegionIterator regionIterator(_extensions->heap->getHeapRegionManager()); + + _extensions->unfinalizedObjectLists = NULL; + _extensions->setOwnableSynchronizerObjectLists(NULL); + _extensions->setContinuationObjectLists(NULL); + + while (NULL != (region = regionIterator.nextRegion())) { + MM_HeapRegionDescriptorStandardExtension *regionExtension = getHeapRegionDescriptorStandardExtension(env, region); + if (!regionExtension->reinitializeForRestore(env)) { + return false; + } + } + + return true; + } +#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ + bool initializeHeapRegionDescriptorExtension(MM_EnvironmentBase *env, MM_HeapRegionDescriptor *region) { diff --git a/runtime/gc_glue_java/HeapRegionDescriptorStandardExtension.hpp b/runtime/gc_glue_java/HeapRegionDescriptorStandardExtension.hpp index 8e3b57c607e..2533bf79996 100644 --- a/runtime/gc_glue_java/HeapRegionDescriptorStandardExtension.hpp +++ b/runtime/gc_glue_java/HeapRegionDescriptorStandardExtension.hpp @@ -69,24 +69,60 @@ class MM_HeapRegionDescriptorStandardExtension : public MM_BaseNonVirtual bool initialize(MM_EnvironmentBase *env) { - if (NULL == (_unfinalizedObjectLists = MM_UnfinalizedObjectList::newInstanceArray(env, _maxListIndex))) { + if ((NULL == (_unfinalizedObjectLists = MM_UnfinalizedObjectList::newInstanceArray(env, _maxListIndex, NULL, 0))) + || (NULL == (_ownableSynchronizerObjectLists = MM_OwnableSynchronizerObjectList::newInstanceArray(env, _maxListIndex, NULL, 0))) + || (NULL == (_continuationObjectLists = MM_ContinuationObjectList::newInstanceArray(env, _maxListIndex, NULL, 0))) + || (NULL == (_referenceObjectLists = MM_ReferenceObjectList::newInstanceArray(env, _maxListIndex, NULL, 0))) + ) { + tearDown(env); return false; } - if (NULL == (_ownableSynchronizerObjectLists = MM_OwnableSynchronizerObjectList::newInstanceArray(env, _maxListIndex))) { - return false; - } + return true; + } - if (NULL == (_continuationObjectLists = MM_ContinuationObjectList::newInstanceArray(env, _maxListIndex))) { - return false; - } +#if defined(J9VM_OPT_CRIU_SUPPORT) + bool + reinitializeForRestore(MM_EnvironmentBase* env) + { + MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env); - if (NULL == (_referenceObjectLists = MM_ReferenceObjectList::newInstanceArray(env, _maxListIndex))) { - return false; + MM_UnfinalizedObjectList *newUnfinalizedObjectLists = NULL; + MM_OwnableSynchronizerObjectList *newOwnableSynchronizerObjectLists = NULL; + MM_ContinuationObjectList *newContinuationObjectLists = NULL; + MM_ReferenceObjectList *newReferenceObjectLists = NULL; + + uintptr_t newListCount = extensions->gcThreadCount; + + Assert_MM_true(_maxListIndex > 0); + + if (newListCount > _maxListIndex) { + if ((NULL == (newUnfinalizedObjectLists = MM_UnfinalizedObjectList::newInstanceArray(env, newListCount, _unfinalizedObjectLists, _maxListIndex))) + || (NULL == (newOwnableSynchronizerObjectLists = MM_OwnableSynchronizerObjectList::newInstanceArray(env, newListCount, _ownableSynchronizerObjectLists, _maxListIndex))) + || (NULL == (newContinuationObjectLists = MM_ContinuationObjectList::newInstanceArray(env, newListCount, _continuationObjectLists, _maxListIndex))) + || (NULL == (newReferenceObjectLists = MM_ReferenceObjectList::newInstanceArray(env, newListCount, _referenceObjectLists, _maxListIndex))) + ) { + goto failed; + } + + tearDown(env); + + _unfinalizedObjectLists = newUnfinalizedObjectLists; + _ownableSynchronizerObjectLists = newOwnableSynchronizerObjectLists; + _continuationObjectLists = newContinuationObjectLists; + _referenceObjectLists = newReferenceObjectLists; + + _maxListIndex = newListCount; } return true; + +failed: + releaseLists(env, &newUnfinalizedObjectLists, &newOwnableSynchronizerObjectLists, &newContinuationObjectLists, &newReferenceObjectLists); + + return false; } +#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */ void kill(MM_EnvironmentBase *env) @@ -98,24 +134,30 @@ class MM_HeapRegionDescriptorStandardExtension : public MM_BaseNonVirtual void tearDown(MM_EnvironmentBase *env) { - if (NULL != _unfinalizedObjectLists) { - env->getForge()->free(_unfinalizedObjectLists); - _unfinalizedObjectLists = NULL; + releaseLists(env, &_unfinalizedObjectLists, &_ownableSynchronizerObjectLists, &_continuationObjectLists, &_referenceObjectLists); + } + + void + releaseLists(MM_EnvironmentBase *env, MM_UnfinalizedObjectList **unfinalizedObjectLists, MM_OwnableSynchronizerObjectList **ownableSynchronizerObjectLists, MM_ContinuationObjectList **continuationObjectLists, MM_ReferenceObjectList **referenceObjectLists) + { + if (NULL != *unfinalizedObjectLists) { + env->getForge()->free(*unfinalizedObjectLists); + *unfinalizedObjectLists = NULL; } - if (NULL != _ownableSynchronizerObjectLists) { - env->getForge()->free(_ownableSynchronizerObjectLists); - _ownableSynchronizerObjectLists = NULL; + if (NULL != *ownableSynchronizerObjectLists) { + env->getForge()->free(*ownableSynchronizerObjectLists); + *ownableSynchronizerObjectLists = NULL; } - if (NULL != _continuationObjectLists) { - env->getForge()->free(_continuationObjectLists); - _continuationObjectLists = NULL; + if (NULL != *continuationObjectLists) { + env->getForge()->free(*continuationObjectLists); + *continuationObjectLists = NULL; } - if (NULL != _referenceObjectLists) { - env->getForge()->free(_referenceObjectLists); - _referenceObjectLists = NULL; + if (NULL != *referenceObjectLists) { + env->getForge()->free(*referenceObjectLists); + *referenceObjectLists = NULL; } }