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

Initial changes to refactor snapshot at the beginning barrier. #2298

Merged
merged 1 commit into from
Sep 19, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion runtime/compiler/control/J9Options.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1106,7 +1106,8 @@ J9::Options::fePreProcess(void * base)
case j9gc_modron_wrtbar_cardmark: wrtbarMode = TR_WrtbarCardMark; break;
case j9gc_modron_wrtbar_cardmark_and_oldcheck: wrtbarMode = TR_WrtbarCardMarkAndOldCheck; break;
case j9gc_modron_wrtbar_cardmark_incremental: wrtbarMode = TR_WrtbarCardMarkIncremental; break;
case j9gc_modron_wrtbar_realtime: wrtbarMode = TR_WrtbarRealTime; break;
case j9gc_modron_wrtbar_satb:
case j9gc_modron_wrtbar_satb_and_oldcheck: wrtbarMode = TR_WrtbarRealTime; break;
}

#if defined(J9VM_GC_HEAP_CARD_TABLE)
Expand Down
2 changes: 1 addition & 1 deletion runtime/compiler/env/VMJ9.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1677,7 +1677,7 @@ TR_J9VMBase::thisThreadRememberedSetFragmentOffset()
{

#if defined(J9VM_GC_REALTIME)
return offsetof(J9VMThread, staccatoRememberedSetFragment);
return offsetof(J9VMThread, sATBBarrierRememberedSetFragment);
#endif
return 0;
}
Expand Down
4 changes: 2 additions & 2 deletions runtime/gc_base/modron.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@

/*******************************************************************************
* Copyright (c) 1991, 2017 IBM Corp. and others
* Copyright (c) 1991, 2018 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -123,7 +123,7 @@ extern "C" fj9object_t j9gc_objaccess_tokenFromPointer(J9VMThread *vmThread, mm_

#if defined(J9VM_GC_STACCATO)
/* Note that the "reserved" index is used for 2 different purposes with the
* staccatoRememberedSet:
* sATBBarrierRememberedSet:
* 1) As a per-thread flag indicating the double barrier is on.
* 2) As a global flag indicating the barrier is disabled.
*
Expand Down
33 changes: 32 additions & 1 deletion runtime/gc_glue_java/ConcurrentMarkingDelegate.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1991, 2017 IBM Corp. and others
* Copyright (c) 1991, 2018 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -93,6 +93,37 @@ MM_ConcurrentMarkingDelegate::signalThreadsToTraceStacks(MM_EnvironmentBase *env
_collector->getConcurrentGCStats()->setThreadsToScanCount(threadCount);
}

void
MM_ConcurrentMarkingDelegate::signalThreadsToActivateWriteBarrier(MM_EnvironmentBase *env)
{
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
GC_VMInterface::lockVMThreadList(extensions);

J9VMThread *walkThread;
GC_VMThreadListIterator vmThreadListIterator(_javaVM);
while ((walkThread = vmThreadListIterator.nextVMThread()) != NULL) {
walkThread->privateFlags |= J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE;
}
GC_VMInterface::unlockVMThreadList(extensions);
}

void
MM_ConcurrentMarkingDelegate::signalThreadsToDeactivateWriteBarrier(MM_EnvironmentBase *env)
{
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(_javaVM);
if (extensions->optimizeConcurrentWB) {
GC_VMInterface::lockVMThreadList(extensions);
GC_VMThreadListIterator vmThreadListIterator(_javaVM);
J9VMThread *walkThread;

/* Reset vmThread flag so mutators don't dirty cards or run write barriers until next concurrent KO */
while ((walkThread = vmThreadListIterator.nextVMThread()) != NULL) {
walkThread->privateFlags &= ~J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE;
}
GC_VMInterface::unlockVMThreadList(extensions);
}
}

