Path: blob/master/runtime/gc_api/HeapIteratorAPI.cpp
5985 views
/*******************************************************************************1* Copyright (c) 1991, 2019 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#include "j9.h"23#include "j9cfg.h"24#include "j9port.h"25#include "modron.h"26#include "HeapIteratorAPI.h"27#include "ModronAssertions.h"2829#include "ArrayletLeafIterator.hpp"30#include "GCExtensionsBase.hpp"31#include "HeapIteratorAPIRootIterator.hpp"32#include "HeapIteratorAPIBufferedIterator.hpp"33#include "HeapRegionDescriptor.hpp"34#if defined(OMR_GC_SEGREGATED_HEAP)35#include "HeapRegionDescriptorSegregated.hpp"36#endif /* defined(OMR_GC_SEGREGATED_HEAP) */37#include "HeapRegionIterator.hpp"38#include "HeapRegionManager.hpp"39#include "MemorySpace.hpp"40#include "MemorySubSpace.hpp"41#include "MixedObjectIterator.hpp"42#include "ObjectAccessBarrier.hpp"43#include "OwnableSynchronizerObjectList.hpp"44#include "PointerArrayIterator.hpp"45#include "SlotObject.hpp"46#include "VMInterface.hpp"4748static void49initializeRegionDescriptor(50J9MM_IterateRegionDescriptor *descriptor,51const char* name,52UDATA id,53UDATA objectAlignment,54UDATA objectMinimumSize,55void* start,56UDATA size);5758static void59initializeRegionDescriptor(60MM_GCExtensionsBase* extensions,61J9MM_IterateRegionDescriptor *descriptor,62MM_HeapRegionDescriptor *region);63static void64initializeObjectDescriptor(65J9JavaVM *javaVM,66J9MM_IterateObjectDescriptor *descriptor,67J9MM_IterateRegionDescriptor *regionDesc,68j9object_t object);6970static jvmtiIterationControl71iterateRegions(72J9JavaVM* vm,73J9MM_IterateSpaceDescriptor *space,74UDATA flags,75jvmtiIterationControl (*func)(J9JavaVM* vm, J9MM_IterateRegionDescriptor *regionDesc, void *userData),76void *userData);7778static jvmtiIterationControl79iterateRegionObjects(80J9JavaVM *vm,81J9MM_IterateRegionDescriptor *region,82UDATA flags,83jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateObjectDescriptor *objectDesc, void *userData),84void *userData);8586extern "C" {8788/* used by j9mm_iterate_all_objects */89static jvmtiIterationControl internalIterateHeaps(J9JavaVM *vm, J9MM_IterateHeapDescriptor *heap, void *userData);90static jvmtiIterationControl internalIterateSpaces(J9JavaVM *vm, J9MM_IterateSpaceDescriptor *space, void *userData);91static jvmtiIterationControl internalIterateRegions(J9JavaVM *vm, J9MM_IterateRegionDescriptor *region, void *userData);9293typedef struct J9MM_CallbackDataHolderPrivate{94jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateObjectDescriptor *object, void *userData);95void *userData;96J9PortLibrary *portLibrary;97UDATA flags;98} J9MM_CallbackDataHolderPrivate;99100101typedef enum J9MM_RegionType{102j9mm_region_type_region = 0103} J9MM_RegionType;104105typedef struct J9MM_IterateRegionDescriptorPrivate {106J9MM_IterateRegionDescriptor descriptor; /**< Public region descriptor */107J9MM_RegionType type; /**< Internal - type of region */108} J9MM_IterateRegionDescriptorPrivate;109110#define HEAPITERATORAPI_REGION_NAME_FREE "Free Region"111#define HEAPITERATORAPI_REGION_NAME_RESERVED "Reserved Region"112#define HEAPITERATORAPI_REGION_NAME_ARRAYLET "Arraylet Region"113#define HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_TENURED "Tenured Region"114#define HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_NURSERY "Nursery Region"115#define HEAPITERATORAPI_REGION_NAME_SEGREGATED_SMALL "Small Region"116#define HEAPITERATORAPI_REGION_NAME_SEGREGATED_LARGE "Large Region"117#define HEAPITERATORAPI_REGION_NAME_SHARED "Shared Region"118#define HEAPITERATORAPI_REGION_NAME "Region"119120/**121* Walk all heaps, call user provided function.122*123* @param flags The flags describing the walk (unused currently)124* @param func The function to call on each heap descriptor.125* @param userData Pointer to storage for userData.126*/127jvmtiIterationControl128j9mm_iterate_heaps(129J9JavaVM *vm,130J9PortLibrary *portLibrary,131UDATA flags,132jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateHeapDescriptor *heapDesc, void *userData),133void *userData)134{135/* There is only one heap currently. Since we can not see the MM_Heap struct in136* OOP we will just use an id of 0x1.137*/138J9MM_IterateHeapDescriptor heapDescriptor;139heapDescriptor.name = "Heap";140heapDescriptor.id = 0x1;141142return func(vm, &heapDescriptor, userData);143}144145/**146* Walk all space for the given heap, call user provided function.147*148* @param heap The descriptor for the heap that should be walked149* @param flags The flags describing the walk (unused currently)150* @param func The function to call on each region descriptor.151* @param userData Pointer to storage for userData.152*/153jvmtiIterationControl154j9mm_iterate_spaces(155J9JavaVM *vm,156J9PortLibrary *portLibrary,157J9MM_IterateHeapDescriptor *heap,158UDATA flags,159jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateSpaceDescriptor *spaceDesc, void *userData),160void *userData)161{162jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;163164if (NULL == heap) {165return JVMTI_ITERATION_CONTINUE;166}167168void *defaultMemorySpace = vm->defaultMemorySpace;169if (NULL != defaultMemorySpace) {170UDATA const referenceSize = J9JAVAVM_REFERENCE_SIZE(vm);171J9MM_IterateSpaceDescriptor spaceDesc;172spaceDesc.name = MM_MemorySpace::getMemorySpace(defaultMemorySpace)->getName();173spaceDesc.id = (UDATA)defaultMemorySpace;174spaceDesc.classPointerOffset = TMP_OFFSETOF_J9OBJECT_CLAZZ;175spaceDesc.classPointerSize = referenceSize;176spaceDesc.fobjectPointerDisplacement = 0;177#if defined(OMR_GC_COMPRESSED_POINTERS)178if (J9JAVAVM_COMPRESS_OBJECT_REFERENCES(vm)) {179spaceDesc.fobjectPointerScale = (UDATA)1 << vm->compressedPointersShift;180} else181#endif /* OMR_GC_COMPRESSED_POINTERS */182{183spaceDesc.fobjectPointerScale = 1;184}185spaceDesc.fobjectSize = referenceSize;186spaceDesc.memorySpace = defaultMemorySpace;187188returnCode = func(vm, &spaceDesc, userData);189}190191return returnCode;192}193194/**195* Walk all roots in a heap, call user provided function.196*197* @param flags The flags describing the walk (unused currently)198* @param func The function to call on each heap descriptor.199* @param userData Pointer to storage for userData.200*/201jvmtiIterationControl202j9mm_iterate_roots(203J9JavaVM *javaVM,204J9PortLibrary *portLibrary,205UDATA flags,206rootIteratorCallBackFunc callBackFunc,207void *userData)208{209210HeapIteratorAPI_RootIterator rootIterator(javaVM, callBackFunc, flags, userData);211212rootIterator.scanAllSlots();213214return JVMTI_ITERATION_ABORT;215}216217/**218* Walk all regions for the given heap, call user provided function.219* A region may be a J9MemorySegment or a HeapIteratorAPI_Page.220*221* @param heap The descriptor for the heap that should be walked222* @param flags The flags describing the walk: read only (region data only) or prepare heap for walk223* @param func The function to call on each region descriptor.224* @param userData Pointer to storage for userData.225*/226jvmtiIterationControl227j9mm_iterate_regions(228J9JavaVM *vm,229J9PortLibrary *portLibrary,230J9MM_IterateSpaceDescriptor *space,231UDATA flags,232jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateRegionDescriptor *regionDesc, void *userData),233void *userData)234{235if (NULL == space) {236return JVMTI_ITERATION_CONTINUE;237}238239if (j9mm_iterator_flag_regions_read_only != (flags & j9mm_iterator_flag_regions_read_only)) {240/* It is not a read-only request - make sure the heap is walkable (flush TLH's, secure heap integrity) */241vm->memoryManagerFunctions->j9gc_flush_caches_for_walk(vm);242}243244return iterateRegions(vm, space, flags, func, userData);245246}247248/**249* Walk all objects for the given region, call user provided function.250*251* @param heap The descriptor for the region that should be walked252* @param flags The flags describing the walk (0 or j9mm_iterator_objects_flag_fix_dead_objects)253* @param func The function to call on each object descriptor.254* @param userData Pointer to storage for userData.255*/256jvmtiIterationControl257j9mm_iterate_region_objects(258J9JavaVM *vm,259J9PortLibrary *portLibrary,260J9MM_IterateRegionDescriptor *region,261UDATA flags,262jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateObjectDescriptor *objectDesc, void *userData),263void *userData)264{265J9MM_IterateRegionDescriptorPrivate *privateRegion = (J9MM_IterateRegionDescriptorPrivate *)region;266jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;267268if (NULL == privateRegion) {269return JVMTI_ITERATION_CONTINUE;270}271272switch (privateRegion->type) {273case j9mm_region_type_region:274returnCode = iterateRegionObjects(vm, region, flags, func, userData);275break;276default:277Assert_MM_unreachable();278break;279}280281return returnCode;282}283284jvmtiIterationControl static285iterateObjectSlotDo(286J9JavaVM *javaVM,287GC_SlotObject *slotObject,288J9MM_IterateObjectDescriptor *object,289J9MM_IteratorObjectRefType type,290UDATA flags,291jvmtiIterationControl (*func)(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *objectDesc, J9MM_IterateObjectRefDescriptor *refDesc, void *userData),292void *userData)293{294jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;295J9Object *actualObject = slotObject->readReferenceFromSlot();296if ( (NULL != actualObject) || (0 == (flags & j9mm_iterator_flag_exclude_null_refs)) ) {297J9MM_IterateObjectRefDescriptor refDescriptor;298refDescriptor.object = actualObject;299refDescriptor.id = (UDATA)actualObject;300refDescriptor.fieldAddress = slotObject->readAddressFromSlot();301refDescriptor.type = type;302returnCode = func(javaVM, object, &refDescriptor, userData);303slotObject->writeReferenceToSlot(refDescriptor.object);304}305return returnCode;306}307308jvmtiIterationControl static309iterateMixedObjectSlots(310J9JavaVM *javaVM,311J9Object *objectPtr,312J9MM_IterateObjectDescriptor *object,313UDATA flags,314jvmtiIterationControl (*func)(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *objectDesc, J9MM_IterateObjectRefDescriptor *refDesc, void *userData),315void *userData)316{317GC_MixedObjectIterator mixedObjectIterator(javaVM->omrVM, objectPtr);318GC_SlotObject *slotObject;319jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;320321while ((slotObject = mixedObjectIterator.nextSlot()) != NULL) {322returnCode = iterateObjectSlotDo(javaVM, slotObject, object, j9mm_iterator_object_ref_type_object, flags, func, userData);323if (JVMTI_ITERATION_ABORT == returnCode) {324break;325}326}327return returnCode;328}329330jvmtiIterationControl static331iterateArrayObjectSlots(332J9JavaVM *javaVM,333J9Object *objectPtr,334J9MM_IterateObjectDescriptor *object,335UDATA flags,336jvmtiIterationControl (*func)(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *objectDesc, J9MM_IterateObjectRefDescriptor *refDesc, void *userData),337void *userData)338{339GC_PointerArrayIterator pointerArrayIterator(javaVM, objectPtr);340GC_SlotObject *slotObject;341jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;342343while ((slotObject = pointerArrayIterator.nextSlot()) != NULL) {344returnCode = iterateObjectSlotDo(javaVM, slotObject, object, j9mm_iterator_object_ref_type_object, flags, func, userData);345if (JVMTI_ITERATION_ABORT == returnCode) {346break;347}348}349return returnCode;350}351352jvmtiIterationControl static353iterateArrayletSlots(354J9JavaVM *javaVM,355J9Object *objectPtr,356J9MM_IterateObjectDescriptor *object,357UDATA flags,358jvmtiIterationControl (*func)(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *objectDesc, J9MM_IterateObjectRefDescriptor *refDesc, void *userData),359void *userData)360{361jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;362if (j9mm_iterator_flag_include_arraylet_leaves == (flags & j9mm_iterator_flag_include_arraylet_leaves) ) {363if (MM_GCExtensions::getExtensions(javaVM->omrVM)->indexableObjectModel.hasArrayletLeafPointers((J9IndexableObject *)objectPtr)) {364GC_ArrayletLeafIterator arrayletLeafIterator(javaVM, (J9IndexableObject*)objectPtr);365GC_SlotObject *slotObject = NULL;366367while (NULL != (slotObject = arrayletLeafIterator.nextLeafPointer())) {368returnCode = iterateObjectSlotDo(javaVM, slotObject, object, j9mm_iterator_object_ref_type_arraylet_leaf, flags, func, userData);369if (JVMTI_ITERATION_ABORT == returnCode) {370break;371}372}373}374}375return returnCode;376}377378/**379* Walk all object slots for the given object, call user provided function.380*381* @param object The descriptor for the object that should be walked382* @param flags The flags describing the walk (unused currently)383* @param func The function to call on each object descriptor.384* @param userData Pointer to storage for userData.385*/386jvmtiIterationControl387j9mm_iterate_object_slots(388J9JavaVM *javaVM,389J9PortLibrary *portLibrary,390J9MM_IterateObjectDescriptor *object,391UDATA flags,392jvmtiIterationControl (*func)(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *objectDesc, J9MM_IterateObjectRefDescriptor *refDesc, void *userData),393void *userData)394{395jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;396J9Object *objectPtr = (J9Object *)(object->id);397MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(javaVM->omrVM);398399switch(extensions->objectModel.getScanType(objectPtr)) {400case GC_ObjectModel::SCAN_MIXED_OBJECT_LINKED:401case GC_ObjectModel::SCAN_ATOMIC_MARKABLE_REFERENCE_OBJECT:402case GC_ObjectModel::SCAN_MIXED_OBJECT:403case GC_ObjectModel::SCAN_OWNABLESYNCHRONIZER_OBJECT:404case GC_ObjectModel::SCAN_CLASS_OBJECT:405case GC_ObjectModel::SCAN_CLASSLOADER_OBJECT:406case GC_ObjectModel::SCAN_REFERENCE_MIXED_OBJECT:407returnCode = iterateMixedObjectSlots(javaVM, objectPtr, object, flags, func, userData);408break;409410case GC_ObjectModel::SCAN_POINTER_ARRAY_OBJECT:411returnCode = iterateArrayObjectSlots(javaVM, objectPtr, object, flags, func, userData);412if (JVMTI_ITERATION_CONTINUE == returnCode) {413returnCode = iterateArrayletSlots(javaVM, objectPtr, object, flags, func, userData);414}415break;416417case GC_ObjectModel::SCAN_PRIMITIVE_ARRAY_OBJECT:418returnCode = iterateArrayletSlots(javaVM, objectPtr, object, flags, func, userData);419break;420421default:422Assert_MM_unreachable();423}424425return returnCode;426}427428/**429* Initialize a descriptor for the specified object.430* This descriptor may subsequently be used with j9mm_iterate_object_slots or other iterator APIs.431*432* @return descriptor The descriptor to be initialized433* @param object The object to store into the descriptor434*/435void436j9mm_initialize_object_descriptor(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *descriptor, j9object_t object)437{438MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(javaVM->omrVM);439440descriptor->id = (UDATA)object;441descriptor->object = object;442descriptor->size = extensions->objectModel.getConsumedSizeInBytesWithHeader(object);443descriptor->isObject = TRUE;444}445446/**447* Walk all objects reachable under the given VM, call user provided function.448* @param flags The flags describing the walk (unused currently)449* @param func The function to call on each object descriptor.450* @param userData Pointer to storage for userData.451*/452jvmtiIterationControl453j9mm_iterate_all_objects(J9JavaVM *vm, J9PortLibrary *portLibrary, UDATA flags, jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateObjectDescriptor *object, void *userData), void *userData)454{455J9MM_CallbackDataHolderPrivate data;456data.func = func;457data.userData = userData;458data.portLibrary = portLibrary;459data.flags = flags;460return j9mm_iterate_heaps(vm, portLibrary, flags, &internalIterateHeaps, &data);461}462463/* used by j9mm_iterate_all_objects */464static jvmtiIterationControl465internalIterateHeaps(J9JavaVM *vm, J9MM_IterateHeapDescriptor *heap, void *userData)466{467J9MM_CallbackDataHolderPrivate *data = (J9MM_CallbackDataHolderPrivate *)userData;468return j9mm_iterate_spaces(vm, data->portLibrary, heap, data->flags, &internalIterateSpaces, userData);469}470471static jvmtiIterationControl472internalIterateSpaces(J9JavaVM *vm, J9MM_IterateSpaceDescriptor *space, void *userData)473{474J9MM_CallbackDataHolderPrivate *data = (J9MM_CallbackDataHolderPrivate *)userData;475return j9mm_iterate_regions(vm, data->portLibrary, space, data->flags, internalIterateRegions, userData);476}477478static jvmtiIterationControl479internalIterateRegions(J9JavaVM *vm, J9MM_IterateRegionDescriptor *region, void *userData)480{481J9MM_CallbackDataHolderPrivate *data = (J9MM_CallbackDataHolderPrivate *)userData;482return j9mm_iterate_region_objects(vm, data->portLibrary, region, data->flags, data->func, data->userData);483}484485/**486* Walk all ownable synchronizer object, call user provided function.487* @param flags The flags describing the walk (unused currently)488* @param func The function to call on each object descriptor.489* @param userData Pointer to storage for userData.490* @return return 0 on successfully iterating entire list, return user provided function call if it did not return JVMTI_ITERATION_CONTINUE491*/492jvmtiIterationControl493j9mm_iterate_all_ownable_synchronizer_objects(J9VMThread *vmThread, J9PortLibrary *portLibrary, UDATA flags, jvmtiIterationControl (*func)(J9VMThread *vmThread, J9MM_IterateObjectDescriptor *object, void *userData), void *userData)494{495J9JavaVM *javaVM = vmThread->javaVM;496MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM->omrVM);497MM_ObjectAccessBarrier *barrier = extensions->accessBarrier;498MM_OwnableSynchronizerObjectList *ownableSynchronizerObjectList = extensions->getOwnableSynchronizerObjectListsExternal(vmThread);499500Assert_MM_true(NULL != ownableSynchronizerObjectList);501502J9MM_IterateObjectDescriptor objectDescriptor;503J9MM_IterateRegionDescriptor regionDesc;504jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;505506while (NULL != ownableSynchronizerObjectList) {507J9Object *objectPtr = ownableSynchronizerObjectList->getHeadOfList();508while (NULL != objectPtr) {509UDATA regionFound = j9mm_find_region_for_pointer(javaVM, objectPtr, ®ionDesc);510if (0 != regionFound) {511initializeObjectDescriptor(javaVM, &objectDescriptor, ®ionDesc, objectPtr);512returnCode = func(vmThread, &objectDescriptor, userData);513if (JVMTI_ITERATION_ABORT == returnCode) {514return returnCode;515}516} else {517Assert_MM_unreachable();518}519objectPtr = barrier->getOwnableSynchronizerLink(objectPtr);520}521ownableSynchronizerObjectList = ownableSynchronizerObjectList->getNextList();522}523return returnCode;524}525526} /* extern "C" */527528/**529* Initialize the specified descriptor with the specified values.530* Invariant fields are initialized to the appropriate values for the JVM.531*532* @param[in] extensions - a pointer to the GC extensions533* @param[out] descriptor - the descriptor to initialize534* @param[in] region - The region to use for descriptor initialization535*/536static void537initializeRegionDescriptor(MM_GCExtensionsBase* extensions, J9MM_IterateRegionDescriptor *descriptor, MM_HeapRegionDescriptor *region)538{539UDATA objectAlignment = extensions->getObjectAlignmentInBytes();540UDATA objectMinimumSize = 0;541const char *regionName = NULL;542#if defined(J9VM_GC_MINIMUM_OBJECT_SIZE)543objectMinimumSize = J9_GC_MINIMUM_OBJECT_SIZE;544#else /* J9VM_GC_MINIMUM_OBJECT_SIZE */545objectMinimumSize = J9GC_OBJECT_HEADER_SIZE(extensions)546#endif /* J9VM_GC_MINIMUM_OBJECT_SIZE */547548switch(region->getRegionType()) {549case MM_HeapRegionDescriptor::RESERVED:550regionName = HEAPITERATORAPI_REGION_NAME_RESERVED;551objectAlignment = 0;552objectMinimumSize = 0;553break;554case MM_HeapRegionDescriptor::FREE:555case MM_HeapRegionDescriptor::ADDRESS_ORDERED_IDLE:556case MM_HeapRegionDescriptor::BUMP_ALLOCATED_IDLE:557/* (for all intents and purposes, an IDLE region is the same as a FREE region) */558regionName = HEAPITERATORAPI_REGION_NAME_FREE;559objectAlignment = 0;560objectMinimumSize = 0;561break;562case MM_HeapRegionDescriptor::ARRAYLET_LEAF:563regionName = HEAPITERATORAPI_REGION_NAME_ARRAYLET;564objectAlignment = 0;565objectMinimumSize = 0;566break;567#if defined(J9VM_GC_SEGREGATED_HEAP)568case MM_HeapRegionDescriptor::SEGREGATED_SMALL:569regionName = HEAPITERATORAPI_REGION_NAME_SEGREGATED_SMALL;570objectMinimumSize = ((MM_HeapRegionDescriptorSegregated *)region)->getCellSize();571break;572case MM_HeapRegionDescriptor::SEGREGATED_LARGE:573regionName = HEAPITERATORAPI_REGION_NAME_SEGREGATED_LARGE;574objectMinimumSize = region->getSize();575break;576#endif /* J9VM_GC_SEGREGATED_HEAP */577case MM_HeapRegionDescriptor::ADDRESS_ORDERED:578case MM_HeapRegionDescriptor::BUMP_ALLOCATED:579if (extensions->isVLHGC()) {580#if defined(J9VM_GC_VLHGC)581regionName = HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_NURSERY;582#endif /* J9VM_GC_VLHGC */583} else {584if (MEMORY_TYPE_NEW == (region->getTypeFlags() & MEMORY_TYPE_NEW)) {585regionName = HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_NURSERY;586} else if (MEMORY_TYPE_OLD == (region->getTypeFlags() & MEMORY_TYPE_OLD)) {587regionName = HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_TENURED;588} else {589regionName = HEAPITERATORAPI_REGION_NAME;590}591}592break;593#if defined(J9VM_GC_VLHGC)594case MM_HeapRegionDescriptor::ADDRESS_ORDERED_MARKED:595case MM_HeapRegionDescriptor::BUMP_ALLOCATED_MARKED:596regionName = HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_TENURED;597break;598#endif /* J9VM_GC_VLHGC */599default:600Assert_MM_unreachable();601}602603initializeRegionDescriptor(descriptor, regionName, (UDATA)region, objectAlignment, objectMinimumSize, region->getLowAddress(), region->getSize());604}605606/**607* Initialize the specified descriptor with the specified values.608* Invariant fields are initialized to the appropriate values for the JVM.609*610* @param[out] descriptor - the descriptor to initialize611* @param[in] name - name of the region612* @param[in] id - id of the region613* @param[in] start - start address of the region614* @param[in] size - size (in bytes) of the region615*/616static void617initializeRegionDescriptor(J9MM_IterateRegionDescriptor *descriptor, const char* name, UDATA id, UDATA objectAlignment, UDATA objectMinimumSize, void* start, UDATA size)618{619descriptor->name = name;620descriptor->id = id;621descriptor->objectAlignment = objectAlignment;622descriptor->objectMinimumSize = objectMinimumSize;623descriptor->regionStart = start;624descriptor->regionSize = size;625}626627/**628* Initialize a descriptor for the specified object.629* This descriptor may subsequently be used with j9mm_iterate_object_slots or other iterator APIs.630*631* @return descriptor The descriptor to be initialized632* @param regionDesc the region to use to round object to minimum object size633* @param object The object to store into the descriptor634*/635static void636initializeObjectDescriptor(637J9JavaVM *javaVM,638J9MM_IterateObjectDescriptor *descriptor,639J9MM_IterateRegionDescriptor *regionDesc,640j9object_t object)641{642j9mm_initialize_object_descriptor(javaVM, descriptor, object);643644#if defined(J9VM_GC_SEGREGATED_HEAP)645MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(javaVM->omrVM);646647if (extensions->isSegregatedHeap()) {648/* TODO remove this once the objectModel properly handles Segregated Heaps */649if (descriptor->size < regionDesc->objectMinimumSize) {650descriptor->size = regionDesc->objectMinimumSize;651}652}653#endif /* J9VM_GC_SEGREGATED_HEAP */654}655656static jvmtiIterationControl657iterateRegions(658J9JavaVM *vm,659J9MM_IterateSpaceDescriptor *space,660UDATA flags,661jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateRegionDescriptor *regionDesc, void *userData),662void *userData)663{664jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;665666MM_MemorySpace *memorySpace = MM_MemorySpace::getMemorySpace((void *)space->id);667MM_HeapRegionManager *manager = memorySpace->getHeap()->getHeapRegionManager();668manager->lock();669670GC_HeapRegionIterator regionIterator(manager, memorySpace);671MM_HeapRegionDescriptor *region = NULL;672MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(vm->omrVM);673while(NULL != (region = regionIterator.nextRegion())) {674J9MM_IterateRegionDescriptorPrivate regionDescription;675regionDescription.type = j9mm_region_type_region;676initializeRegionDescriptor(extensions, ®ionDescription.descriptor, region);677returnCode = func(vm, &(regionDescription.descriptor), userData);678if (JVMTI_ITERATION_ABORT == returnCode) {679break;680}681}682manager->unlock();683684return returnCode;685}686687static jvmtiIterationControl688iterateRegionObjects(689J9JavaVM *vm,690J9MM_IterateRegionDescriptor *region,691UDATA flags,692jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateObjectDescriptor *objectDesc, void *userData),693void *userData)694{695PORT_ACCESS_FROM_JAVAVM(vm);696jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;697/* Iterate over live and dead objects */698MM_HeapRegionDescriptor* heapRegion = (MM_HeapRegionDescriptor*)region->id;699MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(vm->omrVM);700HeapIteratorAPI_BufferedIterator objectHeapIterator(vm, PORTLIB, heapRegion, true);701J9Object* object = NULL;702while(NULL != (object = objectHeapIterator.nextObject())) {703J9MM_IterateObjectDescriptor objectDescriptor;704if ((extensions->objectModel.isDeadObject(object)) || (0 != (J9CLASS_FLAGS(J9GC_J9OBJECT_CLAZZ_VM(object, vm)) & J9AccClassDying))) {705if (0 != (flags & j9mm_iterator_flag_include_holes)) {706if (extensions->objectModel.isDeadObject(object)) {707objectDescriptor.id = (UDATA)object;708objectDescriptor.object = object;709objectDescriptor.size = extensions->objectModel.getSizeInBytesDeadObject(object);710} else {711/* this object is not marked as a hole, but its class has been partially unloaded so it's treated like a hole here */712j9mm_initialize_object_descriptor(vm, &objectDescriptor, object);713}714objectDescriptor.isObject = FALSE;715returnCode = func(vm, &objectDescriptor, userData);716if (JVMTI_ITERATION_ABORT == returnCode) {717break;718}719}720} else {721initializeObjectDescriptor(vm, &objectDescriptor, region, object);722returnCode = func(vm, &objectDescriptor, userData);723if (JVMTI_ITERATION_ABORT == returnCode) {724break;725}726}727}728729return returnCode;730}731732/**733* Find the Region that the pointer belongs too.734* Returns true if region found.735*/736UDATA737j9mm_find_region_for_pointer(J9JavaVM* javaVM, void *pointer, J9MM_IterateRegionDescriptor *regionDesc)738{739MM_GCExtensions* extensions = MM_GCExtensions::getExtensions(javaVM->omrVM);740bool found = false;741MM_HeapRegionManager *regionManager = extensions->heap->getHeapRegionManager();742/* See if the pointer is being managed by the RegionManager */743MM_HeapRegionDescriptor *region = regionManager->regionDescriptorForAddress(pointer);744745if (NULL != region) {746initializeRegionDescriptor(extensions, regionDesc, region);747found = true;748}749750return (UDATA) found; /* TODO: fix this, we really return bool */751}752753/**754* Convert the memory that is currently represented as an object to dark matter.755* This routine is typically used by GC tools such as gccheck and tgc to ensure that only valid (i.e. reachable)756* objects remain on the heap after a sweep. An 'dead' object may contain dangling references to heap addresses757* which no longer contain walkable objects. The problem is solved by converting the invalid objects to dark matter.758*759* @param[in] javaVM the JavaVM760* @param[in] region the region in which the object exists761* @param[in] objectDesc the object to be abandoned762* @return 0 on success, non-0 on failure.763*/764UDATA765j9mm_abandon_object(766J9JavaVM *javaVM,767J9MM_IterateRegionDescriptor *region,768J9MM_IterateObjectDescriptor *objectDesc)769{770UDATA rc = 0;771J9MM_IterateRegionDescriptorPrivate *privateRegion = (J9MM_IterateRegionDescriptorPrivate *)region;772773if (j9mm_region_type_region == privateRegion->type) {774MM_HeapRegionDescriptor* heapRegion = (MM_HeapRegionDescriptor*)region->id;775MM_MemorySubSpace* memorySubSpace = heapRegion->getSubSpace();776777UDATA deadObjectByteSize = MM_GCExtensions::getExtensions(javaVM)->objectModel.getConsumedSizeInBytesWithHeader(objectDesc->object);778memorySubSpace->abandonHeapChunk(objectDesc->object, ((U_8*)objectDesc->object) + deadObjectByteSize);779780} else {781rc = 1;782}783784return rc;785}786787788