Path: blob/master/runtime/gc_base/ReferenceChainWalker.hpp
5985 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(REFERENCECHAINWALKER_HPP_)23#define REFERENCECHAINWALKER_HPP_2425#include "j9accessbarrier.h"26#include "j9cfg.h"27#include "j9comp.h"28#include "j9modron.h"29#include "modronbase.h"3031#include "ModronTypes.hpp"32#include "ReferenceChainWalkerMarkMap.hpp"33#include "RootScanner.hpp"34#include "RootScannerTypes.h"3536class GC_HashTableIterator;37class GC_JVMTIObjectTagTableIterator;38class GC_SlotObject;39class GC_VMClassSlotIterator;40class GC_VMThreadIterator;41class MM_EnvironmentBase;42class MM_Heap;43class MM_OwnableSynchronizerObjectList;44class MM_UnfinalizedObjectList;4546/**47* Interface for walking reference chains in the system starting either at the root set or a specified object.48*49* MM_ReferenceChainWalker makes use of the general MM_RootScanner for walking the root set. It uses a user50* callback to provide the function to be done on all references and roots. The type of reference is reported back51* to the callback functions.52*53* The objects are queued in a stack that makes use of the OBJECT_HEADER_COLOR_MASK bits of the object header54* flags to indicate whether an object has been queued, or overflowed. The stack is allocated as an array of slots55* of the size passed in to the constructor. When the stack runs out of space, half of the objects are removed56* and have their overflow flag set. These objects are scanned for when the stack next becomes empty.57*58* @note You must use <code>initialize</code> and <code>kill</code> to allocate and deallocate the internal structures.59* @note Does not handle overflowing stack allocated objects.60* @ingroup GC_Base61*/62class MM_ReferenceChainWalker : public MM_RootScanner63{64private:65J9Object **_queue; /**< Main queue used for queuing objects */66J9Object **_queueEnd; /**< End of the queue used for queuing objects */67J9Object **_queueCurrent; /**< Current position of the queue used for queuing objects */68UDATA _queueSlots; /**< Size of the queue before overflow occurs */69J9MODRON_REFERENCE_CHAIN_WALKER_CALLBACK *_userCallback; /**< User callback function to be called on every reachable slot */70void *_userData; /**< User data to be passed to the user callback function */71bool _hasOverflowed; /**< Set when the queue has overflowed */72bool _isProcessingOverflow; /**< Set when the queue is currently processing the overflow */73bool _isTerminating; /**< Set when no more callbacks should be queued */74bool _shouldPreindexInterfaceFields; /**< if true, indexes interface fields of the class being visited before class and superclass fields, otherwise, returns them in the order they appear in an object instance (CMVC 142897) */75MM_ReferenceChainWalkerMarkMap *_markMap; /**< Mark Map created for Reference Chain Walker */76MM_Heap *_heap; /**< Cached pointer to the heap */77void *_heapBase; /**< Cached value of the heap base */78void *_heapTop; /**< Cached value of the heap top */7980void clearQueue();81void pushObject(J9Object *obj);82J9Object *popObject();8384void findOverflowObjects();8586virtual void scanClass(J9Class *clazz);87virtual void scanObject(J9Object *objectPtr);88virtual void scanMixedObject(J9Object *objectPtr);89virtual void scanPointerArrayObject(J9IndexableObject *objectPtr);90virtual void scanReferenceMixedObject(J9Object *objectPtr);9192virtual void doClassLoader(J9ClassLoader *classLoader);9394#if defined(J9VM_GC_FINALIZATION)95virtual void doUnfinalizedObject(J9Object *objectPtr, MM_UnfinalizedObjectList *list);96virtual void doFinalizableObject(J9Object *objectPtr);97#endif /* J9VM_GC_FINALIZATION */9899/**100* @todo Provide function documentation101*/102virtual void doOwnableSynchronizerObject(J9Object *objectPtr, MM_OwnableSynchronizerObjectList *list);103104virtual void doJNIWeakGlobalReference(J9Object **slotPtr);105virtual void doJNIGlobalReferenceSlot(J9Object **slotPtr, GC_JNIGlobalReferenceIterator *jniGlobalReferenceIterator);106107#if defined(J9VM_GC_MODRON_SCAVENGER)108virtual void doRememberedSetSlot(J9Object **slotPtr, GC_RememberedSetSlotIterator *rememberedSetSlotIterator);109#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */110111#if defined(J9VM_OPT_JVMTI)112virtual void doJVMTIObjectTagSlot(J9Object **slotPtr, GC_JVMTIObjectTagTableIterator *objectTagTableIterator);113#endif /* J9VM_OPT_JVMTI */114115virtual void doMonitorReference(J9ObjectMonitor *objectMonitor, GC_HashTableIterator *monitorReferenceIterator);116virtual void doStringTableSlot(J9Object **slotPtr, GC_StringTableIterator *stringTableIterator);117virtual void doVMClassSlot(J9Class *classPtr);118virtual void doVMThreadSlot(J9Object **slotPtr, GC_VMThreadIterator *vmThreadIterator);119virtual void doStackSlot(J9Object **slotPtr, void *walkState, const void* stackLocation);120virtual void doSlot(J9Object **slotPtr);121virtual void doClassSlot(J9Class *classPtr);122virtual void doClass(J9Class *clazz);123virtual void doSlot(J9Object **slotPtr, IDATA type, IDATA index, J9Object *sourceObj);124virtual void doClassSlot(J9Class *classPtr, IDATA type, IDATA index, J9Object *sourceObj);125using MM_RootScanner::doFieldSlot;126virtual void doFieldSlot(GC_SlotObject *slotObject, IDATA type, IDATA index, J9Object *sourceObj);127128MMINLINE virtual CompletePhaseCode scanClassesComplete(MM_EnvironmentBase *env) {129reportScanningStarted(RootScannerEntity_ClassesComplete);130completeScan();131reportScanningEnded(RootScannerEntity_ClassesComplete);132return complete_phase_OK;133}134135MMINLINE virtual CompletePhaseCode scanWeakReferencesComplete(MM_EnvironmentBase *env) {136return complete_phase_OK;137}138MMINLINE virtual CompletePhaseCode scanSoftReferencesComplete(MM_EnvironmentBase *env) {139return complete_phase_OK;140}141142MMINLINE virtual CompletePhaseCode scanPhantomReferencesComplete(MM_EnvironmentBase *env) {143return complete_phase_OK;144}145146#if defined(J9VM_GC_FINALIZATION)147MMINLINE virtual CompletePhaseCode scanUnfinalizedObjectsComplete(MM_EnvironmentBase *env) {148reportScanningStarted(RootScannerEntity_UnfinalizedObjectsComplete);149completeScan();150reportScanningEnded(RootScannerEntity_UnfinalizedObjectsComplete);151return complete_phase_OK;152}153#endif /* J9VM_GC_FINALIZATION */154155virtual CompletePhaseCode scanMonitorReferencesComplete(MM_EnvironmentBase *env) {156return complete_phase_OK;157}158159void completeScan();160161162MMINLINE bool isHeapObject(J9Object* objectPtr)163{164return ((_heapBase <= (U_8 *)objectPtr) && (_heapTop > (U_8 *)objectPtr));165}166167168MMINLINE bool isMarked(J9Object *object)169{170if (isHeapObject(object)) {171/* check one bit in mark map only - return true if 10 or 11 */172return _markMap->isBitSet(object);173} else {174return true;175}176}177178MMINLINE void setMarked(J9Object * object)179{180if (isHeapObject(object)) {181/* mark one bit only (next one has to be 0) - set 10 */182_markMap->setBit(object);183}184}185186MMINLINE void setOverflow(J9Object *object)187{188if (isHeapObject(object)) {189UDATA referenceSize = _env->compressObjectReferences() ? sizeof(uint32_t) : sizeof(uintptr_t);190/* set both mark bits - set 11 */191_markMap->setBit(object);192_markMap->setBit((J9Object *)((UDATA)object + referenceSize));193}194}195196MMINLINE bool isOverflow(J9Object * object)197{198if (isHeapObject(object)) {199UDATA referenceSize = _env->compressObjectReferences() ? sizeof(uint32_t) : sizeof(uintptr_t);200/* check both bits in mark map - return true if 11 */201return (_markMap->isBitSet(object) && _markMap->isBitSet((J9Object *)((UDATA)object + referenceSize)));202} else {203return false;204}205}206207MMINLINE void clearOverflow(J9Object * object)208{209if (isHeapObject(object)) {210UDATA referenceSize = _env->compressObjectReferences() ? sizeof(uint32_t) : sizeof(uintptr_t);211/* clear both mark bits - set 00 */212_markMap->clearBit(object);213_markMap->clearBit((J9Object *)((UDATA)object + referenceSize));214}215}216217protected:218219public:220MM_ReferenceChainWalker(MM_EnvironmentBase *env, UDATA queueSlots, J9MODRON_REFERENCE_CHAIN_WALKER_CALLBACK *userCallback, void *userData) :221MM_RootScanner(env, true),222_queue(NULL),223_queueEnd(NULL),224_queueCurrent(NULL),225_queueSlots(queueSlots),226_userCallback(userCallback),227_userData(userData),228_hasOverflowed(false),229_isProcessingOverflow(false),230_isTerminating(false),231_shouldPreindexInterfaceFields(true), /* default to behaviour required for Java6/heap11 */232_markMap(NULL),233_heap(NULL),234_heapBase(NULL),235_heapTop(NULL)236{237_typeId = __FUNCTION__;238#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)239setClassDataAsRoots(false);240#endif /* J9VM_GC_DYNAMIC_CLASS_UNLOADING */241};242243bool initialize(MM_EnvironmentBase *env);244void tearDown(MM_EnvironmentBase *env);245246void scanReachableObjects(MM_EnvironmentBase *env) {247scanAllSlots(env);248completeScan();249}250251void scanReachableFromObject(MM_EnvironmentBase *env, J9Object *objectPtr) {252pushObject(objectPtr);253completeScan();254}255256/**257* Added to support bi-modal interface indexing in JVMTI (CMVC 142897).258* Detail: heap10 requires no pre-indexing in order to preserve Java5 behaviour but heap11 requires pre-indexing to pass a Java6 JCK259*/260void setPreindexInterfaceFields(bool shouldPreindexInterfaceFields) { _shouldPreindexInterfaceFields = shouldPreindexInterfaceFields; }261};262263#endif /* REFERENCECHAINWALKER_HPP_ */264265266267