Path: blob/master/runtime/gc_glue_java/ObjectModel.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/**23* @file24* @ingroup GC_Base25*/2627#if !defined(OBJECTMODEL_HPP_)28#define OBJECTMODEL_HPP_2930/* @ddr_namespace: default */31#include <assert.h>3233#include "j9.h"34#include "j9cfg.h"35#include "j9consts.h"36#include "j9nonbuilder.h"37#include "modron.h"38#include "j9modron.h"39#include "objectdescription.h"40#include "util_api.h"4142#include "ArrayObjectModel.hpp"43#include "ArrayletObjectModel.hpp"44#include "AtomicOperations.hpp"45#include "ForwardedHeader.hpp"46#include "HeapLinkedFreeHeader.hpp"47#include "MixedObjectModel.hpp"48#include "ObjectModelBase.hpp"49#include "ObjectModelDelegate.hpp"5051#if defined(OMR_GC_REALTIME)52/* this bit is set in the object header slot if an overflow condition is raised */53#define GC_OVERFLOW 0x454#endif /* defined(OMR_GC_REALTIME) */5556/*57* #defines representing the scope depth stored in each object header58* use two low bits of Collector Bits for Depth59*/60#define OBJECT_HEADER_DEPTH_ZERO 061#define OBJECT_HEADER_DEPTH_MAX 362#define OBJECT_HEADER_DEPTH_SHIFT OMR_OBJECT_METADATA_AGE_SHIFT63#define OBJECT_HEADER_DEPTH_MASK (OBJECT_HEADER_DEPTH_MAX << OBJECT_HEADER_DEPTH_SHIFT)6465/* check that we have enough collector bits to be used for Depth */66#if (0 != (OBJECT_HEADER_DEPTH_MASK & ~(OMR_OBJECT_METADATA_AGE_MASK)))67#error "Some OBJECT_HEADER_DEPTH_MASK bits are out of range of OMR_OBJECT_METADATA_AGE_MASK."68#endif /* (0 != (OBJECT_HEADER_DEPTH_MASK & ~(OMR_OBJECT_METADATA_AGE_MASK))) */6970/*71* #defines representing the 2 bits stored in immortal object header used as mark and overflow bits by ReferenceChainWalker.72* Both bits occupy the arraylet layout bits which have been deprecated73*/74#define OBJECT_HEADER_REFERENCE_CHAIN_WALKER_IMMORTAL_MARKED 0x4075#define OBJECT_HEADER_REFERENCE_CHAIN_WALKER_IMMORTAL_OVERFLOW 0xC07677/* Object header flag bits used for lazy hashcode insertion on copy/move */78#define OMR_GC_DEFERRED_HASHCODE_INSERTION7980class MM_AllocateInitialization;81class MM_EnvironmentBase;82class MM_GCExtensionsBase;8384/**85* Provides information for a given object.86* @ingroup GC_Base87*/88class GC_ObjectModel : public GC_ObjectModelBase89{90/*91* Member data and types92*/93private:94J9JavaVM* _javaVM; /***< pointer to the Java VM */95GC_MixedObjectModel *_mixedObjectModel; /**< pointer to the mixed object model in extensions (so that we can delegate to it) */96GC_ArrayObjectModel *_indexableObjectModel; /**< pointer to the indexable object model in extensions (so that we can delegate to it) */97J9Class *_classClass; /**< java.lang.Class class pointer for detecting special objects */98J9Class *_classLoaderClass; /**< java.lang.ClassLoader class pointer for detecting special objects */99J9Class *_atomicMarkableReferenceClass; /**< java.util.concurrent.atomic.AtomicMarkableReference class pointer for detecting special objects */100101protected:102public:103/**104* Return values for getScanType().105*/106enum ScanType {107SCAN_INVALID_OBJECT = 0,108SCAN_MIXED_OBJECT = 1,109SCAN_POINTER_ARRAY_OBJECT = 2,110SCAN_PRIMITIVE_ARRAY_OBJECT = 3,111SCAN_REFERENCE_MIXED_OBJECT = 4,112SCAN_CLASS_OBJECT = 5,113SCAN_CLASSLOADER_OBJECT = 6,114SCAN_ATOMIC_MARKABLE_REFERENCE_OBJECT = 7,115SCAN_OWNABLESYNCHRONIZER_OBJECT = 8,116SCAN_MIXED_OBJECT_LINKED = 9,117SCAN_FLATTENED_ARRAY_OBJECT = 10118};119120/**121* Values for the 'state' field in java.lang.ref.Reference.122* Note that these values are mirrored in the Java code. Do not change them.123*/124enum ReferenceState {125REF_STATE_INITIAL = 0, /**< indicates the initial (normal) state for a Reference object. Referent is weak. */126REF_STATE_CLEARED = 1, /**< indicates that the Reference object has been cleared, either by the GC or by the Java clear() API. Referent is null or strong. */127REF_STATE_ENQUEUED = 2, /**< indicates that the Reference object has been cleared and enqueued on its ReferenceQueue. Referent is null or strong. */128REF_STATE_REMEMBERED = 3, /**< indicates that the Reference object was discovered by a global cycle and that the current local GC cycle must return it to that list and restore the state to INITIAL. */129};130131/*132* Member functions133*/134private:135/**136* Determine the scan type for an instant of the specified class.137* The class has the J9AccClassGCSpecial bit set.138* @param[in] objectClazz the class of the object to identify139* @return one of the ScanType constants140*/141ScanType getSpecialClassScanType(J9Class *objectClazz);142143/**144* Examine all classes as they are loaded to determine if they require the J9AccClassGCSpecial bit.145* These classes are handled specially by GC_ObjectModel::getScanType()146*/147static void internalClassLoadHook(J9HookInterface** hook, uintptr_t eventNum, void* eventData, void* userData);148149/**150* Update all of the GC special class pointers to their most current version after a class151* redefinition has occurred.152*/153static void classesRedefinedHook(J9HookInterface** hook, uintptr_t eventNum, void* eventData, void* userData);154155/**156* Returns the shape of an class.157* @param objectPtr Pointer to object whose shape is required.158* @return The shape of the object159*/160MMINLINE uintptr_t161getClassShape(J9Object *objectPtr)162{163J9Class* clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, this);164return J9GC_CLASS_SHAPE(clazz);165}166167public:168/**169* Determine the ScanType code for objects of the specified class. This code determines how instances should be scanned.170* @param clazz[in] the class of the object to be scanned171* @return a ScanType code, SCAN_INVALID_OBJECT if the code cannot be determined due to an error172*/173MMINLINE ScanType174getScanType(J9Class *clazz)175{176ScanType result = SCAN_INVALID_OBJECT;177178switch(J9GC_CLASS_SHAPE(clazz)) {179case OBJECT_HEADER_SHAPE_MIXED:180{181uintptr_t classFlags = J9CLASS_FLAGS(clazz) & (J9AccClassReferenceMask | J9AccClassGCSpecial | J9AccClassOwnableSynchronizer);182if (0 == classFlags) {183if (0 != clazz->selfReferencingField1) {184result = SCAN_MIXED_OBJECT_LINKED;185} else {186result = SCAN_MIXED_OBJECT;187}188} else {189if (0 != (classFlags & J9AccClassReferenceMask)) {190result = SCAN_REFERENCE_MIXED_OBJECT;191} else if (0 != (classFlags & J9AccClassGCSpecial)) {192result = getSpecialClassScanType(clazz);193} else if (0 != (classFlags & J9AccClassOwnableSynchronizer)) {194result = SCAN_OWNABLESYNCHRONIZER_OBJECT;195} else {196/* Assert_MM_unreachable(); */197assert(false);198}199}200break;201}202case OBJECT_HEADER_SHAPE_POINTERS:203if (J9_IS_J9CLASS_FLATTENED(clazz)) {204if (J9CLASS_HAS_REFERENCES(((J9ArrayClass *)clazz)->leafComponentType)) {205result = SCAN_FLATTENED_ARRAY_OBJECT;206} else {207result = SCAN_PRIMITIVE_ARRAY_OBJECT;208}209} else {210result = SCAN_POINTER_ARRAY_OBJECT;211}212break;213case OBJECT_HEADER_SHAPE_DOUBLES:214case OBJECT_HEADER_SHAPE_BYTES:215case OBJECT_HEADER_SHAPE_WORDS:216case OBJECT_HEADER_SHAPE_LONGS:217/* Must be a primitive array*/218result = SCAN_PRIMITIVE_ARRAY_OBJECT;219break;220default:221result = SCAN_INVALID_OBJECT;222}223224return result;225}226227MMINLINE ScanType228getScanType(J9Object *objectPtr)229{230J9Class *clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, this);231return getScanType(clazz);232}233234/**235* Returns the depth of an object.236* @param objectPtr Pointer to object whose depth is required.237* @return The depth of the object238*/239MMINLINE uintptr_t240getObjectDepth(J9Object *objectPtr)241{242return (getRememberedBits(objectPtr) & OBJECT_HEADER_DEPTH_MASK);243}244245/**246* Returns TRUE if a class is indexable, FALSE otherwise.247* @param clazz Pointer to the class248* @return TRUE if a class is indexable, FALSE otherwise249*/250MMINLINE bool251isIndexable(J9Class* clazz)252{253return J9GC_CLASS_IS_ARRAY(clazz);254}255256using GC_ObjectModelBase::isIndexable;257258/**259* Returns TRUE if an object has a OBJECT_HEADER_SHAPE_POINTERS shape, FALSE otherwise.260* @param objectPtr Pointer to an object261* @return TRUE if an object has a OBJECT_HEADER_SHAPE_POINTERS shape, FALSE otherwise262*/263MMINLINE bool264isObjectArray(J9Object *objectPtr)265{266J9Class* clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, this);267return (OBJECT_HEADER_SHAPE_POINTERS == J9GC_CLASS_SHAPE(clazz));268}269270/**271* @see isObjectArray(J9Object *objectPtr)272*/273MMINLINE bool274isObjectArray(J9IndexableObject *objectPtr)275{276return isObjectArray((J9Object*)objectPtr);277}278279/**280* Returns TRUE if an object is primitive array, FALSE otherwise.281* @param objectPtr Pointer to an object282* @return TRUE if an object is primitive array, FALSE otherwise283*/284MMINLINE bool285isPrimitiveArray(J9Object *objectPtr)286{287bool isPrimitiveArray = false;288289switch(getClassShape(objectPtr)) {290case OBJECT_HEADER_SHAPE_BYTES:291case OBJECT_HEADER_SHAPE_WORDS:292case OBJECT_HEADER_SHAPE_LONGS:293case OBJECT_HEADER_SHAPE_DOUBLES:294isPrimitiveArray = true;295break;296default:297isPrimitiveArray = false;298break;299}300301return isPrimitiveArray;302}303304/**305* @see isPrimitiveArray(J9Object *objectPtr)306*/307MMINLINE bool308isPrimitiveArray(J9IndexableObject *objectPtr)309{310return isPrimitiveArray((J9Object*)objectPtr);311}312313/**314* Determine whether or not the given object is a double array315*316* @return true if objectPtr is a double array317* @return false otherwise318*/319MMINLINE bool320isDoubleArray(J9Object* objectPtr)321{322return (OBJECT_HEADER_SHAPE_DOUBLES == getClassShape(objectPtr));323}324325/**326* @see isDoubleArray(J9Object* objectPtr)327*/328MMINLINE bool329isDoubleArray(J9IndexableObject *objectPtr)330{331return isDoubleArray((J9Object*)objectPtr);332}333334/**335* Check is indexable bit set properly:336* must be set for arrays and primitive arrays337* must not be set for all others338* @param objectPtr Pointer to an object339* @return TRUE if indexable bit is set properly340*/341MMINLINE bool342checkIndexableFlag(J9Object *objectPtr)343{344bool result = false;345346if (isObjectArray(objectPtr) || isPrimitiveArray(objectPtr)) {347if (isIndexable(objectPtr)) {348result = true;349}350} else {351if (!isIndexable(objectPtr)) {352result = true;353}354}355return result;356}357358/**359* Determine the basic hash code for the specified object. This may modify the object. For example, it may360* set the HAS_BEEN_HASHED bit in the object's header. Object must not be NULL.361*362* @param object[in] the object to be hashed363* @return the persistent, basic hash code for the object364*/365MMINLINE int32_t366getObjectHashCode(J9JavaVM *vm, J9Object *object)367{368int32_t result = 0;369#if defined (OMR_GC_MODRON_COMPACTION) || defined (J9VM_GC_GENERATIONAL)370if (hasBeenMoved(object)) {371uintptr_t hashOffset = getHashcodeOffset(object);372result = *(int32_t*)((uint8_t*)object + hashOffset);373} else {374atomicSetObjectFlags(object, 0, OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS);375result = convertValueToHash(vm, (uintptr_t)object);376}377#else /* defined (OMR_GC_MODRON_COMPACTION) || defined (J9VM_GC_GENERATIONAL) */378result = computeObjectAddressToHash(vm, object);379#endif /* defined (OMR_GC_MODRON_COMPACTION) || defined (J9VM_GC_GENERATIONAL) */380return result;381}382383/**384* Initialize the basic hash code for the specified object.385* Space for the hash slot must already exist.386*387* @note Sets OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS | OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS flags388* @param object[in] the object to be initialized.389*/390MMINLINE void391initializeHashSlot(J9JavaVM* vm, J9Object *objectPtr)392{393#if defined (OMR_GC_MODRON_COMPACTION) || defined (J9VM_GC_GENERATIONAL)394uintptr_t hashOffset = getHashcodeOffset(objectPtr);395uint32_t *hashCodePointer = (uint32_t*)((uint8_t*)objectPtr + hashOffset);396397*hashCodePointer = convertValueToHash(vm, (uintptr_t)objectPtr);398setObjectHasBeenMoved(objectPtr);399#endif /* defined (OMR_GC_MODRON_COMPACTION) || defined (J9VM_GC_GENERATIONAL) */400}401402/**403* Returns TRUE if an object has been hashed or moved, FALSE otherwise.404* @param objectPtr Object to test405* @return TRUE if an object has been hashed or moved, FALSE otherwise406*/407MMINLINE bool408hasBeenHashed(J9Object *objectPtr)409{410return hasBeenHashed(getObjectFlags(objectPtr));411}412413MMINLINE bool414hasBeenHashed(uintptr_t objectFlags)415{416return 0 != (objectFlags & (OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS | OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS));417}418419/**420* Returns TRUE if an object has been hashed but not moved, FALSE otherwise.421* @param objectPtr Object to test422* @return TRUE if an object has been hashed but not moved, FALSE otherwise423*/424MMINLINE bool425hasJustBeenHashed(J9Object *objectPtr)426{427return hasJustBeenHashed(getObjectFlags(objectPtr));428}429430MMINLINE bool431hasJustBeenHashed(uintptr_t objectFlags)432{433return OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS == (objectFlags & OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS);434}435436/**437* Returns TRUE if an object has been moved, regardless of state of hashed bit, FALSE otherwise.438* @param objectPtr Object to test439* @return TRUE if an object has been moved, regardless of state of hashed bit, FALSE otherwise440*/441MMINLINE bool442hasBeenMoved(J9Object *objectPtr)443{444return hasBeenMoved(getObjectFlags(objectPtr));445}446447MMINLINE bool448hasBeenMoved(uintptr_t objectFlags)449{450return OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS == (objectFlags & OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS);451}452453/**454* Returns TRUE if an object has been moved and hashed bit cleared, FALSE otherwise.455* @param objectPtr Object to test456* @return TRUE if an object has been moved and hashed bit cleared, FALSE otherwise457*/458MMINLINE bool459hasRecentlyBeenMoved(J9Object *objectPtr)460{461return hasRecentlyBeenMoved(getObjectFlags(objectPtr));462}463464MMINLINE bool465hasRecentlyBeenMoved(uintptr_t objectFlags)466{467return OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS == (objectFlags & (OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS | OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS));468}469470/**471* Set OBJECT_HEADER_HAS_BEEN_MOVED and OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS flags472* @param objectPtr Pointer to an object473*/474MMINLINE void475setObjectHasBeenMoved(omrobjectptr_t objectPtr)476{477setObjectFlags(objectPtr, 0, OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS | OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS);478}479480/**481* Set OBJECT_HEADER_HAS_BEEN_MOVED flag / clear OBJECT_HEADER_HAS_BEEN_HASHED bit482* @param objectPtr Pointer to an object483*/484MMINLINE void485setObjectJustHasBeenMoved(omrobjectptr_t objectPtr)486{487setObjectFlags(objectPtr, OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS, OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS);488}489490MMINLINE int32_t491computeObjectHash(MM_ForwardedHeader *forwardedHeader)492{493return convertValueToHash(_javaVM, (uintptr_t)forwardedHeader->getObject());494}495496MMINLINE uintptr_t497getHashcodeOffset(omrobjectptr_t objectPtr) {498return getObjectModelDelegate()->getHashcodeOffset(objectPtr);499}500501/**502* Same as getConsumedSizeInBytesWithHeader, except that it returns the size503* the object will consume if it is moved. i.e. it includes space for the504* hash code slot.505* @param objectPtr Pointer to an object506* @return The consumed heap size of an object, in bytes, including the header507*/508MMINLINE uintptr_t509getConsumedSizeInBytesWithHeaderForMove(J9Object *objectPtr)510{511return adjustSizeInBytes(getObjectModelDelegate()->getObjectSizeInBytesWithHeader(objectPtr, hasBeenHashed(objectPtr)));512}513514/**515* Same as getConsumedSizeInBytesWithHeader, except that it returns the size516* the object will consume if it is moved. i.e. it includes space for the517* hash code slot.518* @param objectPtr Pointer to an object519* @return The consumed heap size of an object, in bytes, including the header520*/521MMINLINE uintptr_t522getConsumedSizeInBytesWithHeaderBeforeMove(J9Object *objectPtr)523{524return adjustSizeInBytes(getObjectModelDelegate()->getObjectSizeInBytesWithHeader(objectPtr, hasBeenMoved(objectPtr) && !hasRecentlyBeenMoved(objectPtr)));525}526527#if defined(J9VM_GC_MODRON_SCAVENGER)528/**529* Extract the class pointer from an unforwarded object.530*531* This method will assert if the object has been marked as forwarded.532*533* @param[in] pointer to forwardedHeader the MM_ForwardedHeader instance encapsulating the object534* @return pointer to the J9Class from the object encapsulated by forwardedHeader535* @see MM_ForwardingHeader::isForwardedObject()536*/537MMINLINE J9Class *538getPreservedClass(MM_ForwardedHeader *forwardedHeader)539{540return (J9Class *)((uintptr_t)(forwardedHeader->getPreservedSlot()) & J9GC_J9OBJECT_CLAZZ_ADDRESS_MASK);541}542543/**544* Update the new version of this object after it has been copied. This undoes any damaged545* caused by installing the forwarding pointer into the original prior to the copy, and sets546* the object age.547*548* This will install the correct (i.e. unforwarded) class pointer, update the hashed/moved549* flags and install the hash code if the object has been hashed but not previously moved.550*551* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object552* @param[in] destinationObjectPtr pointer to the copied object to be fixed up553* @param[in] objectAge the age to set in the copied object554*/555MMINLINE void556fixupForwardedObject(MM_ForwardedHeader *forwardedHeader, omrobjectptr_t destinationObjectPtr, uintptr_t objectAge)557{558GC_ObjectModelBase::fixupForwardedObject(forwardedHeader, destinationObjectPtr, objectAge);559560if (isIndexable(forwardedHeader)) {561/* Updates internal field of indexable objects. Every indexable object have an extra field562* that can be used to store any extra information about the indexable object. One use case is563* OpenJ9 where we use this field to point to array data. In this case it will always point to564* the address right after the header, in case of contiguous data it will point to the data565* itself, and in case of discontiguous arraylet it will point to the first arrayiod. How to566* updated dataAddr is up to the target language that must override fixupDataAddr */567_indexableObjectModel->fixupDataAddr(forwardedHeader, destinationObjectPtr);568}569570fixupHashFlagsAndSlot(forwardedHeader, destinationObjectPtr);571}572573/**574* This will install the correct (i.e. unforwarded) class pointer, update the hashed/moved575* flags and install the hash code if the object has been hashed but not previously moved.576*577* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object578* @param[in] destinationObjectPtr pointer to the copied object to be fixed up579*/580MMINLINE void581fixupHashFlagsAndSlot(MM_ForwardedHeader *forwardedHeader, omrobjectptr_t destinationObjectPtr)582{583/* To have ability to backout last scavenge we need to recognize objects just moved (moved first time) in current scavenge584*585* Bits State586* --------------------------------587* m h moved / hashed bits588* 0 0 not moved / not hashed589* 0 1 not moved / hashed590* 1 0 just moved / hashed591* 1 1 moved / hashed592* --------------------------------593*/594if (hasBeenMoved(getPreservedFlags(forwardedHeader))) {595if (hasRecentlyBeenMoved(getPreservedFlags(forwardedHeader))) {596/* Moved bit set / hashed bit not set means "moved previous scavenge" so set moved/hashed */597setObjectHasBeenMoved(destinationObjectPtr);598}599} else if (hasBeenHashed(getPreservedFlags(forwardedHeader))) {600/* The object has been hashed and has not been moved so we must store the previous address into the hashcode slot at hashcode offset. */601uintptr_t hashOffset;602J9Class *clazz = getPreservedClass(forwardedHeader);603if (isIndexable(clazz)) {604hashOffset = _indexableObjectModel->getPreservedHashcodeOffset(forwardedHeader);605} else {606hashOffset = _mixedObjectModel->getHashcodeOffset(clazz);607}608609uint32_t *hashCodePointer = (uint32_t*)((uint8_t*) destinationObjectPtr + hashOffset);610*hashCodePointer = convertValueToHash(_javaVM, (uintptr_t)forwardedHeader->getObject());611setObjectJustHasBeenMoved(destinationObjectPtr);612}613}614615#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */616617#if defined(OMR_GC_REALTIME)618/**619* Set GC_OVERFLOW bit atomically620* @param objectPtr Pointer to an object621* @return true, if GC_OVERFLOW bit has been set this call622*/623MMINLINE bool624atomicSetOverflowBit(J9Object *objectPtr)625{626return atomicSetObjectFlags(objectPtr, 0, GC_OVERFLOW);627}628629/**630* Clear GC_OVERFLOW bit atomically631* @param objectPtr Pointer to an object632* @return true, if GC_OVERFLOW bit has been cleared this call633*/634MMINLINE bool635atomicClearOverflowBit(J9Object *objectPtr)636{637return atomicSetObjectFlags(objectPtr, GC_OVERFLOW, 0);638}639640/**641* Return back true if GC_OVERFLOW bit is set642* @param objectPtr Pointer to an object643* @return true, if GC_OVERFLOW bit is set644*/645MMINLINE bool646isOverflowBitSet(J9Object *objectPtr)647{648return (GC_OVERFLOW == (J9GC_J9OBJECT_FLAGS_FROM_CLAZZ(objectPtr, this) & GC_OVERFLOW));649}650#endif /* defined(OMR_GC_REALTIME) */651652/**653* Set class in clazz slot in object header, with header flags.654* @param objectPtr Pointer to an object655* @param clazz class pointer to set656* @param flags flag bits to set657*/658MMINLINE void659setObjectClassAndFlags(J9Object *objectPtr, J9Class* clazz, uintptr_t flags)660{661uintptr_t classBits = (uintptr_t)clazz;662uintptr_t flagsBits = flags & (uintptr_t)OMR_OBJECT_METADATA_FLAGS_MASK;663if (compressObjectReferences()) {664*((uint32_t*)getObjectHeaderSlotAddress(objectPtr)) = (uint32_t)(classBits | flagsBits);665} else {666*((uintptr_t*)getObjectHeaderSlotAddress(objectPtr)) = (classBits | flagsBits);667}668}669670/**671* Set class in clazz slot in object header, preserving header flags672* @param objectPtr Pointer to an object673* @param clazz class pointer to set674*/675MMINLINE void676setObjectClass(J9Object *objectPtr, J9Class* clazz)677{678setObjectClassAndFlags(objectPtr, clazz, getObjectFlags(objectPtr));679}680681/**682* Initialize the receiver, a new instance of GC_ObjectModel683*684* @return true on success, false on failure685*/686virtual bool initialize(MM_GCExtensionsBase *extensions);687688/**689* Tear down the receiver690*/691virtual void tearDown(MM_GCExtensionsBase *extensions);692693/**694* Constructor.695*/696GC_ObjectModel()697: GC_ObjectModelBase()698{}699};700701#endif /* OBJECTMODEL_HPP_ */702703704