Path: blob/master/runtime/gc_glue_java/FlattenedArrayObjectScanner.hpp
5990 views
/*******************************************************************************1* Copyright (c) 2020, 2020 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(FLATTENEDARRAYOBJECTSCANNER_HPP_)23#define FLATTENEDARRAYOBJECTSCANNER_HPP_2425#include "j9.h"26#include "j9cfg.h"27#include "modron.h"2829#include "objectdescription.h"30#include "ArrayObjectModel.hpp"31#include "GCExtensionsBase.hpp"32#include "HeadlessMixedObjectScanner.hpp"33#include "IndexableObjectScanner.hpp"3435class GC_FlattenedArrayObjectScanner : public GC_HeadlessMixedObjectScanner36{37/* Data Members */38private:3940MM_EnvironmentBase *_env;41uintptr_t _elementSizeWithoutPadding; /**< Size of the flattened element, without padding */42uintptr_t *_descriptionBasePtr; /**< Pointer to the description base */43#if defined(OMR_GC_LEAF_BITS)44uintptr_t *_leafBasePtr; /**< Pointer to the leaf description base */45#endif /* defined(OMR_GC_LEAF_BITS) */46GC_IndexableObjectScanner _indexableScanner; /**< Used to iterate the array by element */4748protected:4950public:5152/* Methods */53private:5455protected:5657/**58* @param env The scanning thread environment59* @param arrayPtr pointer to the array to be processed60* @param basePtr pointer to the first contiguous array cell61* @param limitPtr pointer to end of last contiguous array cell62* @param scanPtr pointer to the array cell where scanning will start63* @param endPtr pointer to the array cell where scanning will stop64* @param scanMap The first scan map65* @param elementSize The size of each element, without padding66* @param elementStride The stride of each element, including element padding67* @param flags Scanning context flags68*/69MMINLINE GC_FlattenedArrayObjectScanner(70MM_EnvironmentBase *env71, omrobjectptr_t arrayPtr72, fomrobject_t *basePtr73, fomrobject_t *limitPtr74, fomrobject_t *scanPtr75, fomrobject_t *endPtr76, uintptr_t elementSize77, uintptr_t elementStride78, uintptr_t *descriptionBasePtr79#if defined(OMR_GC_LEAF_BITS)80, uintptr_t *leafBasePtr81#endif /* defined(OMR_GC_LEAF_BITS) */82, uintptr_t flags)83: GC_HeadlessMixedObjectScanner(env, scanPtr, elementSize, flags | GC_ObjectScanner::indexableObject)84, _env(env)85, _elementSizeWithoutPadding(elementSize)86, _descriptionBasePtr(descriptionBasePtr)87#if defined(OMR_GC_LEAF_BITS)88, _leafBasePtr(leafBasePtr)89#endif /* defined(OMR_GC_LEAF_BITS) */90/* Pass 0 for scanMap, as the indexable iterator does not use the scanMap */91, _indexableScanner(env, arrayPtr, basePtr, limitPtr, scanPtr, endPtr, 0, elementStride, flags)92{93_typeId = __FUNCTION__;94}9596MMINLINE void97initialize(MM_EnvironmentBase *env)98{99#if defined(OMR_GC_LEAF_BITS)100GC_HeadlessMixedObjectScanner::initialize(env, _descriptionBasePtr, _leafBasePtr);101#else /* defined(OMR_GC_LEAF_BITS) */102GC_HeadlessMixedObjectScanner::initialize(env, _descriptionBasePtr);103#endif /* defined(OMR_GC_LEAF_BITS) */104105_indexableScanner.initialize(env);106107/* The HeadlessMixedObjectScanner will setNoMoreSlots() causing us108* to miss other elements of the array109*/110setMoreSlots();111}112113public:114115/**116* @param[in] env The scanning thread environment117* @param[in] objectPtr pointer to the array to be processed118* @param[in] allocSpace pointer to space within which the scanner should be instantiated (in-place)119* @param[in] flags Scanning context flags120* @param[in] splitAmount If >0, the number of elements to include for this scanner instance; if 0, include all elements121* @param[in] startIndex The index of the first element to scan122*/123MMINLINE static GC_FlattenedArrayObjectScanner *124newInstance(MM_EnvironmentBase *env, omrobjectptr_t objectPtr, void *allocSpace, uintptr_t flags, uintptr_t splitAmount, uintptr_t startIndex = 0)125{126GC_FlattenedArrayObjectScanner *objectScanner = (GC_FlattenedArrayObjectScanner *)allocSpace;127GC_ArrayObjectModel *arrayObjectModel = &(env->getExtensions()->indexableObjectModel);128J9Class *clazzPtr = J9GC_J9OBJECT_CLAZZ(objectPtr, env);129J9ArrayClass *j9ArrayClass = (J9ArrayClass *) clazzPtr;130131/* TODO are these always the same? */132Assert_MM_true(j9ArrayClass->componentType == j9ArrayClass->leafComponentType);133134J9Class *elementClass = j9ArrayClass->componentType;135omrarrayptr_t arrayPtr = (omrarrayptr_t)objectPtr;136137uintptr_t sizeInElements = arrayObjectModel->getSizeInElements(arrayPtr);138uintptr_t elementSize = J9_VALUETYPE_FLATTENED_SIZE(elementClass);139uintptr_t elementStride = J9ARRAYCLASS_GET_STRIDE(clazzPtr);140fomrobject_t *basePtr = (fomrobject_t *)arrayObjectModel->getDataPointerForContiguous(arrayPtr);141fomrobject_t *limitPtr = (fomrobject_t *)((uintptr_t)basePtr + (sizeInElements * elementStride));142fomrobject_t *scanPtr = (fomrobject_t *)((uintptr_t)basePtr + (startIndex * elementStride));143fomrobject_t *endPtr = limitPtr;144if (!GC_ObjectScanner::isIndexableObjectNoSplit(flags) && (splitAmount != 0)) {145Assert_MM_unreachable();146endPtr = (fomrobject_t *)((uintptr_t)scanPtr + (splitAmount * elementStride));147if (endPtr > limitPtr) {148endPtr = limitPtr;149}150}151uintptr_t *instanceDescription = elementClass->instanceDescription;152#if defined(OMR_GC_LEAF_BITS)153uintptr_t *leafDescription = elementClass->instanceLeafDescription;154new(objectScanner) GC_FlattenedArrayObjectScanner(env, objectPtr, basePtr, limitPtr, scanPtr, endPtr, elementSize, elementStride, instanceDescription, leafDescription, flags);155#else /* defined(OMR_GC_LEAF_BITS) */156new(objectScanner) GC_FlattenedArrayObjectScanner(env, objectPtr, basePtr, limitPtr, scanPtr, endPtr, elementSize, elementStride, instanceDescription, flags);157#endif /* defined(OMR_GC_LEAF_BITS) */158159objectScanner->initialize(env);160if (0 != startIndex) {161objectScanner->clearHeadObjectScanner();162}163return objectScanner;164}165166MMINLINE uintptr_t getBytesRemaining() { return sizeof(fomrobject_t) * (_endPtr - _scanPtr); }167168/**169* @param env The scanning thread environment170* @param allocSpace pointer to space within which the scanner should be instantiated (in-place)171* @param splitAmount The maximum number of array elements to include172* @return Pointer to split scanner in allocSpace173*/174GC_IndexableObjectScanner *175splitTo(MM_EnvironmentBase *env, void *allocSpace, uintptr_t splitAmount)176{177Assert_MM_unimplemented();178return NULL;179}180181/**182* Return base pointer and slot bit map for next block of contiguous slots to be scanned. The183* base pointer must be fomrobject_t-aligned. Bits in the bit map are scanned in order of184* increasing significance, and the least significant bit maps to the slot at the returned185* base pointer.186*187* @param[out] scanMap the bit map for the slots contiguous with the returned base pointer188* @param[out] hasNextSlotMap set this to true if this method should be called again, false if this map is known to be last189* @return a pointer to the first slot mapped by the least significant bit of the map, or NULL if no more slots190*/191virtual fomrobject_t *192getNextSlotMap(uintptr_t *slotMap, bool *hasNextSlotMap)193{194fomrobject_t *result = GC_HeadlessMixedObjectScanner::getNextSlotMap(slotMap, hasNextSlotMap);195/* Ignore hasNextSlotMap from HeadLess, we want to always report that there is another element */196*hasNextSlotMap = true;197if (result == NULL) {198/* No more slots in the current element, get the next element of the array */199result = _indexableScanner.nextIndexableElement();200if (result == NULL) {201/* There are no elements in the array */202*hasNextSlotMap = false;203} else {204_mapPtr = result;205_endPtr = (fomrobject_t *)((uintptr_t)_mapPtr + _elementSizeWithoutPadding);206GC_HeadlessMixedObjectScanner::initialize(_env, _descriptionBasePtr, _leafBasePtr);207/* GC_HeadlessMixedObjectScanner::initialize() may setNoMoreSlots(), so set it back to true.208* We must also return (hasNextSlotMap = true) on top of this209*/210setMoreSlots();211}212}213return result;214}215216#if defined(OMR_GC_LEAF_BITS)217/**218* Return base pointer and slot bit map for next block of contiguous slots to be scanned. The219* base pointer must be fomrobject_t-aligned. Bits in the bit map are scanned in order of220* increasing significance, and the least significant bit maps to the slot at the returned221* base pointer.222*223* @param[out] scanMap the bit map for the slots contiguous with the returned base pointer224* @param[out] leafMap the leaf bit map for the slots contiguous with the returned base pointer225* @param[out] hasNextSlotMap set this to true if this method should be called again, false if this map is known to be last226* @return a pointer to the first slot mapped by the least significant bit of the map, or NULL if no more slots227*/228virtual fomrobject_t *229getNextSlotMap(uintptr_t *slotMap, uintptr_t *leafMap, bool *hasNextSlotMap)230{231fomrobject_t *result = GC_HeadlessMixedObjectScanner::getNextSlotMap(slotMap, leafMap, hasNextSlotMap);232/* Ignore hasNextSlotMap from HeadLess, we want to always report that there is another element */233*hasNextSlotMap = true;234if (result == NULL) {235/* No more slots in the current element, get the next element of the array */236result = _indexableScanner.nextIndexableElement();237if (result == NULL) {238/* There are no elements in the array */239*hasNextSlotMap = false;240} else {241_mapPtr = result;242_endPtr = (fomrobject_t *)((uintptr_t)_mapPtr + _elementSizeWithoutPadding);243GC_HeadlessMixedObjectScanner::initialize(_env, _descriptionBasePtr, _leafBasePtr);244/* GC_HeadlessMixedObjectScanner::initialize() may setNoMoreSlots(), so set it back to true.245* We must also return (hasNextSlotMap = true) on top of this246*/247setMoreSlots();248}249}250return result;251}252#endif /* defined(OMR_GC_LEAF_BITS) */253};254255#endif /* FLATTENEDARRAYOBJECTSCANNER_HPP_ */256257258