From 76e9d65ec38f452f742de6112b32dee9aa7372d5 Mon Sep 17 00:00:00 2001 From: Salman Rana Date: Tue, 7 Jan 2020 14:44:54 -0500 Subject: [PATCH] Fixes https://github.com/eclipse/openj9/issues/8020 - MarkMap init consolidated MarkMap init logic has been merged to resolve the timing hole outlined in https://github.com/eclipse/openj9/issues/8020. MarkMap init is dependent on Concurrent State of the global collector, with the init logic split between `heapAddRange` and `heapReconfigured`, any changes in states between the two may leave expanded mark map uninited. Hence, the decision to init (`setMarkBitsInRange`) the mark map has been moved from `heapAddRange` to `heapReconfigured` which is where we determine if an update to the init table is required (`tuneToHeap`/`determineInitWork`). As a result, init is no longer affected by the change in Concurrent state and we eliminate the timing window. This guarantee that the MarkMap will be inited, either on the spot or afterwards by updating the init table. - Introduced HeapReconfigReason and reworked heapReconfigred API heapReconfigred now distinguishes different reasons for reconfiguration (Expand, contract, etc), this functionality is required for the Mark Map init changes, specifically for Gencon and it is used when Scavenger resizes tenure _(PhysicalSubArenaVirtualMemorySemiSpace)_ or global collecter preforms a resize _(PhysicalSubArenaVirtualMemoryFlat)_. At the time, this is new information is only consumed by Concurrent Global Collecter (ConcurrentGC.cpp), for policies making use of other collectors the HeapReconfigReason param defaults to `NONE`. The Reconfig reasons are dealt in the following ways by Concurrent Global Collector: - We should never end up in `heapReconfigured` with `RECONFIG_NONE` reason - `RECONFIG_CONTRACT` signifies that `heapRemoveRange` had taken place, in which case, we just need to update init table (`tuneToHeap`) when Concurrent is Off, otherwise just `adjustTraceTargets` - If `heapAddRange` takes place then `heapReconfigured` is called with `RECONFIG_EXPAND` and have have two different cases: 1) heapAddRange was successful (return true), heap reconfig should be provided with `lowAddress` & `highAddress` which will be used to init mark map 2) heapAddRange returns false, signifies a failed `heapAddRange`, address params are expected to be NULL, in which case mark map won't be inited but we'll still either `tuneToHeap` or `adjustTraceTarget`. Signed-off-by: Salman Rana --- gc/base/Collector.hpp | 2 +- gc/base/GCExtensionsBase.hpp | 2 +- gc/base/Heap.cpp | 4 +- gc/base/Heap.hpp | 2 +- gc/base/MemorySpace.cpp | 4 +- gc/base/MemorySpace.hpp | 2 +- gc/base/MemorySubSpace.cpp | 8 +- gc/base/MemorySubSpace.hpp | 2 +- gc/base/PhysicalSubArenaVirtualMemoryFlat.cpp | 26 ++++--- .../segregated/MemorySubSpaceSegregated.cpp | 4 +- .../segregated/MemorySubSpaceSegregated.hpp | 2 +- gc/base/segregated/SegregatedGC.cpp | 2 +- gc/base/segregated/SegregatedGC.hpp | 2 +- gc/base/standard/ConcurrentCardTable.cpp | 2 +- gc/base/standard/ConcurrentCardTable.hpp | 2 +- gc/base/standard/ConcurrentGC.cpp | 78 ++++++++++--------- gc/base/standard/ConcurrentGC.hpp | 2 +- .../ConcurrentGCIncrementalUpdate.cpp | 1 - gc/base/standard/ParallelGlobalGC.cpp | 4 +- gc/base/standard/ParallelGlobalGC.hpp | 2 +- gc/base/standard/ParallelSweepScheme.cpp | 2 +- gc/base/standard/ParallelSweepScheme.hpp | 2 +- ...PhysicalSubArenaVirtualMemorySemiSpace.cpp | 52 +++++++++---- gc/base/standard/Scavenger.cpp | 2 +- gc/base/standard/Scavenger.hpp | 2 +- gc/startup/omrgcstartup.cpp | 2 +- include_core/omrgcconsts.h | 8 ++ 27 files changed, 135 insertions(+), 88 deletions(-) diff --git a/gc/base/Collector.hpp b/gc/base/Collector.hpp index 3cccf07faf3..ce2baacddc9 100644 --- a/gc/base/Collector.hpp +++ b/gc/base/Collector.hpp @@ -194,7 +194,7 @@ class MM_Collector : public MM_BaseVirtual * moved from one subspace to another. * @param env[in] The thread which performed the change in heap geometry */ - virtual void heapReconfigured(MM_EnvironmentBase* env) = 0; + virtual void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL) = 0; /** * Post collection broadcast event, indicating that the collection has been completed. diff --git a/gc/base/GCExtensionsBase.hpp b/gc/base/GCExtensionsBase.hpp index 7bcb19fa15a..fc1ed873dcb 100644 --- a/gc/base/GCExtensionsBase.hpp +++ b/gc/base/GCExtensionsBase.hpp @@ -1509,7 +1509,7 @@ class MM_GCExtensionsBase : public MM_BaseVirtual { #if defined(OMR_GC_CONCURRENT_SCAVENGER) , softwareRangeCheckReadBarrier(false) , concurrentScavenger(false) - , concurrentScavengerForced(false) + , concurrentScavengerForced(true) , concurrentScavengerHWSupport(false) , concurrentScavengerBackgroundThreads(1) , concurrentScavengerBackgroundThreadsForced(false) diff --git a/gc/base/Heap.cpp b/gc/base/Heap.cpp index a066e537fc5..ac7235e9e37 100644 --- a/gc/base/Heap.cpp +++ b/gc/base/Heap.cpp @@ -433,12 +433,12 @@ MM_Heap::heapRemoveRange(MM_EnvironmentBase* env, MM_MemorySubSpace* subspace, u * The heap has had its memory shuffled between memory subspaces and/or memory pools. */ void -MM_Heap::heapReconfigured(MM_EnvironmentBase* env) +MM_Heap::heapReconfigured(MM_EnvironmentBase* env, HeapReconfigReason reason, MM_MemorySubSpace *subspace, void *lowAddress, void *highAddress) { MM_GlobalCollector* globalCollector = env->getExtensions()->getGlobalCollector(); if (NULL != globalCollector) { - globalCollector->heapReconfigured(env); + globalCollector->heapReconfigured(env, reason, subspace, lowAddress, highAddress); } } diff --git a/gc/base/Heap.hpp b/gc/base/Heap.hpp index 052d5018c69..840a8fbf830 100644 --- a/gc/base/Heap.hpp +++ b/gc/base/Heap.hpp @@ -148,7 +148,7 @@ class MM_Heap : public MM_BaseVirtual * moved from one subspace to another. * @param env[in] The thread which performed the change in heap geometry */ - virtual void heapReconfigured(MM_EnvironmentBase *env); + virtual void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL); virtual bool objectIsInGap(void *object); diff --git a/gc/base/MemorySpace.cpp b/gc/base/MemorySpace.cpp index bf534843fe5..75722d50f09 100644 --- a/gc/base/MemorySpace.cpp +++ b/gc/base/MemorySpace.cpp @@ -515,9 +515,9 @@ MM_MemorySpace::heapRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subs * */ void -MM_MemorySpace::heapReconfigured(MM_EnvironmentBase *env) +MM_MemorySpace::heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason, MM_MemorySubSpace *subspace, void *lowAddress, void *highAddress) { - _heap->heapReconfigured(env); + _heap->heapReconfigured(env, reason, subspace, lowAddress, highAddress); } /** diff --git a/gc/base/MemorySpace.hpp b/gc/base/MemorySpace.hpp index 31982480a20..892f79f950f 100644 --- a/gc/base/MemorySpace.hpp +++ b/gc/base/MemorySpace.hpp @@ -181,7 +181,7 @@ class MM_MemorySpace : public MM_BaseVirtual * moved from one subspace to another. * @param env[in] The thread which performed the change in heap geometry */ - void heapReconfigured(MM_EnvironmentBase *env); + void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL); static MM_MemorySpace *getMemorySpace(void *memorySpace) { return (MM_MemorySpace *)memorySpace; } diff --git a/gc/base/MemorySubSpace.cpp b/gc/base/MemorySubSpace.cpp index 2eaa7e855f4..9188eaaa977 100644 --- a/gc/base/MemorySubSpace.cpp +++ b/gc/base/MemorySubSpace.cpp @@ -1380,16 +1380,16 @@ MM_MemorySubSpace::heapRemoveRange(MM_EnvironmentBase* env, MM_MemorySubSpace* s * */ void -MM_MemorySubSpace::heapReconfigured(MM_EnvironmentBase* env) +MM_MemorySubSpace::heapReconfigured(MM_EnvironmentBase* env, HeapReconfigReason reason, MM_MemorySubSpace *subspace, void *lowAddress, void *highAddress) { if (!_usesGlobalCollector && (NULL != _collector)) { - _collector->heapReconfigured(env); + _collector->heapReconfigured(env, reason, subspace, lowAddress, highAddress); } if (_parent) { - _parent->heapReconfigured(env); + _parent->heapReconfigured(env, reason, subspace, lowAddress, highAddress); } else if (_memorySpace) { - _memorySpace->heapReconfigured(env); + _memorySpace->heapReconfigured(env, reason, subspace, lowAddress, highAddress); } } diff --git a/gc/base/MemorySubSpace.hpp b/gc/base/MemorySubSpace.hpp index ebed5efefd7..46c993d78cb 100644 --- a/gc/base/MemorySubSpace.hpp +++ b/gc/base/MemorySubSpace.hpp @@ -404,7 +404,7 @@ friend class GC_MemorySubSpaceRegionIterator; * moved from one subspace to another. * @param env[in] The thread which performed the change in heap geometry */ - virtual void heapReconfigured(MM_EnvironmentBase *env); + virtual void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL); virtual void *findFreeEntryEndingAtAddr(MM_EnvironmentBase *env, void *addr); virtual void *findFreeEntryTopStartingAtAddr(MM_EnvironmentBase *env, void *addr); diff --git a/gc/base/PhysicalSubArenaVirtualMemoryFlat.cpp b/gc/base/PhysicalSubArenaVirtualMemoryFlat.cpp index 3546ded98e9..1d3c3b35979 100644 --- a/gc/base/PhysicalSubArenaVirtualMemoryFlat.cpp +++ b/gc/base/PhysicalSubArenaVirtualMemoryFlat.cpp @@ -94,7 +94,7 @@ MM_PhysicalSubArenaVirtualMemoryFlat::tearDown(MM_EnvironmentBase *env) } if (NULL != _subSpace) { _subSpace->heapRemoveRange(env, _subSpace, ((uintptr_t)_highAddress) - ((uintptr_t)_lowAddress), _lowAddress, _highAddress, lowValidAddress, highValidAddress); - _subSpace->heapReconfigured(env); + _subSpace->heapReconfigured(env, RECONFIG_CONTRACT); } MM_PhysicalSubArenaVirtualMemory::tearDown(env); } @@ -113,9 +113,17 @@ MM_PhysicalSubArenaVirtualMemoryFlat::inflate(MM_EnvironmentBase *env) if(NULL != _region) { Assert_MM_true((_lowAddress == _region->getLowAddress()) && (_highAddress == _region->getHighAddress())); /* Inflation successful - inform the owning memorySubSpace */ - //TODO: Like the semi space arena, this should dispatch directory to the child subspace - result = _subSpace->expanded(env, this, _region->getSize(), _region->getLowAddress(), _region->getHighAddress(), false); - _subSpace->heapReconfigured(env); + + void *lowAddress = _region->getLowAddress(); + void *highAddress = _region->getHighAddress(); + + MM_MemorySubSpace *genericSubSpace = ((MM_MemorySubSpaceFlat *)_subSpace)->getChildSubSpace(); + result = genericSubSpace->expanded(env, this, _region->getSize(), lowAddress, highAddress, false); + if (result) { + _subSpace->heapReconfigured(env, RECONFIG_EXPAND, genericSubSpace, lowAddress, highAddress); + } else { + _subSpace->heapReconfigured(env, RECONFIG_EXPAND); + } } } return result; @@ -211,11 +219,12 @@ MM_PhysicalSubArenaVirtualMemoryFlat::expandNoCheck(MM_EnvironmentBase *env, uin getHeapRegionManager()->resizeAuxillaryRegion(env, _region, _lowAddress, _highAddress); Assert_MM_true(NULL != _region); - if(result){ + if(result) { genericSubSpace->addExistingMemory(env, this, expandSize, lowExpandAddress, highExpandAddress, true); + _subSpace->heapReconfigured(env, RECONFIG_EXPAND, genericSubSpace, lowExpandAddress, highExpandAddress); + } else { + _subSpace->heapReconfigured(env, RECONFIG_EXPAND); } - - _subSpace->heapReconfigured(env); } Assert_MM_true(_lowAddress == _region->getLowAddress()); @@ -305,10 +314,9 @@ MM_PhysicalSubArenaVirtualMemoryFlat::contract(MM_EnvironmentBase *env, uintptr_ _highAddress = (void *)contractBase; getHeapRegionManager()->resizeAuxillaryRegion(env, _region, _lowAddress, _highAddress); Assert_MM_true(NULL != _region); - /* Broadcast that heap has been removed */ genericSubSpace->heapRemoveRange(env, _subSpace, contractSize, (void *)contractBase, (void *)contractTop, lowValidAddress, highValidAddress); - genericSubSpace->heapReconfigured(env); + genericSubSpace->heapReconfigured(env, RECONFIG_CONTRACT); /* Execute any pending counter balances to the contract that have been enqueued */ _subSpace->triggerEnqueuedCounterBalancing(env); diff --git a/gc/base/segregated/MemorySubSpaceSegregated.cpp b/gc/base/segregated/MemorySubSpaceSegregated.cpp index e5090179eee..9cc8e61aac2 100644 --- a/gc/base/segregated/MemorySubSpaceSegregated.cpp +++ b/gc/base/segregated/MemorySubSpaceSegregated.cpp @@ -310,9 +310,9 @@ MM_MemorySubSpaceSegregated::heapRemoveRange(MM_EnvironmentBase *env, MM_MemoryS } void -MM_MemorySubSpaceSegregated::heapReconfigured(MM_EnvironmentBase *env) +MM_MemorySubSpaceSegregated::heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason, MM_MemorySubSpace *subspace, void *lowAddress, void *highAddress) { - MM_MemorySubSpaceUniSpace::heapReconfigured(env); + MM_MemorySubSpaceUniSpace::heapReconfigured(env, reason, subspace, lowAddress, highAddress); if (_regionExpansionBase != _regionExpansionTop) { expandRegionPool(); } diff --git a/gc/base/segregated/MemorySubSpaceSegregated.hpp b/gc/base/segregated/MemorySubSpaceSegregated.hpp index 03c9b91db15..a5493097efe 100644 --- a/gc/base/segregated/MemorySubSpaceSegregated.hpp +++ b/gc/base/segregated/MemorySubSpaceSegregated.hpp @@ -114,7 +114,7 @@ class MM_MemorySubSpaceSegregated : public MM_MemorySubSpaceUniSpace virtual bool heapAddRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subspace, uintptr_t size, void *lowAddress, void *highAddress); virtual bool heapRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subspace, uintptr_t size, void *lowAddress, void *highAddress, void *lowValidAddress, void *highValidAddress); - virtual void heapReconfigured(MM_EnvironmentBase *env); + virtual void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL); virtual MM_MemoryPool *getMemoryPool(); diff --git a/gc/base/segregated/SegregatedGC.cpp b/gc/base/segregated/SegregatedGC.cpp index 2bd3a369350..be1637fa95c 100644 --- a/gc/base/segregated/SegregatedGC.cpp +++ b/gc/base/segregated/SegregatedGC.cpp @@ -126,7 +126,7 @@ MM_SegregatedGC::heapRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpace *sub return _markingScheme->heapRemoveRange(env, subspace, size, lowAddress, highAddress, lowValidAddress, highValidAddress); } -void MM_SegregatedGC::heapReconfigured(MM_EnvironmentBase* env) +void MM_SegregatedGC::heapReconfigured(MM_EnvironmentBase* env, HeapReconfigReason reason, MM_MemorySubSpace *subspace, void *lowAddress, void *highAddress) { /* OMRTODO implement proper heap resizing in segregated heaps */ } diff --git a/gc/base/segregated/SegregatedGC.hpp b/gc/base/segregated/SegregatedGC.hpp index 3c8a9845fe8..8f5dd525858 100644 --- a/gc/base/segregated/SegregatedGC.hpp +++ b/gc/base/segregated/SegregatedGC.hpp @@ -96,7 +96,7 @@ class MM_SegregatedGC : public MM_GlobalCollector virtual bool heapAddRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subspace, uintptr_t size, void *lowAddress, void *highAddress); virtual bool heapRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subspace,uintptr_t size, void *lowAddress, void *highAddress, void *lowValidAddress, void *highValidAddress); - virtual void heapReconfigured(MM_EnvironmentBase* env); + virtual void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL); virtual bool isMarked(void *objectPtr) { return _markingScheme->isMarked(static_cast(objectPtr)); } diff --git a/gc/base/standard/ConcurrentCardTable.cpp b/gc/base/standard/ConcurrentCardTable.cpp index ea74a43c628..a6116c985f2 100644 --- a/gc/base/standard/ConcurrentCardTable.cpp +++ b/gc/base/standard/ConcurrentCardTable.cpp @@ -416,7 +416,7 @@ MM_ConcurrentCardTable::heapRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpa * */ void -MM_ConcurrentCardTable::heapReconfigured(MM_EnvironmentBase *env) +MM_ConcurrentCardTable::heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason, MM_MemorySubSpace *subspace, void *lowAddress, void *highAddress) { } diff --git a/gc/base/standard/ConcurrentCardTable.hpp b/gc/base/standard/ConcurrentCardTable.hpp index c65558d9b43..95513ff007f 100644 --- a/gc/base/standard/ConcurrentCardTable.hpp +++ b/gc/base/standard/ConcurrentCardTable.hpp @@ -325,7 +325,7 @@ class MM_ConcurrentCardTable : public MM_CardTable * @param[in] env The thread which caused the heap geometry change (typically the master GC thread) * @note This implementation does nothing. */ - void heapReconfigured(MM_EnvironmentBase *env); + void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL); /** * @return A pointer to the mutable card table stats structure diff --git a/gc/base/standard/ConcurrentGC.cpp b/gc/base/standard/ConcurrentGC.cpp index 06363449601..21b670f6c85 100644 --- a/gc/base/standard/ConcurrentGC.cpp +++ b/gc/base/standard/ConcurrentGC.cpp @@ -3267,23 +3267,6 @@ MM_ConcurrentGC::heapAddRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subspa /* Expand any superclass structures including mark bits*/ bool result = MM_ParallelGlobalGC::heapAddRange(env, subspace, size, lowAddress, highAddress); - if (result) { - /* If we are within a concurrent cycle we need to initialize the mark bits - * for new region of heap now - */ - if (CONCURRENT_OFF < _stats.getExecutionMode()) { - /* If subspace is concurrently collectible then clear bits otherwise - * set the bits on to stop tracing INTO this area during concurrent - * mark cycle. - */ - if (subspace->isConcurrentCollectable()) { - _markingScheme->setMarkBitsInRange(env, lowAddress, highAddress, true); - } else { - _markingScheme->setMarkBitsInRange(env, lowAddress, highAddress, false); - } - } - } - _heapAlloc = _extensions->heap->getHeapTop(); Trc_MM_ConcurrentGC_heapAddRange_Exit(env->getLanguageVMThread()); @@ -3329,34 +3312,57 @@ MM_ConcurrentGC::heapRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpace *sub * @see MM_ParallelGlobalGC::heapReconfigured() */ void -MM_ConcurrentGC::heapReconfigured(MM_EnvironmentBase *env) +MM_ConcurrentGC::heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason, MM_MemorySubSpace *subspace, void *lowAddress, void *highAddress) { - /* If called outside a global collection for a heap expand/contract.. - */ - if (!_stwCollectionInProgress && (_rebuildInitWorkForAdd || _rebuildInitWorkForRemove)) { - /* ... and a concurrent cycle has not yet started then we - * tune to heap here to reflect new heap size - * Note: CMVC 153167 : Under gencon, there is a timing hole where - * if we are in the middle of initializing the heap ranges while a - * scavenge occurs, and if the scavenge causes the heap to contract, - * we will try to memset ranges that are now contracted (decommitted memory) - * when we resume the init work. + Assert_MM_true(reason != RECONFIG_NONE); + + if (lowAddress != NULL && highAddress != NULL) { + Assert_MM_true(_rebuildInitWorkForAdd && reason == RECONFIG_EXPAND); + /* If we are within a concurrent cycle we need to initialize the mark bits + * for new region of heap now */ - if (_stats.getExecutionMode() < CONCURRENT_INIT_COMPLETE) { - tuneToHeap(env); - } else { - /* Heap expand/contract is during a concurrent cycle..we need to adjust the trace target so - * that the trace rate is adjusted correctly on subsequent allocates. + if (CONCURRENT_OFF < _stats.getExecutionMode()) { + /* If subspace is concurrently collectible then clear bits otherwise + * set the bits on to stop tracing INTO this area during concurrent + * mark cycle. */ - adjustTraceTarget(); + if (subspace->isConcurrentCollectable()) { + _markingScheme->setMarkBitsInRange(env, lowAddress, highAddress, true); + } else { + _markingScheme->setMarkBitsInRange(env, lowAddress, highAddress, false); + } } } + /* If called outside a global collection for a heap expand/contract.. */ + if(reason == RECONFIG_CONTRACT || reason == RECONFIG_EXPAND) { + Assert_MM_true(_rebuildInitWorkForAdd || _rebuildInitWorkForRemove); + if (!_stwCollectionInProgress) { + /* ... and a concurrent cycle has not yet started then we + * tune to heap here to reflect new heap size + * Note: CMVC 153167 : Under gencon, there is a timing hole where + * if we are in the middle of initializing the heap ranges while a + * scavenge occurs, and if the scavenge causes the heap to contract, + * we will try to memset ranges that are now contracted (decommitted memory) + * when we resume the init work. + */ + if (_stats.getExecutionMode() < CONCURRENT_INIT_COMPLETE) { + tuneToHeap(env); + } else { + /* Heap expand/contract is during a concurrent cycle..we need to adjust the trace target so + * that the trace rate is adjusted correctly on subsequent allocates. + */ + adjustTraceTarget(); + } + } + } + + /* Expand any superclass structures */ - MM_ParallelGlobalGC::heapReconfigured(env); + MM_ParallelGlobalGC::heapReconfigured(env, reason, subspace, lowAddress, highAddress); /* ...and then expand the card table */ - ((MM_ConcurrentCardTable *)_cardTable)->heapReconfigured(env); + ((MM_ConcurrentCardTable *)_cardTable)->heapReconfigured(env, reason, subspace, lowAddress, highAddress); } /** diff --git a/gc/base/standard/ConcurrentGC.hpp b/gc/base/standard/ConcurrentGC.hpp index 05354dcd906..e9b248a0cda 100644 --- a/gc/base/standard/ConcurrentGC.hpp +++ b/gc/base/standard/ConcurrentGC.hpp @@ -426,7 +426,7 @@ class MM_ConcurrentGC : public MM_ParallelGlobalGC virtual bool heapAddRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subspace, uintptr_t size, void *lowAddress, void *highAddress); virtual bool heapRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subspace, uintptr_t size, void *lowAddress, void *highAddress, void *lowValidAddress, void *highValidAddress); - virtual void heapReconfigured(MM_EnvironmentBase *env); + virtual void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL); void finalCleanCards(MM_EnvironmentBase *env); diff --git a/gc/base/standard/ConcurrentGCIncrementalUpdate.cpp b/gc/base/standard/ConcurrentGCIncrementalUpdate.cpp index ce30763dc0b..3273f65f29b 100644 --- a/gc/base/standard/ConcurrentGCIncrementalUpdate.cpp +++ b/gc/base/standard/ConcurrentGCIncrementalUpdate.cpp @@ -124,7 +124,6 @@ MM_ConcurrentGCIncrementalUpdate::heapAddRange(MM_EnvironmentBase *env, MM_Memor /* Expand any superclass structures including mark bits*/ bool result = MM_ConcurrentGC::heapAddRange(env, subspace, size, lowAddress, highAddress); - if (result) { /* expand the card table */ result = ((MM_ConcurrentCardTable *)_cardTable)->heapAddRange(env, subspace, size, lowAddress, highAddress, clearCards); diff --git a/gc/base/standard/ParallelGlobalGC.cpp b/gc/base/standard/ParallelGlobalGC.cpp index d6727a6d02d..09282ee8fd5 100644 --- a/gc/base/standard/ParallelGlobalGC.cpp +++ b/gc/base/standard/ParallelGlobalGC.cpp @@ -1345,9 +1345,9 @@ MM_ParallelGlobalGC::heapRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpace * @see MM_GlobalCollector::heapReconfigured() */ void -MM_ParallelGlobalGC::heapReconfigured(MM_EnvironmentBase *env) +MM_ParallelGlobalGC::heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason, MM_MemorySubSpace *subspace, void *lowAddress, void *highAddress) { - _sweepScheme->heapReconfigured(env); + _sweepScheme->heapReconfigured(env, reason, subspace, lowAddress, highAddress); } diff --git a/gc/base/standard/ParallelGlobalGC.hpp b/gc/base/standard/ParallelGlobalGC.hpp index 0f9e815eb81..52bff889721 100644 --- a/gc/base/standard/ParallelGlobalGC.hpp +++ b/gc/base/standard/ParallelGlobalGC.hpp @@ -289,7 +289,7 @@ class MM_ParallelGlobalGC : public MM_GlobalCollector virtual bool heapAddRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subspace, uintptr_t size, void *lowAddress, void *highAddress); virtual bool heapRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpace *subspace, uintptr_t size, void *lowAddress, void *highAddress, void *lowValidAddress, void *highValidAddress); - virtual void heapReconfigured(MM_EnvironmentBase *env); + virtual void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL); virtual uint32_t getGCTimePercentage(MM_EnvironmentBase *env); diff --git a/gc/base/standard/ParallelSweepScheme.cpp b/gc/base/standard/ParallelSweepScheme.cpp index e4272e4aa50..e3752e8edcd 100644 --- a/gc/base/standard/ParallelSweepScheme.cpp +++ b/gc/base/standard/ParallelSweepScheme.cpp @@ -305,7 +305,7 @@ MM_ParallelSweepScheme::heapRemoveRange(MM_EnvironmentBase *env, MM_MemorySubSpa * */ void -MM_ParallelSweepScheme::heapReconfigured(MM_EnvironmentBase *env) +MM_ParallelSweepScheme::heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason, MM_MemorySubSpace *subspace, void *lowAddress, void *highAddress) { _sweepHeapSectioning->update(env); } diff --git a/gc/base/standard/ParallelSweepScheme.hpp b/gc/base/standard/ParallelSweepScheme.hpp index 567ce6f32d3..b86f05f217c 100644 --- a/gc/base/standard/ParallelSweepScheme.hpp +++ b/gc/base/standard/ParallelSweepScheme.hpp @@ -187,7 +187,7 @@ class MM_ParallelSweepScheme : public MM_BaseVirtual * moved from one subspace to another. * @param env[in] The thread which performed the change in heap geometry */ - void heapReconfigured(MM_EnvironmentBase *env); + void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL); #if defined(OMR_GC_CONCURRENT_SWEEP) virtual bool replenishPoolForAllocate(MM_EnvironmentBase *env, MM_MemoryPool *memoryPool, uintptr_t size); diff --git a/gc/base/standard/PhysicalSubArenaVirtualMemorySemiSpace.cpp b/gc/base/standard/PhysicalSubArenaVirtualMemorySemiSpace.cpp index 5351daf9baa..de00d3d01c6 100644 --- a/gc/base/standard/PhysicalSubArenaVirtualMemorySemiSpace.cpp +++ b/gc/base/standard/PhysicalSubArenaVirtualMemorySemiSpace.cpp @@ -114,7 +114,7 @@ MM_PhysicalSubArenaVirtualMemorySemiSpace::tearDown(MM_EnvironmentBase *env) /* Remove the heap range represented */ if (NULL != _subSpace) { _subSpace->heapRemoveRange(env, _subSpace, ((uintptr_t)_highAddress) - ((uintptr_t)_lowAddress), _lowAddress, _highAddress, lowValidAddress, highValidAddress); - _subSpace->heapReconfigured(env); + _subSpace->heapReconfigured(env, RECONFIG_CONTRACT); } MM_PhysicalSubArenaVirtualMemory::tearDown(env); } @@ -188,12 +188,30 @@ MM_PhysicalSubArenaVirtualMemorySemiSpace::inflate(MM_EnvironmentBase *env) Assert_MM_inflateInvalidRange(); } + void *lowAddress = _highSemiSpaceRegion->getLowAddress(); + void *highAddress = _highSemiSpaceRegion->getHighAddress(); + /* Inform the semi spaces that they have been expanded */ - bool result = subSpaceAllocate->expanded(env, this, _highSemiSpaceRegion->getSize(), _highSemiSpaceRegion->getLowAddress(), _highSemiSpaceRegion->getHighAddress(), false); - subSpaceAllocate->heapReconfigured(env); - result = result && subSpaceSurvivor->expanded(env, this, _lowSemiSpaceRegion->getSize(), _lowSemiSpaceRegion->getLowAddress(), _lowSemiSpaceRegion->getHighAddress(), false); - subSpaceSurvivor->heapReconfigured(env); - return result; + bool resultExpandAllocate = subSpaceAllocate->expanded(env, this, _highSemiSpaceRegion->getSize(), lowAddress, highAddress, false); + + if (resultExpandAllocate) { + subSpaceAllocate->heapReconfigured(env, RECONFIG_EXPAND, subSpaceAllocate, lowAddress, highAddress); + } else { + subSpaceAllocate->heapReconfigured(env, RECONFIG_EXPAND); + } + + lowAddress = _lowSemiSpaceRegion->getLowAddress(); + highAddress = _lowSemiSpaceRegion->getHighAddress(); + + bool resultExpandSurvivor = subSpaceSurvivor->expanded(env, this, _lowSemiSpaceRegion->getSize(), lowAddress, highAddress, false); + + if(resultExpandSurvivor) { + subSpaceSurvivor->heapReconfigured(env, RECONFIG_EXPAND, subSpaceSurvivor, lowAddress, highAddress); + } else { + subSpaceSurvivor->heapReconfigured(env, RECONFIG_EXPAND); + } + + return resultExpandAllocate && resultExpandSurvivor; } return false; } @@ -686,7 +704,7 @@ MM_PhysicalSubArenaVirtualMemorySemiSpace::contract(MM_EnvironmentBase *env, uin removeMemoryTop, previousValidAddressNotRemoved, (void *)allocateSegmentBase); - _subSpace->heapReconfigured(env); + _subSpace->heapReconfigured(env, RECONFIG_CONTRACT); /* Decommit the heap (the return value really doesn't matter here - its already too late) */ _heap->decommitMemory( @@ -869,7 +887,7 @@ MM_PhysicalSubArenaVirtualMemorySemiSpace::contract(MM_EnvironmentBase *env, uin removeMemoryTop, previousValidAddressNotRemoved, (void *)survivorSegmentBase); - _subSpace->heapReconfigured(env); + _subSpace->heapReconfigured(env, RECONFIG_CONTRACT); /* Decommit the heap (the return value really doesn't matter here - its already too late) */ _heap->decommitMemory( @@ -1046,7 +1064,7 @@ MM_PhysicalSubArenaVirtualMemorySemiSpace::tilt(MM_EnvironmentBase *env, uintptr ((MM_MemorySubSpaceSemiSpace *)_subSpace)->setSurvivorSpaceSizeRatio(survivorSpaceSize / ((_highSemiSpaceRegion->getSize() + _lowSemiSpaceRegion->getSize()) / 100)); /* Broadcast that the heap has been reconfigured */ - _subSpace->heapReconfigured(env); + _subSpace->heapReconfigured(env, RECONFIG_SCAVENGER_TILT); } /** @@ -1253,8 +1271,12 @@ MM_PhysicalSubArenaVirtualMemorySemiSpace::expandNoCheck(MM_EnvironmentBase *env /* Broadcast the expansion of the heap, but do not add the memory to any free lists. * Must be done after segment information has been updated. */ - _subSpace->heapAddRange(env, _subSpace, splitExpandSize, newLowAddress, (void *) (((uintptr_t)newLowAddress) + splitExpandSize)); - _subSpace->heapReconfigured(env); + bool expandResult = _subSpace->heapAddRange(env, _subSpace, splitExpandSize, newLowAddress, (void *) (((uintptr_t)newLowAddress) + splitExpandSize)); + if (expandResult) { + _subSpace->heapReconfigured(env, RECONFIG_EXPAND, _subSpace, newLowAddress, (void *) (((uintptr_t)newLowAddress) + splitExpandSize)); + } else { + _subSpace->heapReconfigured(env, RECONFIG_EXPAND); + } /* Include the memory into the free lists */ if(debug) { @@ -1315,8 +1337,12 @@ MM_PhysicalSubArenaVirtualMemorySemiSpace::expandNoCheck(MM_EnvironmentBase *env /* Broadcast the expansion of the heap, but do not add the memory to any free lists. * Must be done after segment information has been updated. */ - _subSpace->heapAddRange(env, _subSpace, splitExpandSize, newLowAddress, (void *) (((uintptr_t)newLowAddress) + splitExpandSize)); - _subSpace->heapReconfigured(env); + bool expandResult = _subSpace->heapAddRange(env, _subSpace, splitExpandSize, newLowAddress, (void *) (((uintptr_t)newLowAddress) + splitExpandSize)); + if (expandResult) { + _subSpace->heapReconfigured(env, RECONFIG_EXPAND, _subSpace, newLowAddress, (void *) (((uintptr_t)newLowAddress) + splitExpandSize)); + } else { + _subSpace->heapReconfigured(env, RECONFIG_EXPAND); + } /* Include the memory into the free lists. */ if(debug) { diff --git a/gc/base/standard/Scavenger.cpp b/gc/base/standard/Scavenger.cpp index a55f47228a2..d6877322cbc 100644 --- a/gc/base/standard/Scavenger.cpp +++ b/gc/base/standard/Scavenger.cpp @@ -4435,7 +4435,7 @@ MM_Scavenger::percolateGarbageCollect(MM_EnvironmentBase *env, MM_MemorySubSpac * */ void -MM_Scavenger::heapReconfigured(MM_EnvironmentBase *env) +MM_Scavenger::heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason, MM_MemorySubSpace *subspace, void *lowAddress, void *highAddress) { } diff --git a/gc/base/standard/Scavenger.hpp b/gc/base/standard/Scavenger.hpp index 6d907f991a9..6effb60496a 100644 --- a/gc/base/standard/Scavenger.hpp +++ b/gc/base/standard/Scavenger.hpp @@ -815,7 +815,7 @@ class MM_Scavenger : public MM_Collector virtual bool canCollectorExpand(MM_EnvironmentBase *env, MM_MemorySubSpace *subSpace, uintptr_t expandSize); virtual uintptr_t getCollectorExpandSize(MM_EnvironmentBase *env); - virtual void heapReconfigured(MM_EnvironmentBase *env); + virtual void heapReconfigured(MM_EnvironmentBase *env, HeapReconfigReason reason = RECONFIG_NONE, MM_MemorySubSpace *subspace = NULL, void *lowAddress = NULL, void *highAddress = NULL); MM_Scavenger(MM_EnvironmentBase *env, MM_HeapRegionManager *regionManager) : MM_Collector() diff --git a/gc/startup/omrgcstartup.cpp b/gc/startup/omrgcstartup.cpp index ece3778353a..1b4ccaba8bf 100644 --- a/gc/startup/omrgcstartup.cpp +++ b/gc/startup/omrgcstartup.cpp @@ -283,7 +283,7 @@ OMR_GC_InitializeCollector(OMR_VMThread* omrVMThread) } /* Make sure sweep scheme is up-to-date with the heap configuration */ - globalCollector->heapReconfigured(env); + globalCollector->heapReconfigured(env, RECONFIG_EXPAND); } } diff --git a/include_core/omrgcconsts.h b/include_core/omrgcconsts.h index 87e1471d9a8..496efa4b2e9 100644 --- a/include_core/omrgcconsts.h +++ b/include_core/omrgcconsts.h @@ -275,6 +275,14 @@ typedef enum { COMPACT_MICRO_FRAG = 14 } CompactReason; +typedef enum { + RECONFIG_NONE = 0, + RECONFIG_EXPAND = 1, + RECONFIG_CONTRACT = 2, + RECONFIG_SCAVENGER_TILT = 3 +} HeapReconfigReason; + + typedef enum { COMPACT_PREVENTED_NONE = 0, COMPACT_PREVENTED_CRITICAL_REGIONS