Path: blob/master/runtime/gc_glue_java/ConcurrentMarkingDelegate.hpp
5990 views
/*******************************************************************************1* Copyright (c) 1991, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception20*******************************************************************************/2122#if !defined(CONCURRENTMARKINGDELEGATE_HPP_)23#define CONCURRENTMARKINGDELEGATE_HPP_2425#include "j9.h"26#include "j9cfg.h"2728#if defined(OMR_GC_MODRON_CONCURRENT_MARK)29#include "j9class.h"30#include "j9consts.h"31#include "j9cp.h"32#include "j9modron.h"33#include "j9nongenerated.h"34#include "j9nonbuilder.h"35#include "modron.h"36#include "objectdescription.h"37#include "omrgcconsts.h"3839#include "ConcurrentSafepointCallbackJava.hpp"40#include "EnvironmentBase.hpp"41#include "GCExtensionsBase.hpp"42#include "MarkingScheme.hpp"43#include "ReferenceObjectBuffer.hpp"44#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)45#include "ScanClassesMode.hpp"46#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */4748class GC_VMThreadIterator;49class MM_ConcurrentGC;50class MM_MarkingScheme;5152/**53* Provides language-specific support for marking.54*/55class MM_ConcurrentMarkingDelegate56{57/*58* Data members59*/60private:6162protected:63J9JavaVM *_javaVM;64GC_ObjectModel *_objectModel;65MM_ConcurrentGC *_collector;66MM_MarkingScheme *_markingScheme;67#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)68MM_ScanClassesMode _scanClassesMode; /** Support for dynamic class unloading in concurrent mark */69#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */7071public:72/* This enum extends ConcurrentStatus with values in the exclusive range (CONCURRENT_ROOT_TRACING,73* CONCURRENT_TRACE_ONLY). ConcurrentStatus extensions allow the client language to define discrete74* units of work that can be executed in parallel by concurrent threads. ConcurrentGC will call75* MM_ConcurrentMarkingDelegate::collectRoots(..., concurrentStatus, ...) only once with each76* client-defined status value. The thread that receives the call can check the concurrentStatus77* value to select and execute the appropriate unit of work.78*79* @see ConcurrentStatus (omrgcconsts.h)80*/81enum {82CONCURRENT_ROOT_TRACING1 = CONCURRENT_ROOT_TRACING + 183, CONCURRENT_ROOT_TRACING2 = CONCURRENT_ROOT_TRACING + 284, CONCURRENT_ROOT_TRACING3 = CONCURRENT_ROOT_TRACING + 385, CONCURRENT_ROOT_TRACING4 = CONCURRENT_ROOT_TRACING + 486};8788typedef struct markSchemeStackIteratorData {89MM_MarkingScheme *markingScheme;90MM_EnvironmentBase *env;91} markSchemeStackIteratorData;9293/*94* Function members95*/96private:97void collectJNIRoots(MM_EnvironmentBase *env, bool *completedJNIRoots);98void collectClassRoots(MM_EnvironmentBase *env, bool *completedClassRoots, bool *classesMarkedAsRoots);99void collectFinalizableRoots(MM_EnvironmentBase *env, bool *completedFinalizableRoots);100void collectStringRoots(MM_EnvironmentBase *env, bool *completedStringRoots, bool *collectedStringConstants);101#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)102uintptr_t concurrentClassMark(MM_EnvironmentBase *env, bool *completedClassMark);103#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */104105protected:106107public:108/**109* Initialize the delegate.110*111* @param env environment for calling thread112* @return true if delegate initialized successfully113*/114bool initialize(MM_EnvironmentBase *env, MM_ConcurrentGC *collector);115116/**117* In the case of Weak Consistency platforms we require this method to bring mutator threads to a safe point. A safe118* point is a point at which a GC may occur.119*120* @param[in] env The environment for the calling thread.121* @return An instance of a MM_ConcurrentSafepointCallback instance that can signal all mutator threads and cause them122* to synchronize at a safe point123* @see MM_ConcurrentSafepointCallback124*/125MMINLINE MM_ConcurrentSafepointCallback*126createSafepointCallback(MM_EnvironmentBase *env)127{128return MM_ConcurrentSafepointCallbackJava::newInstance(env);129}130131/**132* Concurrent marking component maintains a background helper thread to assist with concurrent marking133* tasks. The delegate may provide a specialized signal handler (and associated argument) to process134* signals raised from this thread.135*136* @param[out] signalHandlerArg receives (nullable) pointer to argument to be passed to signal handler when invoked137* @return a pointer to the signal handler function (or NULL if no signal handler)138*/139MMINLINE omrsig_handler_fn140getProtectedSignalHandler(void **signalHandlerArg)141{142*signalHandlerArg = (void *)_javaVM;143return (omrsig_handler_fn)_javaVM->internalVMFunctions->structuredSignalHandlerVM;144}145146/**147* Test whether a GC can be started. Under some circumstances it may be desirable to circumvent continued148* concurrent marking and allow a GC to kick off immediately. In that case this method should return true149* and set the kick off reason.150*151* If this method returns false, the GC cycle may be started immediately. Otherwise, concurrent marking152* will kick off and the GC cycle will be deferred until concurrent marking completes.153*154* @param env the calling thread environment155* @param gcCode the GC code identifying the cause of the GC request156* @param languageKickoffReason set this to the value to be reported as kickoff reson in verbose GC log157* @see J9MMCONSTANT_* (j9nonbuilder.h) for gcCode values158* @return true if Kickoff can be forced159*/160MMINLINE bool161canForceConcurrentKickoff(MM_EnvironmentBase *env, uintptr_t gcCode, uintptr_t *languageKickoffReason)162{163if (J9MMCONSTANT_IMPLICIT_GC_PERCOLATE_UNLOADING_CLASSES == gcCode) {164*languageKickoffReason = FORCED_UNLOADING_CLASSES;165return true;166}167return false;168}169170MMINLINE uintptr_t171getNextTracingMode(uintptr_t executionMode)172{173uintptr_t nextExecutionMode = CONCURRENT_TRACE_ONLY;174175switch (executionMode) {176case CONCURRENT_ROOT_TRACING:177nextExecutionMode = CONCURRENT_ROOT_TRACING1;178break;179case CONCURRENT_ROOT_TRACING1:180nextExecutionMode = CONCURRENT_ROOT_TRACING2;181break;182case CONCURRENT_ROOT_TRACING2:183nextExecutionMode = CONCURRENT_ROOT_TRACING3;184break;185case CONCURRENT_ROOT_TRACING3:186nextExecutionMode = CONCURRENT_ROOT_TRACING4;187break;188case CONCURRENT_ROOT_TRACING4:189nextExecutionMode = CONCURRENT_TRACE_ONLY;190break;191default:192Assert_MM_unreachable();193}194195return nextExecutionMode;196}197198MMINLINE uintptr_t199collectRoots(MM_EnvironmentBase *env, uintptr_t concurrentStatus, bool *collectedRoots, bool *paidTax)200{201uintptr_t bytesScanned = 0;202*collectedRoots = true;203*paidTax = true;204205switch (concurrentStatus) {206case CONCURRENT_ROOT_TRACING1:207collectJNIRoots(env, collectedRoots);208break;209case CONCURRENT_ROOT_TRACING2:210collectClassRoots(env, paidTax, collectedRoots);211break;212case CONCURRENT_ROOT_TRACING3:213collectFinalizableRoots(env, collectedRoots);214break;215case CONCURRENT_ROOT_TRACING4:216collectStringRoots(env, paidTax, collectedRoots);217break;218default:219Assert_MM_unreachable();220}221222return bytesScanned;223}224225MMINLINE void226concurrentInitializationComplete(MM_EnvironmentBase *env)227{228#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)229_scanClassesMode.setScanClassesMode(MM_ScanClassesMode::SCAN_CLASSES_DISABLED); /* disable concurrent classes scan - default state */230#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */231}232233MMINLINE void cardCleaningStarted(MM_EnvironmentBase *env)234{235#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)236/* If scanning of classes is enabled and was completed in CONCURRENT_TRACE_ONLY state - start it again*/237_scanClassesMode.switchScanClassesMode(MM_ScanClassesMode::SCAN_CLASSES_COMPLETE, MM_ScanClassesMode::SCAN_CLASSES_NEED_TO_BE_EXECUTED);238#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */239}240241/**242* Signal all threads for call back. Iterate over all threads and signal each to call scanThread()243* so we can scan their stacks for roots.244*/245void signalThreadsToTraceStacks(MM_EnvironmentBase *env);246247void signalThreadsToActivateWriteBarrier(MM_EnvironmentBase *env);248249void signalThreadsToDeactivateWriteBarrier(MM_EnvironmentBase *env);250251/**252* This method is called during card cleaning for each object associated with an uncleaned, dirty card in the card253* table. No client actions are necessary but this method may be overridden if desired to hook into card cleaning.254*255* @param[in] env The environment for the calling thread.256* @param[in] objectPtr Reference to an object associated with an uncleaned, dirty card.257*/258MMINLINE void259processItem(MM_EnvironmentBase *env, omrobjectptr_t objectPtr)260{261if (GC_ObjectModel::SCAN_REFERENCE_MIXED_OBJECT == _objectModel->getScanType(objectPtr)) {262/* since we popped this object from the work packet, it is our responsibility to record it in the list of reference objects */263/* we know that the object must be in the collection set because it was on a work packet */264/* we don't need to process cleared or enqueued references */265if (GC_ObjectModel::REF_STATE_INITIAL == J9GC_J9VMJAVALANGREFERENCE_STATE(env, objectPtr)) {266env->getGCEnvironment()->_referenceObjectBuffer->add(env, objectPtr);267}268}269}270271/**272* Scan a thread structure and stack frames for roots. Implementation must call273* MM_MarkingScheme::markObject(MM_EnvironmentBase *, omrobjectptr_t) for274* each heap object reference found on the thread's stack or in thread structure.275*276* @param env the thread environment for the thread to be scanned277* @return true if the thread was scanned successfully278*/279bool scanThreadRoots(MM_EnvironmentBase *env);280281/**282* Flush any roots held in thread local buffers.283*284* @param env the thread environment for the thread to be flushed285* @return true if any data were flushed, false otherwise286*/287MMINLINE bool288flushThreadRoots(MM_EnvironmentBase *env)289{290bool wasEmpty = env->getGCEnvironment()->_referenceObjectBuffer->isEmpty();291env->getGCEnvironment()->_referenceObjectBuffer->flush(env);292return !wasEmpty;293}294295void abortCollection(MM_EnvironmentBase *env);296297/**298*299*/300MMINLINE bool301startConcurrentScanning(MM_EnvironmentBase *env, uintptr_t *bytesTraced, bool *collectedRoots)302{303*bytesTraced = 0;304*collectedRoots = false;305bool started = false;306#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)307if (_scanClassesMode.switchScanClassesMode(MM_ScanClassesMode::SCAN_CLASSES_NEED_TO_BE_EXECUTED, MM_ScanClassesMode::SCAN_CLASSES_CURRENTLY_ACTIVE)) { /* currently not running */308*bytesTraced = concurrentClassMark(env, collectedRoots);309started = true;310}311#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */312return started;313}314315MMINLINE void316concurrentScanningStarted(MM_EnvironmentBase *env, uintptr_t bytesTraced)317{318#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)319if (0 != bytesTraced) {320setConcurrentScanning(env);/* need more iterations */321} else {322_scanClassesMode.setScanClassesMode(MM_ScanClassesMode::SCAN_CLASSES_COMPLETE); /* complete for now */323}324#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */325}326327MMINLINE void328setConcurrentScanning(MM_EnvironmentBase *env)329{330#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)331_scanClassesMode.setScanClassesMode(MM_ScanClassesMode::SCAN_CLASSES_NEED_TO_BE_EXECUTED);332#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */333}334335MMINLINE bool336isConcurrentScanningComplete(MM_EnvironmentBase *env)337{338#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)339return !_scanClassesMode.isPendingOrActiveMode();340#else341return true;342#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */343}344345MMINLINE uintptr_t346reportConcurrentScanningMode(MM_EnvironmentBase *env)347{348#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)349return _scanClassesMode.getScanClassesMode();350#else351return 0;352#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */353}354355bool setupClassScanning(MM_EnvironmentBase *env);356357/**358* Constructor.359*/360MMINLINE MM_ConcurrentMarkingDelegate()361: _javaVM(NULL)362, _objectModel(NULL)363, _collector(NULL)364, _markingScheme(NULL)365{ }366};367368#endif /* defined(OMR_GC_MODRON_CONCURRENT_MARK) */369#endif /* CONCURRENTMARKINGDELEGATE_HPP_ */370371372