void
MM_ConcurrentMarkingDelegate::signalThreadsToDirtyCards(MM_EnvironmentBase *env)
{
Expand Down
8 changes: 7 additions & 1 deletion runtime/gc_glue_java/ConcurrentMarkingDelegate.hpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*******************************************************************************
* Copyright (c) 1991, 2017 IBM Corp. and others
* Copyright (c) 1991, 2018 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
Expand Down Expand Up @@ -245,10 +245,16 @@ class MM_ConcurrentMarkingDelegate
*/
void signalThreadsToTraceStacks(MM_EnvironmentBase *env);

void signalThreadsToActivateWriteBarrier(MM_EnvironmentBase *env);

void signalThreadsToDeactivateWriteBarrier(MM_EnvironmentBase *env);

//TODO: STAB remove two methods bellow after the initial changes are in
void signalThreadsToDirtyCards(MM_EnvironmentBase *env);

void signalThreadsToStopDirtyingCards(MM_EnvironmentBase *env);


/**
* This method is called during card cleaning for each object associated with an uncleaned, dirty card in the card
* table. No client actions are necessary but this method may be overridden if desired to hook into card cleaning.
Expand Down
1 change: 1 addition & 0 deletions runtime/gc_glue_java/ConfigurationDelegate.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,7 @@ class MM_ConfigurationDelegate
if (extensions->alwaysCallWriteBarrier) {
writeBarrierType = gc_modron_wrtbar_always;
}

Assert_MM_true(gc_modron_wrtbar_illegal != writeBarrierType);
javaVM->gcWriteBarrierType = writeBarrierType;

Expand Down
25 changes: 15 additions & 10 deletions runtime/gc_include/ObjectAccessBarrierAPI.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -2625,8 +2625,9 @@ class MM_ObjectAccessBarrierAPI
VMINLINE void
internalPreStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)
{
if (j9gc_modron_wrtbar_realtime == _writeBarrierType) {
internalPreStoreObjectRealtime(vmThread, object, destAddress, value);
if ((j9gc_modron_wrtbar_satb == _writeBarrierType) ||
(j9gc_modron_wrtbar_satb_and_oldcheck == _writeBarrierType)) {
internalPreStoreObjectSATB(vmThread, object, destAddress, value);
}
}

Expand All @@ -2644,8 +2645,9 @@ class MM_ObjectAccessBarrierAPI
VMINLINE void
internalStaticPreStoreObject(J9VMThread *vmThread, j9object_t object, j9object_t *destAddress, j9object_t value)
{
if (j9gc_modron_wrtbar_realtime == _writeBarrierType) {
internalStaticPreStoreObjectRealtime(vmThread, object, destAddress, value);
if ((j9gc_modron_wrtbar_satb == _writeBarrierType) ||
(j9gc_modron_wrtbar_satb_and_oldcheck == _writeBarrierType)) {
internalStaticPreStoreObjectSATB(vmThread, object, destAddress, value);
}
}

Expand All @@ -2658,10 +2660,10 @@ class MM_ObjectAccessBarrierAPI
*
*/
VMINLINE void
internalPreStoreObjectRealtime(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)
internalPreStoreObjectSATB(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)
{
#if defined(J9VM_GC_REALTIME)
J9VMGCRememberedSetFragment *fragment = &vmThread->staccatoRememberedSetFragment;
J9VMGCRememberedSetFragment *fragment = &vmThread->sATBBarrierRememberedSetFragment;
J9VMGCRememberedSet *parent = fragment->fragmentParent;
/* Check if the barrier is enabled. No work if barrier is not enabled */
if (0 != parent->globalFragmentIndex) {
Expand Down Expand Up @@ -2689,10 +2691,10 @@ class MM_ObjectAccessBarrierAPI
*
*/
VMINLINE void
internalStaticPreStoreObjectRealtime(J9VMThread *vmThread, j9object_t object, j9object_t *destAddress, j9object_t value)
internalStaticPreStoreObjectSATB(J9VMThread *vmThread, j9object_t object, j9object_t *destAddress, j9object_t value)
{
#if defined(J9VM_GC_REALTIME)
J9VMGCRememberedSetFragment *fragment = &vmThread->staccatoRememberedSetFragment;
J9VMGCRememberedSetFragment *fragment = &vmThread->sATBBarrierRememberedSetFragment;
J9VMGCRememberedSet *parent = fragment->fragmentParent;
/* Check if the barrier is enabled. No work if barrier is not enabled */
if (0 != parent->globalFragmentIndex) {
Expand Down Expand Up @@ -2763,7 +2765,9 @@ class MM_ObjectAccessBarrierAPI
internalPostObjectStoreCardTable(vmThread, object, value);
break;
case j9gc_modron_wrtbar_none:
case j9gc_modron_wrtbar_realtime:
case j9gc_modron_wrtbar_satb:
case j9gc_modron_wrtbar_satb_and_oldcheck:
//TODO SATB change to handle gencon, decide where to do it in pre/post store
break;
default:
/* Should assert as all real types are handled. Should never get here
Expand All @@ -2790,7 +2794,8 @@ class MM_ObjectAccessBarrierAPI
internalPostBatchStoreObjectCardTable(vmThread, object);
break;
case j9gc_modron_wrtbar_none:
case j9gc_modron_wrtbar_realtime:
case j9gc_modron_wrtbar_satb:
case j9gc_modron_wrtbar_satb_and_oldcheck:
break;
default:
/* Should assert as all real types are handled. Should never get here
Expand Down
3 changes: 2 additions & 1 deletion runtime/gc_include/j9modron.h
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,8 @@ typedef enum {
j9gc_modron_wrtbar_cardmark = gc_modron_wrtbar_cardmark,
j9gc_modron_wrtbar_cardmark_incremental = gc_modron_wrtbar_cardmark_incremental,
j9gc_modron_wrtbar_cardmark_and_oldcheck = gc_modron_wrtbar_cardmark_and_oldcheck,
j9gc_modron_wrtbar_realtime = gc_modron_wrtbar_realtime,
j9gc_modron_wrtbar_satb = gc_modron_wrtbar_satb,
j9gc_modron_wrtbar_satb_and_oldcheck = gc_modron_wrtbar_satb_and_oldcheck,
j9gc_modron_wrtbar_count = gc_modron_wrtbar_count
} J9WriteBarrierType;

Expand Down
145 changes: 142 additions & 3 deletions runtime/gc_modron_standard/StandardAccessBarrier.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,29 @@ MM_StandardAccessBarrier::newInstance(MM_EnvironmentBase *env)
return barrier;
}

/**
* Enables the double barrier on the provided thread.
*/
void
MM_StandardAccessBarrier::setDoubleBarrierActiveOnThread(MM_EnvironmentBase* env)
{
MM_GCExtensions::getExtensions(env)->sATBBarrierRememberedSet->preserveLocalFragmentIndex(env, &(((J9VMThread *)env->getLanguageVMThread())->sATBBarrierRememberedSetFragment));
}

void
MM_StandardAccessBarrier::initializeForNewThread(MM_EnvironmentBase* env)
{
#if defined(OMR_GC_REALTIME)
if (_extensions->configuration->isSnapshotAtTheBeginningBarrierEnabled()) {

_extensions->sATBBarrierRememberedSet->initializeFragment(env, &(((J9VMThread *)env->getLanguageVMThread())->sATBBarrierRememberedSetFragment));
if (isDoubleBarrierActive()) {
setDoubleBarrierActiveOnThread(env);
}
}
#endif /* OMR_GC_REALTIME */
}

bool
MM_StandardAccessBarrier::initialize(MM_EnvironmentBase *env)
{
Expand Down Expand Up @@ -92,13 +115,122 @@ MM_StandardAccessBarrier::tearDown(MM_EnvironmentBase *env)
MM_ObjectAccessBarrier::tearDown(env);
}

/**
* Unmarked, heap reference, about to be deleted (or overwritten), while marking
* is in progress is to be remembered for later marking and scanning.
*/
void
MM_StandardAccessBarrier::rememberObjectToRescan(MM_EnvironmentBase *env, J9Object *object)
{
MM_ParallelGlobalGC *globalCollector = (MM_ParallelGlobalGC *)_extensions->getGlobalCollector();

if (globalCollector->getMarkingScheme()->markObject(env, object, true)) {
rememberObjectImpl(env, object);
}
}

/**
* Unmarked, heap reference, about to be deleted (or overwritten), while marking
* is in progress is to be remembered for later marking and scanning.
* This method is called by MM_StandardAccessBarrier::rememberObject()
*/
void
MM_StandardAccessBarrier::rememberObjectImpl(MM_EnvironmentBase *env, J9Object* object)
{
J9VMThread *vmThread = (J9VMThread *)env->getLanguageVMThread();
_extensions->sATBBarrierRememberedSet->storeInFragment(env, &vmThread->sATBBarrierRememberedSetFragment, (UDATA *)object);
}


bool
MM_StandardAccessBarrier::preObjectStoreImpl(J9VMThread *vmThread, J9Object *destObject, fj9object_t *destAddress, J9Object *value, bool isVolatile)
{
MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);

if (isSATBBarrierActive(env)) {
if (NULL != destObject) {
if (isDoubleBarrierActiveOnThread(vmThread)) {
rememberObjectToRescan(env, value);
}

J9Object *oldObject = NULL;
protectIfVolatileBefore(vmThread, isVolatile, true, false);
oldObject = mmPointerFromToken(vmThread, *destAddress);
protectIfVolatileAfter(vmThread, isVolatile, true, false);
rememberObjectToRescan(env, oldObject);
}
}

return true;
}

bool
MM_StandardAccessBarrier::preObjectStoreImpl(J9VMThread *vmThread, J9Object **destAddress, J9Object *value, bool isVolatile)
{
MM_EnvironmentBase* env = MM_EnvironmentBase::getEnvironment(vmThread->omrVMThread);

if (isSATBBarrierActive(env)) {
if (isDoubleBarrierActiveOnThread(vmThread)) {
rememberObjectToRescan(env, value);
}
J9Object* oldObject = NULL;
protectIfVolatileBefore(vmThread, isVolatile, true, false);
oldObject = *destAddress;
protectIfVolatileAfter(vmThread, isVolatile, true, false);
rememberObjectToRescan(env, oldObject);
}

return true;
}
/**
* @copydoc MM_ObjectAccessBarrier::preObjectStore()
*
* Metronome uses a snapshot-at-the-beginning algorithm, but with a fuzzy snapshot in the
* sense that threads are allowed to run during the root scan. This requires a "double
* barrier." The barrier is active from the start of root scanning through the end of
* tracing. For an unscanned thread performing a store, the new value is remembered by
* the collector. For any thread performing a store (whether scanned or not), the old
* value is remembered by the collector before being overwritten (thus this barrier must be
* positioned as a pre-store barrier). For the latter ("Yuasa barrier") aspect of the
* double barrier, only the first overwritten value needs to be remembered (remembering
* others is harmless but not needed), and so we omit synchronization on the reading of the
* old value.
**/
bool
MM_StandardAccessBarrier::preObjectStore(J9VMThread *vmThread, J9Object *destObject, fj9object_t *destAddress, J9Object *value, bool isVolatile)
{
return preObjectStoreImpl(vmThread, destObject, destAddress, value, isVolatile);
}

/**
* @copydoc MM_MetronomeAccessBarrier::preObjectStore()
*
* Used for stores into classes
*/
bool
MM_StandardAccessBarrier::preObjectStore(J9VMThread *vmThread, J9Object *destClass, J9Object **destAddress, J9Object *value, bool isVolatile)
{
return preObjectStoreImpl(vmThread, destAddress, value, isVolatile);
}

/**
* @copydoc MM_MetronomeAccessBarrier::preObjectStore()
*
* Used for stores into internal structures
*/
bool
MM_StandardAccessBarrier::preObjectStore(J9VMThread *vmThread, J9Object **destAddress, J9Object *value, bool isVolatile)
{
return preObjectStoreImpl(vmThread, destAddress, value, isVolatile);
}
/**
* Called after an object is stored into another object.
*/
void
MM_StandardAccessBarrier::postObjectStore(J9VMThread *vmThread, J9Object *destObject, fj9object_t *destAddress, J9Object *value, bool isVolatile)
{
postObjectStoreImpl(vmThread, destObject, value);

}

/**
Expand Down Expand Up @@ -159,9 +291,7 @@ MM_StandardAccessBarrier::postObjectStoreImpl(J9VMThread *vmThread, J9Object *ds

#if defined(OMR_GC_MODRON_CONCURRENT_MARK)
/* Call the concurrent write barrier if required */
if(_extensions->concurrentMark &&
(vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE) &&
_extensions->isOld(dstObject)) {
if(isIncrementalUpdateBarrierActive(vmThread) && _extensions->isOld(dstObject)) {
J9ConcurrentWriteBarrierStore(vmThread->omrVMThread, dstObject, srcObject);
}
#endif /* OMR_GC_MODRON_CONCURRENT_MARK */
Expand Down Expand Up @@ -481,6 +611,10 @@ I_32
MM_StandardAccessBarrier::backwardReferenceArrayCopyIndex(J9VMThread *vmThread, J9IndexableObject *srcObject, J9IndexableObject *destObject, I_32 srcIndex, I_32 destIndex, I_32 lengthInSlots)
{
I_32 retValue = ARRAY_COPY_NOT_DONE;
//TODO SATB re-enable opt?
if (_extensions->configuration->isSnapshotAtTheBeginningBarrierEnabled()) {
Copy link
Contributor

Choose a reason for hiding this comment

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

this (opt for ref array copying) is ok to disable, for the initial contribution

return retValue;
}

if(0 == lengthInSlots) {
retValue = ARRAY_COPY_SUCCESSFUL;
Expand All @@ -507,8 +641,13 @@ MM_StandardAccessBarrier::backwardReferenceArrayCopyIndex(J9VMThread *vmThread,
I_32
MM_StandardAccessBarrier::forwardReferenceArrayCopyIndex(J9VMThread *vmThread, J9IndexableObject *srcObject, J9IndexableObject *destObject, I_32 srcIndex, I_32 destIndex, I_32 lengthInSlots)
{
//TODO SATB re-enable opt
I_32 retValue = ARRAY_COPY_NOT_DONE;

if (_extensions->configuration->isSnapshotAtTheBeginningBarrierEnabled()) {
return retValue;
}

if(0 == lengthInSlots) {
retValue = ARRAY_COPY_SUCCESSFUL;
} else {
Expand Down
Loading