Path: blob/master/runtime/gc_glue_java/ObjectModelDelegate.hpp
5985 views
/*******************************************************************************1* Copyright (c) 2017, 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#ifndef OBJECTMODELDELEGATE_HPP_23#define OBJECTMODELDELEGATE_HPP_2425#include "j9nonbuilder.h"26#include "omr.h"27#include "objectdescription.h"28#include "util_api.h"2930#include "ArrayObjectModel.hpp"31#include "ForwardedHeader.hpp"32#include "MixedObjectModel.hpp"3334class MM_AllocateInitialization;35class MM_EnvironmentBase;3637#define CLI_THREAD_TYPE J9VMThread3839struct CLI_THREAD_TYPE;4041/**42* GC_ObjectModelBase is inaccessible from this class. Some factors are redefined here.43*/44class GC_ObjectModelDelegate45{46/*47* Member data and types48*/49private:50static const uintptr_t _objectHeaderSlotOffset = 0;51static const uintptr_t _objectHeaderSlotFlagsShift = 0;5253const uintptr_t _delegateHeaderSlotFlagsMask;5455GC_ArrayObjectModel *_arrayObjectModel;56GC_MixedObjectModel *_mixedObjectModel;5758protected:59#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)60bool _compressObjectReferences;61#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */62public:6364/*65* Member functions66*/67private:68protected:69public:70/**71* Return back true if object references are compressed72* @return true, if object references are compressed73*/74MMINLINE bool75compressObjectReferences()76{77return OMR_COMPRESS_OBJECT_REFERENCES(_compressObjectReferences);78}7980#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)81/**82* Set the compress object references flag.83*/84MMINLINE void85setCompressObjectReferences(bool compress)86{87_compressObjectReferences = compress;88}89#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */9091/**92* Set the array object model.93*/94MMINLINE void95setArrayObjectModel(GC_ArrayObjectModel *arrayObjectModel)96{97_arrayObjectModel = arrayObjectModel;98}99100/**101* Get the array object model.102*/103MMINLINE GC_ArrayObjectModel*104getArrayObjectModel()105{106return _arrayObjectModel;107}108109/**110* Set the array object model.111*/112MMINLINE void113setMixedObjectModel(GC_MixedObjectModel *mixedObjectModel)114{115_mixedObjectModel = mixedObjectModel;116}117118/**119* Get the array object model.120*/121MMINLINE GC_MixedObjectModel*122getMixedObjectModel()123{124return _mixedObjectModel;125}126127/**128* This method is called for each heap object during heap walks. If the received object holds129* an indirect object reference (ie a reference to an object that might not otherwise be walked),130* a pointer to the indirect object should be returned here.131*132* @param objectPtr the object to obtain indirect reference from133* @return a pointer to the indirect object, or NULL if none134*/135MMINLINE omrobjectptr_t136getIndirectObject(omrobjectptr_t objectPtr)137{138J9Class *clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, this);139return J9VM_J9CLASS_TO_HEAPCLASS(clazz);140}141142/**143* Get the byte offset from object address to object hash code slot.144*/145MMINLINE uintptr_t146getHashcodeOffset(omrobjectptr_t objectPtr) {147UDATA offset = 0;148149if (isIndexable(objectPtr)) {150offset = _arrayObjectModel->getHashcodeOffset((J9IndexableObject *)objectPtr);151} else {152offset = _mixedObjectModel->getHashcodeOffset(objectPtr);153}154155return offset;156}157158/**159* Get the offset of the slot containing the object header.160*/161MMINLINE uintptr_t162getObjectHeaderSlotOffset()163{164return _objectHeaderSlotOffset;165}166167/**168* Get the bit offset to the flags byte in object headers.169*/170MMINLINE uintptr_t171getObjectHeaderSlotFlagsShift()172{173return _objectHeaderSlotFlagsShift;174}175176/**177* Get the exact size of the object header, in bytes.178*/179MMINLINE uintptr_t180getObjectHeaderSizeInBytes(omrobjectptr_t objectPtr)181{182uintptr_t headerSize = 0;183184if (isIndexable(objectPtr)) {185headerSize = _arrayObjectModel->getHeaderSize((J9IndexableObject *)objectPtr);186} else {187headerSize = _mixedObjectModel->getHeaderSize(objectPtr);188}189190return headerSize;191}192193/**194* Get the exact size of the object data, in bytes. This excludes the size of the object header,195* hash code and any bytes added for object alignment. If the object has a discontiguous representation,196* this method should return the size of the root object that the discontiguous parts depend from.197*198* @param[in] objectPtr points to the object to determine size for199* @return the exact size of an object, in bytes, excluding padding bytes and header bytes200*/201MMINLINE uintptr_t202getObjectSizeInBytesWithoutHeader(omrobjectptr_t objectPtr)203{204uintptr_t dataSize = 0;205206if (isIndexable(objectPtr)) {207dataSize = _arrayObjectModel->getSizeInBytesWithoutHeader((J9IndexableObject *)objectPtr);208} else {209dataSize = _mixedObjectModel->getSizeInBytesWithoutHeader(objectPtr);210}211212return dataSize;213}214215/**216* Get the exact total size of the object data, in bytes. This includes the size of the object217* header and hash code but excludes bytes added for object alignment. If the object has a218* discontiguous representation, this method should return the size of the root object that the219* discontiguous parts depend from.220*221* @param[in] objectPtr points to the object to determine size for222* @return the exact size of an object, in bytes, excluding padding bytes and header bytes223*/224MMINLINE uintptr_t225getObjectSizeInBytesWithHeader(omrobjectptr_t objectPtr, bool includeHashCode)226{227uintptr_t dataSize = 0;228229/* get header + data size */230if (isIndexable(objectPtr)) {231dataSize = _arrayObjectModel->getSizeInBytesWithoutHeader((J9IndexableObject *)objectPtr);232dataSize += _arrayObjectModel->getHeaderSize((J9IndexableObject *)objectPtr);233} else {234dataSize = _mixedObjectModel->getSizeInBytesWithoutHeader(objectPtr);235dataSize += _mixedObjectModel->getHeaderSize(objectPtr);236}237238/* include space for hash code reservation */239if (includeHashCode) {240if (getHashcodeOffset(objectPtr) == dataSize) {241dataSize += sizeof(uintptr_t);242}243}244245return dataSize;246}247248/**249* Get the total footprint of an object, in bytes, including the object header and all data.250* If the object has a discontiguous representation, this method should return the size of251* the root object plus the total of all the discontiguous parts of the object.252*253* @param[in] objectPtr points to the object to determine size for254* @return the total size of an object, in bytes, including discontiguous parts255*/256MMINLINE uintptr_t257getTotalFootprintInBytes(omrobjectptr_t objectPtr)258{259uintptr_t dataSize = getObjectSizeInBytesWithHeader(objectPtr);260261if (isIndexable(objectPtr)) {262// add size of arraylet leaves (if any)263dataSize += _arrayObjectModel->externalArrayletsSize((J9IndexableObject *)objectPtr);264}265266return dataSize;267}268269/**270* Get the exact size of the object data, in bytes. This includes the size of the object header and271* hash slot (if allocated) and excludes any bytes added for object alignment. If the object has a272* discontiguous representation, this method should return the size of the root object that the273* discontiguous parts depend from.274*275* @param[in] objectPtr points to the object to determine size for276* @return the exact size of an object, in bytes, excluding padding bytes and header bytes277*/278MMINLINE uintptr_t279getObjectSizeInBytesWithHeader(omrobjectptr_t objectPtr)280{281uintptr_t flags = 0;282if (compressObjectReferences()) {283flags = *(uint32_t*)objectPtr;284} else {285flags = *(uintptr_t*)objectPtr;286}287bool hasBeenMoved = J9_ARE_ANY_BITS_SET((flags >> getObjectHeaderSlotFlagsShift()) & _delegateHeaderSlotFlagsMask, OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS);288return getObjectSizeInBytesWithHeader(objectPtr, hasBeenMoved);289}290291/**292* If object initialization fails for any reason, this method must return NULL. In that case, the heap293* memory allocated for the object will become floating garbage in the heap and will be recovered in294* the next GC cycle.295*296* @param[in] env points to the environment for the calling thread297* @param[in] allocatedBytes points to the heap memory allocated for the object298* @param[in] allocateInitialization points to the MM_AllocateInitialization instance used to allocate the heap memory299* @return pointer to the initialized object, or NULL if initialization fails300*/301omrobjectptr_t initializeAllocation(MM_EnvironmentBase *env, void *allocatedBytes, MM_AllocateInitialization *allocateInitialization);302303/**304* Returns TRUE if an object is indexable, FALSE otherwise. Languages that support indexable objects305* (eg, arrays) must provide an implementation that distinguished indexable from scalar objects.306*307* @param objectPtr pointer to the object308* @return TRUE if object is indexable, FALSE otherwise309*/310MMINLINE bool311isIndexable(omrobjectptr_t objectPtr)312{313J9Class* clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, this);314return J9GC_CLASS_IS_ARRAY(clazz);315}316317/**318* The following methods (defined(OMR_GC_MODRON_SCAVENGER)) are required if generational GC is319* configured for the build (--enable-OMR_GC_MODRON_SCAVENGER in configure_includes/configure_*.mk).320* They typically involve a MM_ForwardedHeader object, and allow information about the forwarded321* object to be obtained.322*/323#if defined(OMR_GC_MODRON_SCAVENGER)324/**325* Returns TRUE if the object referred to by the forwarded header is indexable.326*327* @param forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object328* @return TRUE if object is indexable, FALSE otherwise329*/330MMINLINE bool331isIndexable(MM_ForwardedHeader *forwardedHeader)332{333J9Class* clazz = (J9Class *)((uintptr_t)(forwardedHeader->getPreservedSlot()) & ~(UDATA)_delegateHeaderSlotFlagsMask);334return J9GC_CLASS_IS_ARRAY(clazz);335}336337/**338* Get the instance size (total) in bytes of a forwarded object from the forwarding pointer.339*340* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object341* @return The instance size (total) in bytes of the forwarded object342*/343MMINLINE uintptr_t344getForwardedObjectSizeInBytes(MM_ForwardedHeader *forwardedHeader)345{346uintptr_t size = 0;347uintptr_t preservedSlot = (uintptr_t)(forwardedHeader->getPreservedSlot());348J9Class* clazz = (J9Class *)(preservedSlot & ~(UDATA)_delegateHeaderSlotFlagsMask);349350if (J9GC_CLASS_IS_ARRAY(clazz)) {351uintptr_t elements = 0;352#if defined (OMR_GC_COMPRESSED_POINTERS)353if (compressObjectReferences()) {354elements = forwardedHeader->getPreservedOverlap();355} else356#endif /* defined (OMR_GC_COMPRESSED_POINTERS) */357{358elements = ((J9IndexableObjectContiguousFull *)forwardedHeader->getObject())->size;359}360361if (0 == elements) {362/* Discontiguous */363if (compressObjectReferences()) {364elements = ((J9IndexableObjectDiscontiguousCompressed *)forwardedHeader->getObject())->size;365} else {366elements = ((J9IndexableObjectDiscontiguousFull *)forwardedHeader->getObject())->size;367}368}369370uintptr_t dataSize = _arrayObjectModel->getDataSizeInBytes(clazz, elements);371GC_ArrayletObjectModel::ArrayLayout layout = _arrayObjectModel->getArrayletLayout(clazz, dataSize);372size = _arrayObjectModel->getSizeInBytesWithHeader(clazz, layout, elements);373} else {374size = _mixedObjectModel->getSizeInBytesWithoutHeader(clazz) + J9GC_OBJECT_HEADER_SIZE(this);375}376377return size;378}379380/**381* Returns the field offset of the hottest field of the object referred to by the forwarded header.382* Valid if scavenger dynamicBreadthFirstScanOrdering is enabled.383*384* @param forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object385* @return the offset of the hottest field of the given object referred to by the forwarded header, return U_8_MAX if a hot field does not exist386*/387MMINLINE uint8_t388getHotFieldOffset(MM_ForwardedHeader *forwardedHeader)389{390J9Class* hotClass = ((J9Class *)(((uintptr_t)(forwardedHeader->getPreservedSlot())) & ~(UDATA)_delegateHeaderSlotFlagsMask));391if (hotClass->hotFieldsInfo != NULL) {392return hotClass->hotFieldsInfo->hotFieldOffset1;393}394395return U_8_MAX;396}397398/**399* Returns the field offset of the second hottest field of the object referred to by the forwarded header.400* Valid if scavenger dynamicBreadthFirstScanOrdering is enabled401*402* @param forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object403* @return the offset of the second hottest field of the given object referred to by the forwarded header, return U_8_MAX if the hot field does not exist404*/405MMINLINE uint8_t406getHotFieldOffset2(MM_ForwardedHeader *forwardedHeader)407{408J9Class* hotClass = ((J9Class *)(((uintptr_t)(forwardedHeader->getPreservedSlot())) & ~(UDATA)_delegateHeaderSlotFlagsMask));409if (hotClass->hotFieldsInfo != NULL) {410return hotClass->hotFieldsInfo->hotFieldOffset2;411}412413return U_8_MAX;414}415416/**417* Returns the field offset of the third hottest field of the object referred to by the forwarded header.418* Valid if scavenger dynamicBreadthFirstScanOrdering is enabled419*420* @param forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object421* @return the offset of the third hottest field of the given object referred to by the forwarded header, return U_8_MAX if the hot field does not exist422*/423MMINLINE uint8_t424getHotFieldOffset3(MM_ForwardedHeader *forwardedHeader)425{426J9Class* hotClass = ((J9Class *)(((uintptr_t)(forwardedHeader->getPreservedSlot())) & ~(UDATA)_delegateHeaderSlotFlagsMask));427if (hotClass->hotFieldsInfo != NULL) {428return hotClass->hotFieldsInfo->hotFieldOffset3;429}430431return U_8_MAX;432}433434/**435* Return true if the object holds references to heap objects not reachable from reference graph. For436* example, an object may be associated with a class and the class may have associated meta-objects437* that are in the heap but not directly reachable from the root set. This method is called to438* determine whether or not any such objects exist.439*440* @param env points to environment for the thread441* @param objectPtr points to an object442* @return true if object holds indirect references to heap objects443*/444MMINLINE bool445hasIndirectObjectReferents(CLI_THREAD_TYPE *thread, omrobjectptr_t objectPtr)446{447return J9GC_IS_INITIALIZED_HEAPCLASS(thread, objectPtr);448}449450/**451* Calculate the actual object size and the size adjusted to object alignment. The calculated object size452* includes any expansion bytes allocated if the object will grow when moved.453*454* @param[in] env points to the environment for the calling thread455* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object456* @param[out] objectCopySizeInBytes actual object size457* @param[out] objectReserveSizeInBytes size adjusted to object alignment458* @param[out] hotFieldAlignmentDescriptor pointer to hot field alignment descriptor for class (or NULL)459*/460void calculateObjectDetailsForCopy(MM_EnvironmentBase *env, MM_ForwardedHeader *forwardedHeader, uintptr_t *objectCopySizeInBytes, uintptr_t *objectReserveSizeInBytes, uintptr_t *hotFieldAlignmentDescriptor);461#endif /* defined(OMR_GC_MODRON_SCAVENGER) */462463/**464* Constructor receives a copy of OMR's object flags mask, normalized to low order byte. Delegate465* realigns it for internal use.466*/467GC_ObjectModelDelegate(uintptr_t omrHeaderSlotFlagsMask)468: _delegateHeaderSlotFlagsMask(omrHeaderSlotFlagsMask << _objectHeaderSlotFlagsShift)469{}470471};472473#endif /* OBJECTMODELDELEGATE_HPP_ */474475476