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

Pruning the cards from InterRegionRememberedsets after GMP #8804

Merged
merged 1 commit into from
Mar 30, 2020

Conversation

LinHu2016
Copy link
Contributor

@LinHu2016 LinHu2016 commented Mar 9, 2020

After Global Marking Phase, the cards reference from "free memory"
should be pruned from InterRegionRememberedsets, in order to
reuse the free memory in future, currently we have card refresh
and card pruning in beginning PGC, so piggyback existing logic
add extra condition for pruning cards related with "free memory"
in first PGC after GMP.

- During Rememberedsets flush in the beginning PGC(for
collection set), extra condition check for dirty card (do not
dirty card if corresponding MarkMap is 0)
- During global Rememberedsets prune, extra condition check
for pruning the card (do remove the card if corresponding
MarkMap is 0).

depends on: eclipse-omr/omr#4928
fix partial #9247

Signed-off-by: Lin Hu linhu@ca.ibm.com

bool needToFlush = true;
if (needToCheckMarkMap) {
void* heapAddress = convertHeapAddressFromRememberedSetCard(envBase, card);
uint64_t* map4Card = (uint64_t*) &((uintptr_t *)(markMap->getMarkBits()))[markMap->getSlotIndex((omrobjectptr_t) heapAddress)];
Copy link
Contributor

@amicic amicic Mar 11, 2020

Choose a reason for hiding this comment

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

this needs to go to MarkMap class, a helper like:
bool anyLiveObjectInCard(void *heapAddress);

Copy link
Contributor

@amicic amicic Mar 11, 2020

Choose a reason for hiding this comment

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

and state in a comment that implementation assumes that card covers exactly 512 bytes, 1 mark bit is 8 bytes of heap and heap address is card size aligned.

Copy link
Contributor

Choose a reason for hiding this comment

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

you can add compile time assert that BITS_PER_BYTE is 8 and CARD_SIZE_SHIFT is 9

writeFlushToCardState(cardAddress, gmpIsActive);
bool needToFlush = true;
if (needToCheckMarkMap) {
void* heapAddress = convertHeapAddressFromRememberedSetCard(envBase, card);
Copy link
Contributor

Choose a reason for hiding this comment

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

interRegionRememberedSet is available. you can use its convertHeapAddressFromRememberedSetCard(), and no need to clone it in this class

needToRemove = true;
}

if (!needToRemove && needToCheckMarkMap) {
Copy link
Contributor

Choose a reason for hiding this comment

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

The new check is just more generic variant of fromRegion->containsObjects().
So I recommend you introduce a helper that will replace that containsObjects() check:

inline bool IRRS::cardContainsObjects(card, fromRegion, needToCheckMarkMap) {
if needToCheckMarkMap
return markMap->anyLiveObjectInCard(card)
else
return !fromRegion->containsObjects()
}

Copy link
Contributor

@amicic amicic Mar 11, 2020

Choose a reason for hiding this comment

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

We can later consider checking against MarkMap all the time (not just after GMP), if it's not much slower. But that might be tricky since for evacuated regions clearing of mark map might be done late(r).

Copy link
Contributor Author

Choose a reason for hiding this comment

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

The new check is just more generic variant of fromRegion->containsObjects().
So I recommend you introduce a helper that will replace that containsObjects() check:

inline bool IRRS::cardContainsObjects(card, fromRegion, needToCheckMarkMap) {
if needToCheckMarkMap
return markMap->anyLiveObjectInCard(card)
else
return !fromRegion->containsObjects()
}

good idea! it is good for clearFromRegionReferencesForMarkDirect(), but for clearFromRegionReferencesForMarkOptimized() (it is default, using compressed card table ), it is little bit tricky, partial logic for checking empty region is in rebuildCompressedCardTableForMark(), we can add CheckMarkMap in rebuildCompressedCardTableForMark, but it need to check every card in the regions, it might be expensive?

Copy link
Contributor

@amicic amicic Mar 26, 2020

Choose a reason for hiding this comment

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

I see. Actually, I think it is CompressedCardTable::rebuildCompressedCardTableForPartialCollect that would be more impacted. We could try that later and see if it will slow it down.

Still I think you can introduce the helper and use it here, and in 'else' clause of 'if (compressedCardTable->isReady()) {', while the existing areAnyLiveObjectsInCard() check you can move up in 'then' clause of 'if (compressedCardTable->isReady()) {'

Copy link
Contributor Author

Choose a reason for hiding this comment

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

if we use the helper in "else" clause, so we have to add the logic in rebuildCompressedCardTableForPartialCollect(), otherwise if compressedCardTable->isReady() case, we would miss to check markMap.

if (compressedCardTable->isReady()) {
   ....
} else {

}

@amicic
Copy link
Contributor

amicic commented Mar 11, 2020

We need to think/test if Mark Map based check is needed in first PGC after a Mark-Compact based PGC, since it may also create populated regions with empty chunks (at least a tail, if not a chunk in a middle).

@LinHu2016
Copy link
Contributor Author

We need to think/test if Mark Map based check is needed in first PGC after a Mark-Compact based PGC, since it may also create populated regions with empty chunks (at least a tail, if not a chunk in a middle).

there is pruning card at the beginning of compact, clearFromRegionReferencesForCompact(), not sure if it covered the cases.

@LinHu2016 LinHu2016 force-pushed the GMP_clearingRS branch 4 times, most recently from 32d98bc to 84d4894 Compare March 18, 2020 12:21
@LinHu2016 LinHu2016 force-pushed the GMP_clearingRS branch 6 times, most recently from 499e655 to 47aa9c2 Compare March 27, 2020 19:14
Card *cardAddress = interRegionRememberedSet->rememberedSetCardToCardAddr(env, card);
writeFlushToCardState(cardAddress, gmpIsActive);
if (interRegionRememberedSet->cardMayContainObjects(card, referencingRegion, needToCheckMarkMap, markMap) && !referencingRegion->_markData._shouldMark) {
bool needToFlush = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

no need for needToFlush flag, any more. here, and at a couple of other similar spots.

if (fromRegion->_markData._shouldMark || !fromRegion->containsObjects() || isDirtyCardForPartialCollect(env, cardTable, cardAddress)) {
/* Regions that are completely swept after a GMP, might still have outgoing references (thus we consider cardContainsNoObjects) */
if (fromRegion->_markData._shouldMark || !cardMayContainObjects(card, fromRegion, needToCheckMarkMap, markMap) || isDirtyCardForPartialCollect(env, cardTable, cardAddress)) {
needToRemove = true;
Copy link
Contributor

Choose a reason for hiding this comment

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

no need for needToRemove

* Helper function isCompressedCardDirtyForPartialCollect
* extended from compressedCardTable->isCompressedCardDirtyForPartialCollect(), only in case first PGC after GMP, also dirty card if card Contains No Object.
*/
MMINLINE bool isCompressedCardDirtyForPartialCollect(MM_EnvironmentVLHGC* env, UDATA card, bool needToCheckMarkMap)
Copy link
Contributor

Choose a reason for hiding this comment

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

pass compressedCardTable and mark map

@@ -933,11 +935,12 @@ MM_InterRegionRememberedSet::clearFromRegionReferencesForMarkDirect(MM_Environme
while(0 != (card = rsclCardIterator.nextReferencingCard(env))) {
MM_HeapRegionDescriptorVLHGC *fromRegion = tableDescriptorForRememberedSetCard(card);
Card * cardAddress = rememberedSetCardToCardAddr(env, card);
/* Regions that are completely swept after a GMP, might still have outgoing references (thus we consider empty regions too) */
if (fromRegion->_markData._shouldMark || !fromRegion->containsObjects() || isDirtyCardForPartialCollect(env, cardTable, cardAddress)) {
/* Regions that are completely swept after a GMP, might still have outgoing references (thus we consider cardContainsNoObjects) */
Copy link
Contributor

@amicic amicic Mar 27, 2020

Choose a reason for hiding this comment

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

This whole comment should be updated:
Regions that are completely swept or parts of regions that are partially swept after a GMP might still have outgoing references. If they are (if they may not contain objects), cards should be removed.

@LinHu2016 LinHu2016 force-pushed the GMP_clearingRS branch 2 times, most recently from fe52ec3 to 3d321a7 Compare March 27, 2020 20:12
* if this is first PGC after GMP, check if markMap->areAnyLiveObjectsInCard()
* otherwise check if region->containsObjects()
*/
MMINLINE bool cardMayContainObjects(UDATA card, MM_HeapRegionDescriptorVLHGC *fromRegion, bool needToCheckMarkMap, MM_MarkMap *markMap)
Copy link
Contributor

@amicic amicic Mar 27, 2020

Choose a reason for hiding this comment

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

both helpers could be static (hence saving by not passing implicit 'this' pointer)

@@ -96,6 +97,11 @@ MM_CardListFlushTask::run(MM_EnvironmentBase *envBase)
{
MM_EnvironmentVLHGC *env = MM_EnvironmentVLHGC::getEnvironment(envBase);
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
MM_MarkMap *markMap = NULL;
if (static_cast<MM_CycleStateVLHGC*>(envBase->_cycleState)->_schedulingDelegate->isFirstPGCAfterGMP())
{
Copy link
Contributor

Choose a reason for hiding this comment

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

move open bracket to previous line

Copy link
Contributor

@amicic amicic Mar 27, 2020

Choose a reason for hiding this comment

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

your fixed the other two, but not this one :)

MM_CardTable *cardTable = extensions->cardTable;
MM_MarkMap *markMap = NULL;
if (static_cast<MM_CycleStateVLHGC*>(env->_cycleState)->_schedulingDelegate->isFirstPGCAfterGMP())
{
Copy link
Contributor

Choose a reason for hiding this comment

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

move bracket

MM_CompressedCardTable *compressedCardTable = extensions->compressedCardTable;
MM_MarkMap *markMap = NULL;
if (static_cast<MM_CycleStateVLHGC*>(env->_cycleState)->_schedulingDelegate->isFirstPGCAfterGMP())
{
Copy link
Contributor

Choose a reason for hiding this comment

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

bracket


/**
* Helper function isCompressedCardDirtyForPartialCollect
* extended from compressedCardTable->isCompressedCardDirtyForPartialCollect(), only in case first PGC after GMP, also dirty card if card Contains No Object.
Copy link
Contributor

Choose a reason for hiding this comment

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

comment says 'also dirty card'
did you mean 'also remove card'?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

compressedCardTable->isCompressedCardDirtyForPartialCollect() return true if the card is dirty, extra condition if the card Contains No Object return true (the card is dirty)

Copy link
Contributor

Choose a reason for hiding this comment

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

Ah, then it should say 'also return as dirty'. As-is I understood you imply an action of dirtying the card.

{
void* heapAddress = convertHeapAddressFromRememberedSetCard(card);
bool ret = compressedCardTable->isCompressedCardDirtyForPartialCollect(env, heapAddress);
if (!ret && (NULL != markMap)) {
Copy link
Contributor

@amicic amicic Mar 27, 2020

Choose a reason for hiding this comment

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

add comment:
TODO: consider incorporating areAnyLiveObjectsInCard info when building Compressed Card Table

@amicic
Copy link
Contributor

amicic commented Mar 27, 2020

Jenkins test sanity all jdk8

* if this is first PGC after GMP, check if markMap->areAnyLiveObjectsInCard()
* otherwise check if region->containsObjects()
*/
MMINLINE static bool cardMayContainObjects(UDATA card, MM_HeapRegionDescriptorVLHGC *fromRegion, MM_MarkMap *markMap)
Copy link
Contributor

Choose a reason for hiding this comment

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

These helpers won't be able to be static, afterall :( . It may work now, but once OMR_GC_FULL_POINTERS is enabled, they will indirectly rely on class member _compressObjectReferences

	After Global Marking Phase, the cards reference from "free memory"
	should be pruned from InterRegionRememberedsets, in order to
	reuse the free memory in future, currently we have card refresh
	and card pruning in beginning PGC, so piggyback existing logic
	add extra condition for pruning cards related with "free memory"
	in first PGC after GMP.

	- During Rememberedsets flush in the beginning PGC(for
	collection set), extra condition check for dirty card (do not
	dirty card if corresponding MarkMap is 0)
	- During global Rememberedsets prune, extra condition check
	for pruning the card (do remove the card if corresponding
	MarkMap is 0).

Signed-off-by: Lin Hu <linhu@ca.ibm.com>
@amicic
Copy link
Contributor

amicic commented Mar 27, 2020

Jenkins test sanity all jdk8

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants