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

Handle Continuation scan during Concurrent Scavenger and Metronome #16106

Merged

Conversation

LinHu2016
Copy link
Contributor

For CS and Metronome, due to synchronous nature of their barriers (they read the value of the slot and act on it immediately, for example they may evacuate object for CS and mark object for Metronome), We fully scan java stacks of related continuation during the virtual thread mount.

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

@LinHu2016
Copy link
Contributor Author

@amicic @dmitripivkine please review the change, Thanks

if ((J9_GC_POLICY_METRONOME == vmThread->javaVM->gcPolicy) && (extensions->realtimeGC->isCollectorConcurrentTracing())) {
/* metronome in progress */
extensions->realtimeGC->getRealtimeDelegate()->scanContinuationJavaStack((MM_EnvironmentRealtime *)env, object);
}
Copy link
Contributor

Choose a reason for hiding this comment

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

Let's try to 'repackage' this into ObjectAccessBarrier: have a virtual preMountContinuation that Standard and Realtime subclass will override. It's somewhat cleaner (since we don't have to query GC policy).

@amicic
Copy link
Contributor

amicic commented Oct 14, 2022

Noticed in existing code:

postUnmountContinuation(J9VMThread *vmThread, j9object_t object)
{
      J9WriteBarrierBatch(vmThread, object); <<< should be able to call directly

@amicic amicic added comp:gc project:loom Used to track Project Loom related work labels Oct 14, 2022
@amicic
Copy link
Contributor

amicic commented Oct 14, 2022

Noticed in existing code:

postUnmountContinuation(J9VMThread *vmThread, j9object_t object)
{
      J9WriteBarrierBatch(vmThread, object); <<< should be able to call directly

Since I suggested to introduce preMountContinuation in OAB, for symmetry we should do that for postUnmount, too. Then, just call postBatchObjectStore there (bypassing J9WriteBarrierBatch), for Standard and Balanced only and no need for an empty postBatchObjectStore for Realtime, that you had to do when using J9WriteBarrierBatch.

Chances are, we will have to do something in postUnmount for RT too (to compensate for missing double barrier), but let me think about it more. Unfortunately, this (need for double barrier) is very hard scenario to produce in real life workloads.

return true;
}

bool
Copy link
Contributor

Choose a reason for hiding this comment

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

Don't see value in bool ret type, for both pre/post - just make them void.

Don't know why postBatchObjectStore ever had return type bool, but seems like it was never used anywhere or ever returned anything else but true.

@@ -179,6 +179,12 @@ class MM_ScavengerDelegate : public MM_BaseNonVirtual {
bool initialize(MM_EnvironmentBase *env);
void tearDown(MM_EnvironmentBase *env);

void scanContinuationJavaStack(MM_EnvironmentStandard *env, omrobjectptr_t objectPtr)
Copy link
Contributor

Choose a reason for hiding this comment

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

don't see value in this wrapper

Copy link
Contributor

Choose a reason for hiding this comment

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

just make doContinuationObject public

MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vmThread->javaVM);
if (extensions->isConcurrentScavengerInProgress()) {
/* concurrent scavenger in progress */
extensions->scavenger->getDelegate()->scanContinuationJavaStack((MM_EnvironmentStandard *)(MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread)), contObject);
Copy link
Contributor

Choose a reason for hiding this comment

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

create env in a separate line for easier reading

Copy link
Contributor

Choose a reason for hiding this comment

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

let's cache scavenger, there is a dozen of places we use it in this class (I should have done it long ago)

bool
MM_RealtimeAccessBarrier::preMountContinuation(J9VMThread *vmThread, j9object_t contObject)
{
if (_realtimeGC->isCollectorConcurrentTracing()) {
Copy link
Contributor

@amicic amicic Oct 14, 2022

Choose a reason for hiding this comment

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

don't know if it's the same, but use isBarrierActive as it's already case in the rest of this file/class

#include "MetronomeDelegate.hpp"
#include "EnvironmentStandard.hpp"
#include "Scavenger.hpp"
#include "ScavengerDelegate.hpp"
Copy link
Contributor

Choose a reason for hiding this comment

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

most of these includes are not necessary anymore

bool
MM_StandardAccessBarrier::preMountContinuation(J9VMThread *vmThread, j9object_t contObject)
{
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vmThread->javaVM);
Copy link
Contributor

Choose a reason for hiding this comment

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

_extensions is already available

MM_RealtimeAccessBarrier::preMountContinuation(J9VMThread *vmThread, j9object_t contObject)
{
if (_realtimeGC->isCollectorConcurrentTracing()) {
_realtimeGC->getRealtimeDelegate()->scanContinuationJavaStack((MM_EnvironmentRealtime *)(MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread)), contObject);
Copy link
Contributor

Choose a reason for hiding this comment

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

create env in a separate line

}

void
postUnmountContinuation(J9VMThread *vmThread, j9object_t object)
{
/* Conservatively assume that via mutations of stack slots (which are not subject to access barriers),
* all post-write barriers have been triggered on this Continuation object, since it's been mounted. */
Copy link
Contributor

Choose a reason for hiding this comment

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

move this comment to at least Standard OAB

@LinHu2016 LinHu2016 force-pushed the supportConcurrentScavenger branch 2 times, most recently from 7e1db01 to ac65f97 Compare October 14, 2022 20:43
@@ -80,6 +80,8 @@ MM_StandardAccessBarrier::initialize(MM_EnvironmentBase *env)
if (!_generationalAccessBarrierComponent.initialize(env)) {
return false;
}
_scavenger = MM_GCExtensions::getExtensions(env)->scavenger;
Assert_MM_true(NULL != _scavenger);
Copy link
Contributor

Choose a reason for hiding this comment

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

It's actually possible to be null. An obvious config is Optavgpause, but I think even Optthruput will create SAB (although barely use it, not so much for real barrier stuff, but for some java specific API)

@LinHu2016 LinHu2016 force-pushed the supportConcurrentScavenger branch 2 times, most recently from 45f4c13 to 74a8ae0 Compare October 14, 2022 21:06
@@ -901,7 +902,7 @@ MM_StandardAccessBarrier::preObjectRead(J9VMThread *vmThread, J9Object *srcObjec

env->_scavengerStats._readObjectBarrierCopy += 1;
if (GLOBAL_READ_BARRIR_STATS_UPDATE_THRESHOLD == env->_scavengerStats._readObjectBarrierCopy) {
MM_AtomicOperations::addU64(&_extensions->scavengerStats._readObjectBarrierCopy, GLOBAL_READ_BARRIR_STATS_UPDATE_THRESHOLD);
MM_AtomicOperations::addU64(&_scavengerStats._readObjectBarrierCopy, GLOBAL_READ_BARRIR_STATS_UPDATE_THRESHOLD);
Copy link
Contributor

Choose a reason for hiding this comment

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

seems like editor's find&replace went too far

void
MM_RealtimeAccessBarrier::preMountContinuation(J9VMThread *vmThread, j9object_t contObject)
{
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);
Copy link
Contributor

Choose a reason for hiding this comment

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

convert it to MM_EnvironmentRealtime right here and then you don't need a cast later

@@ -179,6 +178,8 @@ class MM_ScavengerDelegate : public MM_BaseNonVirtual {
bool initialize(MM_EnvironmentBase *env);
void tearDown(MM_EnvironmentBase *env);

bool doContinuationObject(MM_EnvironmentStandard *env, omrobjectptr_t objectPtr, MM_ScavengeScanReason reason);
Copy link
Contributor

Choose a reason for hiding this comment

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

move it up above init/teardown, perhaps close to setShouldScavengeContinuationObjects?

Copy link
Contributor

Choose a reason for hiding this comment

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

BTW, we are somewhat inconsistent in naming. For example, MarkingDelegate calls this 'scan', not 'do'.... Not sure what is the right one, and if I want to fix it now (this is already growing too much).

/* concurrent scavenger in progress */
MM_EnvironmentStandard *env = (MM_EnvironmentStandard *) MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);
MM_ScavengeScanReason reason = SCAN_REASON_SCAVENGE;
_scavenger->getDelegate()->doContinuationObject(env, contObject, reason);
Copy link
Contributor

Choose a reason for hiding this comment

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

Do you know when thread is mounted first time if J9VMJDKINTERNALVMCONTINUATION_STARTED is returning true or false? Effectively no scan work should be done on first mount (obviously there is not stack yet), and we should realize that as early as possible. At least not to try to iterate stack, but ideally as early as in Interpreter in enterContinuation.
Nothing to do for this round of changes, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

before first time enterContinuation(), J9VMJDKINTERNALVMCONTINUATION_STARTED return false, enterContinuation() will set it true.

Copy link
Contributor

Choose a reason for hiding this comment

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

before first time enterContinuation(), J9VMJDKINTERNALVMCONTINUATION_STARTED return false, enterContinuation() will set it true.

OK, thanks, that's what I expected. We will still waste time to enter the callback and barrier code, but at least we will not try to setup and enter stack scanning.

@@ -51,6 +51,7 @@ class MM_StandardAccessBarrier : public MM_ObjectAccessBarrier
MM_GenerationalAccessBarrierComponent _generationalAccessBarrierComponent; /**< Generational Component of Access Barrier */
#endif /* J9VM_GC_GENERATIONAL */
MM_MarkingScheme *_markingScheme;
MM_Scavenger *_scavenger;
Copy link
Contributor

Choose a reason for hiding this comment

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

This should be under
OMR_GC_MODRON_SCAVENGER
or perhaps under
J9VM_GC_GENERATIONAL that is very similar although seems to be used more in context of barriers.

@LinHu2016 LinHu2016 force-pushed the supportConcurrentScavenger branch 2 times, most recently from cb0add1 to a210198 Compare October 17, 2022 02:47
@LinHu2016
Copy link
Contributor Author

* all post-write barriers have been triggered on this Continuation object, since it's been mounted. */
vmThread->javaVM->memoryManagerFunctions->J9WriteBarrierBatch(vmThread, object);
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(vmThread->javaVM);
extensions->accessBarrier->postUnmountContinuation(vmThread, object);
Copy link
Contributor

Choose a reason for hiding this comment

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

they now probably fit better into accessBarrier.cpp

Copy link
Contributor

Choose a reason for hiding this comment

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

please move pre/postMountContinuation into accessBarrier.cpp

@amicic
Copy link
Contributor

amicic commented Oct 17, 2022

The changes look good, but I'll let @dmitripivkine review, before launching any testing.

void
MM_StandardAccessBarrier::preMountContinuation(J9VMThread *vmThread, j9object_t contObject)
{
#if defined(J9VM_GC_GENERATIONAL)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd put this under a more specific #ifdef OMR_GC_CONCURRENT_SCAVENGER

(declaration and initialization of _scavenger would still remain under J9VM_GC_GENERATIONAL)

@@ -265,10 +266,12 @@ MM_StandardAccessBarrier::postObjectStoreImpl(J9VMThread *vmThread, J9Object *ds
{
/* If the source object is NULL, there is no need for a write barrier. */
if(NULL != srcObject) {
#if defined(J9VM_GC_GENERATIONAL)
Copy link
Contributor

Choose a reason for hiding this comment

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

I'd put this under a more specific #ifdef OMR_GC_CONCURRENT_SCAVENGER

@@ -49,6 +49,7 @@ class MM_StandardAccessBarrier : public MM_ObjectAccessBarrier
private:
#if defined(J9VM_GC_GENERATIONAL)
MM_GenerationalAccessBarrierComponent _generationalAccessBarrierComponent; /**< Generational Component of Access Barrier */
MM_Scavenger *_scavenger;
#endif /* J9VM_GC_GENERATIONAL */
MM_MarkingScheme *_markingScheme;
Copy link
Contributor

Choose a reason for hiding this comment

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

please add annotations to new _scavenger as well as existed _markingScheme variables

@dmitripivkine
Copy link
Contributor

The changes look good, but I'll let @dmitripivkine review, before launching any testing.

looks reasonable to me

For CS and Metronome, due to synchronous nature of their barriers (they
read the value of the slot and act on it immediately, for example they
may evacuate object for CS and mark object for Metronome), We fully
scan java stacks of related continuation during the virtual thread
mount.

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

amicic commented Oct 17, 2022

jenkins test sanity all jdk19

@amicic
Copy link
Contributor

amicic commented Oct 17, 2022

jenkins compile win,aix jdk8

@dmitripivkine
Copy link
Contributor

jenkins test sanity all jdk19

@amicic
Copy link
Contributor

amicic commented Oct 18, 2022

3 out of 8 specs failed sanity testing but all due to infra issue (uploading artifacts)

@dmitripivkine
Copy link
Contributor

Jenkins test sanity xLinux jdk19

@dmitripivkine
Copy link
Contributor

Jenkins test sanity pLinux jdk19

@dmitripivkine
Copy link
Contributor

Jenkins test sanity x86-64_mac jdk19

@dmitripivkine
Copy link
Contributor

Failure in AIX build is unrelated most likely. Opened new issue #16121

@dmitripivkine
Copy link
Contributor

Jenkins test sanity aix jdk19

@dmitripivkine
Copy link
Contributor

xLinux build failures related to infra, failures in AIX build looks like bad machine

@dmitripivkine
Copy link
Contributor

I think reasons for failure are unrelated, merging this item regardless

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
comp:gc project:loom Used to track Project Loom related work
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants