Path: blob/master/runtime/gc_structs/PointerArrayletIterator.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/**23* @file24* @ingroup GC_Structs25*/2627#if !defined(POINTERARRAYLETITERATOR_HPP_)28#define POINTERARRAYLETITERATOR_HPP_2930#include "j9.h"31#include "j9cfg.h"32#include "ModronAssertions.h"3334#include "ArrayObjectModel.hpp"35#include "Bits.hpp"36#include "GCExtensionsBase.hpp"37#include "ObjectIteratorState.hpp"38#include "SlotObject.hpp"39#include "ArrayletObjectModel.hpp"4041/**42* Iterate over all slots in a pointer array which contain an object reference43* @ingroup GC_Structs44*/45class GC_PointerArrayletIterator46{47private:48J9IndexableObject *_arrayPtr; /**< pointer to the array object being iterated */49GC_SlotObject _slotObject; /**< Create own SlotObject class to provide output */5051UDATA const _arrayletLeafSize; /* The size of an arraylet leaf */52UDATA const _fobjectsPerLeaf; /* The number of fj9object_t's per leaf */53UDATA _index; /* The current index of the array */54fj9object_t * _currentArrayletBaseAddress; /* The base address of the current arraylet */55UDATA _currentArrayletIndex; /* The index of the current arraylet */56UDATA _currentArrayletOffset; /* The offset to the _index'ed item from the currentArrayletBaseAddress */5758MMINLINE void recalculateArrayletOffsets()59{60if ( _index > 0 ) {61MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(_javaVM->omrVM);62_currentArrayletIndex = ((U_32)_index-1) / _fobjectsPerLeaf; /* The index of the arraylet containing _index */63_currentArrayletOffset = ((U_32)_index-1) % _fobjectsPerLeaf; /* The offset of _index in the current arraylet */6465fj9object_t *arrayoidPointer = extensions->indexableObjectModel.getArrayoidPointer(_arrayPtr);66GC_SlotObject arrayletBaseSlotObject(_javaVM->omrVM, GC_SlotObject::addToSlotAddress(arrayoidPointer, _currentArrayletIndex, compressObjectReferences()));67_currentArrayletBaseAddress = (fj9object_t *)arrayletBaseSlotObject.readReferenceFromSlot();6869/* note that we need to check the arraylet base address before reading it since we might be walking70* a partially allocated arraylet which still has some NULL leaf pointers. We return NULL, in those71* cases, which will cause the caller to stop iterating. This is correct behaviour if we can assume72* that arraylet leaves are always allocated in-order. This is currently true.73* Moreover, we can safely assume that an incomplete arraylet contains no non-null object references74* since it hasn't yet been returned from its allocation routine so it isn't yet visible to the mutator.75*/76if (NULL == _currentArrayletBaseAddress) {77_index = 0;78}79}80}8182protected:83#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)84bool const _compressObjectReferences;85#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */86J9JavaVM *const _javaVM; /**< A cached pointer to the shared JavaVM instance */8788public:89/**90* Return back true if object references are compressed91* @return true, if object references are compressed92*/93MMINLINE bool compressObjectReferences() {94return OMR_COMPRESS_OBJECT_REFERENCES(_compressObjectReferences);95}9697MMINLINE void initialize(J9Object *objectPtr) {98MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(_javaVM->omrVM);99100/* if we are using hybrid arraylets, we need to ensure that we don't initialize the discontiguous iterator since it will try to read off the end of the header101* when reading the non-existent arrayoid. In the case of small arrays near the end of a region, this could cause us to read an uncommitted page.102*/103if (extensions->indexableObjectModel.isInlineContiguousArraylet((J9IndexableObject *)objectPtr)) {104_arrayPtr = NULL;105_index = 0;106} else {107_arrayPtr = (J9IndexableObject *)objectPtr;108109/* Set current and end scan pointers */110_index = extensions->indexableObjectModel.getSizeInElements(_arrayPtr);111recalculateArrayletOffsets();112}113}114115MMINLINE GC_SlotObject *nextSlot()116{117if (_index > 0) {118_slotObject.writeAddressToSlot(GC_SlotObject::addToSlotAddress(_currentArrayletBaseAddress, _currentArrayletOffset, compressObjectReferences()));119120_index -= 1;121/* If we reach the end of the arraylet leaf, we need to recalculate our arrayletBaseAddress for the next _index */122if ( 0 == _currentArrayletOffset) {123recalculateArrayletOffsets();124} else {125_currentArrayletOffset -= 1;126}127128return &_slotObject;129}130131/* No more object slots to scan */132return NULL;133}134135GC_PointerArrayletIterator(J9JavaVM *javaVM)136: _arrayPtr(NULL)137, _slotObject(GC_SlotObject(javaVM->omrVM, NULL))138, _arrayletLeafSize(javaVM->arrayletLeafSize)139, _fobjectsPerLeaf(_arrayletLeafSize / J9JAVAVM_REFERENCE_SIZE(javaVM))140, _index(0)141, _currentArrayletBaseAddress(NULL)142, _currentArrayletIndex(0)143, _currentArrayletOffset(0)144#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)145, _compressObjectReferences(J9JAVAVM_COMPRESS_OBJECT_REFERENCES(javaVM))146#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */147, _javaVM(javaVM)148{149}150151/**152* @param objectPtr the array object to be processed153*/154GC_PointerArrayletIterator(J9JavaVM *javaVM, J9Object *objectPtr)155: _arrayPtr(NULL)156, _slotObject(GC_SlotObject(javaVM->omrVM, NULL))157, _arrayletLeafSize(javaVM->arrayletLeafSize)158, _fobjectsPerLeaf(_arrayletLeafSize / J9JAVAVM_REFERENCE_SIZE(javaVM))159, _index(0)160, _currentArrayletBaseAddress(NULL)161, _currentArrayletIndex(0)162, _currentArrayletOffset(0)163#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)164, _compressObjectReferences(J9JAVAVM_COMPRESS_OBJECT_REFERENCES(javaVM))165#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */166, _javaVM(javaVM)167{168initialize(objectPtr);169}170171MMINLINE J9Object *getObject()172{173return (J9Object *)_arrayPtr;174}175176/**177* Gets the current slot's array index.178* @return slot number (or zero based array index) of the last call to nextSlot.179* @return undefined if nextSlot has yet to be called.180*/181MMINLINE UDATA getIndex() {182return _index;183}184185186MMINLINE void setIndex(UDATA index) {187_index = index;188recalculateArrayletOffsets();189}190191/**192* Restores the iterator state into this class193* @param[in] objectIteratorState partially scanned object iterator state194*/195MMINLINE void restore(GC_ObjectIteratorState *objectIteratorState) {196_arrayPtr = (J9IndexableObject *)objectIteratorState->_objectPtr;197setIndex(objectIteratorState->_index);198}199200201/**202* Saves the partially scanned state of this class203* @param[in] objectIteratorState where to store the state204*/205MMINLINE void save(GC_ObjectIteratorState *objectIteratorState) {206objectIteratorState->_objectPtr = (J9Object *)_arrayPtr;207objectIteratorState->_index = _index;208}209};210211#endif /* POINTERARRAYLETITERATOR_HPP_ */212213214