Path: blob/master/runtime/gc_include/ObjectAccessBarrierAPI.hpp
5986 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#if !defined(OBJECTACCESSBARRIERAPI_HPP_)2324#define OBJECTACCESSBARRIERAPI_HPP_2526#include "j9cfg.h"2728#if defined(OMR_OVERRIDE_COMPRESS_OBJECT_REFERENCES)29#if OMR_OVERRIDE_COMPRESS_OBJECT_REFERENCES30#define MM_ObjectAccessBarrierAPI MM_ObjectAccessBarrierAPICompressed31#else /* OMR_OVERRIDE_COMPRESS_OBJECT_REFERENCES */32#define MM_ObjectAccessBarrierAPI MM_ObjectAccessBarrierAPIFull33#endif /* OMR_OVERRIDE_COMPRESS_OBJECT_REFERENCES */34#endif /* OMR_OVERRIDE_COMPRESS_OBJECT_REFERENCES */3536#include "j9.h"37#include "j9modron.h"38#include "omrmodroncore.h"39#include "omr.h"4041#include "AtomicSupport.hpp"42#include "ArrayCopyHelpers.hpp"43#include "j9nongenerated.h"4445#define J9OAB_MIXEDOBJECT_EA(object, offset, type) (type *)(((U_8 *)(object)) + offset)4647class MM_ObjectAccessBarrierAPI48{49friend class MM_ObjectAccessBarrier;50friend class MM_RealtimeAccessBarrier;5152/* Data members & types */53public:5455private:56const UDATA _writeBarrierType;57const UDATA _readBarrierType;58#if defined(OMR_GC_COMPRESSED_POINTERS)59const UDATA _compressedPointersShift;60#endif /* defined(OMR_GC_COMPRESSED_POINTERS) */6162protected:63#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)64bool const _compressObjectReferences;65#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */6667/* Methods */68public:6970/**71* Create an instance.72*/73MM_ObjectAccessBarrierAPI(J9VMThread *currentThread)74: _writeBarrierType(currentThread->javaVM->gcWriteBarrierType)75, _readBarrierType(currentThread->javaVM->gcReadBarrierType)76#if defined(OMR_GC_COMPRESSED_POINTERS)77, _compressedPointersShift(currentThread->javaVM->compressedPointersShift)78#endif /* defined(OMR_GC_COMPRESSED_POINTERS) */79#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)80, _compressObjectReferences(J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(currentThread))81#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */82{}8384/**85* Return back true if object references are compressed86* @return true, if object references are compressed87*/88MMINLINE bool compressObjectReferences() {89return OMR_COMPRESS_OBJECT_REFERENCES(_compressObjectReferences);90}9192static VMINLINE void93internalPostBatchStoreObjectCardTableAndGenerational(J9VMThread *vmThread, j9object_t object)94{95/* Check to see if object is old. If object is not old neither barrier is required96* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old97*98* Since card dirtying also requires this calculation remember these values99*/100UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;101UDATA objectDelta = (UDATA)object - base;102UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;103if (objectDelta < size) {104/* object is old so check for concurrent barrier */105if (0 != (vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE)) {106/* concurrent barrier is enabled so dirty the card for object */107dirtyCard(vmThread, objectDelta);108}109110/* generational barrier is required if object is old*/111rememberObject(vmThread, object);112}113}114115static VMINLINE void116internalPostBatchStoreObjectGenerational(J9VMThread *vmThread, j9object_t object)117{118/* Check to see if object is old. If object is not old neither barrier is required119* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old120*121* Since card dirtying also requires this calculation remember these values122*/123UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;124UDATA objectDelta = (UDATA)object - base;125UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;126if (objectDelta < size) {127/* generational barrier is required if object is old*/128rememberObject(vmThread, object);129}130}131132static VMINLINE void133internalPostBatchStoreObjectCardTableIncremental(J9VMThread *vmThread, j9object_t object)134{135/* Check to see if object is within the barrier range.136* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0)137*138* Since card dirtying also requires this calculation remember these values139*/140UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;141UDATA objectDelta = (UDATA)object - base;142UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;143if (objectDelta < size) {144/* Object is within the barrier range. Dirty the card */145dirtyCard(vmThread, objectDelta);146}147}148149static VMINLINE void150internalPostBatchStoreObjectCardTable(J9VMThread *vmThread, j9object_t object)151{152/* Check to see if object is old. If object is not old neither barrier is required153* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old154*155* Since card dirtying also requires this calculation remember these values156*/157UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;158UDATA objectDelta = (UDATA)object - base;159UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;160if (objectDelta < size) {161/* object is old so check for concurrent barrier */162if (0 != (vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE)) {163/* concurrent barrier is enabled so dirty the card for object */164dirtyCard(vmThread, objectDelta);165}166}167}168169/**170* Call after storing an object reference for barrier type171* j9gc_modron_wrtbar_cardmark_and_oldcheck172*173* @param object the object being stored into174* @param value the object reference being stored175*176*/177static VMINLINE void178internalPostObjectStoreCardTableAndGenerational(J9VMThread *vmThread, j9object_t object, j9object_t value)179{180/* if value is NULL neither barrier is required */181if (NULL != value) {182/* Check to see if object is old. If object is not old neither barrier is required183* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old184*185* Since card dirtying also requires this calculation remember these values186*/187UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;188UDATA objectDelta = (UDATA)object - base;189UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;190if (objectDelta < size) {191/* object is old so check for concurrent barrier */192if (0 != (vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE)) {193/* concurrent barrier is enabled so dirty the card for object */194dirtyCard(vmThread, objectDelta);195}196197/* generational barrier is required if object is old and value is new */198/* Check to see if value is new using the same optimization as above */199UDATA valueDelta = (UDATA)value - base;200if (valueDelta >= size) {201/* value is in new space so do generational barrier */202rememberObject(vmThread, object);203}204}205}206}207208/**209* Call after storing an object reference for barrier type210* j9gc_modron_wrtbar_cardmark211*212* @param object the object being stored into213* @param value the object reference being stored214*215*/216static VMINLINE void217internalPostObjectStoreCardTable(J9VMThread *vmThread, j9object_t object, j9object_t value)218{219/* if value is NULL neither barrier is required */220if (NULL != value) {221/* Check to see if object is old.222* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old223*224* Since card dirtying also requires this calculation remember these values225*/226UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;227UDATA objectDelta = (UDATA)object - base;228UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;229if (objectDelta < size) {230/* object is old so check for concurrent barrier */231if (0 != (vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE)) {232/* concurrent barrier is enabled so dirty the card for object */233dirtyCard(vmThread, objectDelta);234}235}236}237}238239/**240* Call after storing an object reference for barrier type241* j9gc_modron_wrtbar_cardmark_incremental242*243* @param object the object being stored into244* @param value the object reference being stored245*246*/247static VMINLINE void248internalPostObjectStoreCardTableIncremental(J9VMThread *vmThread, j9object_t object, j9object_t value)249{250/* if value is NULL neither barrier is required */251if (NULL != value) {252/* Check to see if object is within the barrier range.253* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0)254*255* Since card dirtying also requires this calculation remember these values256*/257UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;258UDATA objectDelta = (UDATA)object - base;259UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;260if (objectDelta < size) {261/* Object is within the barrier range. Dirty the card */262dirtyCard(vmThread, objectDelta);263}264}265}266267/**268* Call after storing an object reference for barrier type269* j9gc_modron_wrtbar_oldcheck270*271* @param object the object being stored into272* @param value the object reference being stored273*274*/275static VMINLINE void276internalPostObjectStoreGenerational(J9VMThread *vmThread, j9object_t object, j9object_t value)277{278/* if value is NULL neither barrier is required */279if (NULL != value) {280/* Check to see if object is old.281* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old282*283* Since card dirtying also requires this calculation remember these values284*/285UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;286UDATA objectDelta = (UDATA)object - base;287UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;288if (objectDelta < size) {289/* generational barrier is required if object is old and value is new */290/* Check to see if value is new using the same optimization as above */291UDATA valueDelta = (UDATA)value - base;292if (valueDelta >= size) {293/* value is in new space so do generational barrier */294rememberObject(vmThread, object);295}296}297}298}299300/**301* Call after storing an object reference for barrier type302* j9gc_modron_wrtbar_oldcheck303*304* @param object the object being stored into305* @param value the object reference being stored306*307*/308static VMINLINE void309internalPostObjectStoreGenerationalNoValueCheck(J9VMThread *vmThread, j9object_t object)310{311/* Check to see if object is old.312* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old313*314* Since card dirtying also requires this calculation remember these values315*/316UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;317UDATA objectDelta = (UDATA)object - base;318UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;319if (objectDelta < size) {320rememberObject(vmThread, object);321}322}323324/**325* Return the address of the lockword for the given object, or NULL if it326* does not have an inline lockword.327*/328VMINLINE j9objectmonitor_t *329getLockwordAddress(J9VMThread *currentThread, J9Object *object)330{331j9objectmonitor_t *lockwordAddress = NULL;332J9Class *clazz = J9OBJECT_CLAZZ(currentThread, object);333if (!J9_IS_J9CLASS_VALUETYPE(clazz)) {334UDATA lockOffset = clazz->lockOffset;335if ((IDATA) lockOffset >= 0) {336lockwordAddress = (j9objectmonitor_t *)(((U_8 *)object) + lockOffset);337}338}339return lockwordAddress;340}341342VMINLINE void343cloneArray(J9VMThread *currentThread, j9object_t original, j9object_t copy, J9Class *objectClass, U_32 size)344{345#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)346currentThread->javaVM->memoryManagerFunctions->j9gc_objaccess_cloneIndexableObject(currentThread, (J9IndexableObject*)original, (J9IndexableObject*)copy);347#else /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */348bool copyLockword = true;349350if (OBJECT_HEADER_SHAPE_POINTERS == J9CLASS_SHAPE(objectClass)) {351VM_ArrayCopyHelpers::referenceArrayCopy(currentThread, original, 0, copy, 0, size);352} else {353VM_ArrayCopyHelpers::primitiveArrayCopy(currentThread, original, 0, copy, 0, size, (((J9ROMArrayClass*)objectClass->romClass)->arrayShape & 0x0000FFFF));354}355if (copyLockword) {356/* zero lockword, if present */357j9objectmonitor_t *lockwordAddress = getLockwordAddress(currentThread, copy);358if (NULL != lockwordAddress) {359J9_STORE_LOCKWORD(currentThread, lockwordAddress, 0);360}361}362#endif /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */363}364365VMINLINE UDATA366mixedObjectGetHeaderSize(J9Class *objectClass)367{368return (compressObjectReferences() ? sizeof(J9ObjectCompressed) : sizeof(J9ObjectFull)) + J9CLASS_PREPADDING_SIZE(objectClass);369}370371VMINLINE UDATA372mixedObjectGetDataSize(J9Class *objectClass)373{374return J9CLASS_UNPADDED_INSTANCE_SIZE(objectClass);375}376377VMINLINE void378cloneObject(J9VMThread *currentThread, j9object_t original, j9object_t copy, J9Class *objectClass)379{380UDATA offset = mixedObjectGetHeaderSize(objectClass);381382copyObjectFields(currentThread, objectClass, original, offset, copy, offset);383}384385VMINLINE void386copyObjectFieldsToFlattenedArrayElement(J9VMThread *vmThread, J9ArrayClass *arrayClazz, j9object_t srcObject, J9IndexableObject *arrayRef, UDATA index)387{388/* TODO optimizations for non-arraylet path will be added in the future */389vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_copyObjectFieldsToFlattenedArrayElement(vmThread, arrayClazz, srcObject, arrayRef, (I_32)index);390}391392VMINLINE void393copyObjectFieldsFromFlattenedArrayElement(J9VMThread *vmThread, J9ArrayClass *arrayClazz, j9object_t destObject, J9IndexableObject *arrayRef, UDATA index)394{395/* TODO optimizations for non-arraylet path will be added in the future */396vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_copyObjectFieldsFromFlattenedArrayElement(vmThread, arrayClazz, destObject, arrayRef, (I_32)index);397}398399VMINLINE BOOLEAN400structuralFlattenedCompareObjects(J9VMThread *vmThread, J9Class *valueClass, j9object_t lhsObject, j9object_t rhsObject, UDATA startOffset)401{402#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)403return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_structuralCompareFlattenedObjects(vmThread, valueClass, lhsObject, rhsObject, startOffset);404#else /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */405bool hasReferences = J9CLASS_HAS_REFERENCES(valueClass);406if (hasReferences && (j9gc_modron_readbar_none != _readBarrierType)) {407return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_structuralCompareFlattenedObjects(vmThread, valueClass, lhsObject, rhsObject, startOffset);408} else {409UDATA compareSize = mixedObjectGetDataSize(valueClass);410startOffset += J9CLASS_PREPADDING_SIZE(valueClass);411412return (0 == memcmp((void*)((UDATA)lhsObject + startOffset), (void*)((UDATA)rhsObject + startOffset), (size_t)compareSize));413}414#endif /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */415}416417/**418* Copy valueType from sourceObject to destObject419* See MM_ObjectAccessBarrier::copyObjectFields for detailed description420*421* @param vmThread vmthread token422* @param valueClass The valueType class423* @param srcObject The object being used.424* @param srcOffset The offset of the field.425* @param destObject The object being used.426* @param destOffset The offset of the field.427*/428VMINLINE void429copyObjectFields(J9VMThread *vmThread, J9Class *objectClass, j9object_t srcObject, UDATA srcOffset, j9object_t destObject, UDATA destOffset)430{431#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)432vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_copyObjectFields(vmThread, objectClass, srcObject, srcOffset, destObject, destOffset);433#else /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */434bool hasReferences = J9CLASS_HAS_REFERENCES(objectClass);435if (hasReferences && ((j9gc_modron_readbar_none != _readBarrierType) || (j9gc_modron_wrtbar_always == _writeBarrierType))) {436vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_copyObjectFields(vmThread, objectClass, srcObject, srcOffset, destObject, destOffset);437} else {438UDATA offset = 0;439UDATA limit = mixedObjectGetDataSize(objectClass);440441if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {442while (offset < limit) {443*(uint32_t*)((UDATA)destObject + offset + destOffset) = *(uint32_t*)((UDATA)srcObject + offset + srcOffset);444offset += sizeof(uint32_t);445}446} else {447while (offset < limit) {448*(uintptr_t*)((UDATA)destObject + offset + destOffset) = *(uintptr_t*)((UDATA)srcObject + offset + srcOffset);449offset += sizeof(uintptr_t);450}451}452453/* zero lockword, if present */454j9objectmonitor_t *lockwordAddress = getLockwordAddress(vmThread, destObject);455if (NULL != lockwordAddress) {456J9_STORE_LOCKWORD(vmThread, lockwordAddress, 0);457}458if (hasReferences) {459postBatchStoreObject(vmThread, destObject);460}461}462#endif /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */463}464465/**466* Read an object field: perform any pre-use barriers, calculate an effective address467* and perform the work.468*469* @param srcObject The object being used.470* @param srcOffset The offset of the field.471* @param isVolatile non-zero if the field is volatile.472* @return result The object stored at srcOffset in srcObject473*/474VMINLINE j9object_t475inlineMixedObjectReadObject(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, bool isVolatile = false)476{477#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)478return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectReadObject(vmThread, srcObject, srcOffset, isVolatile);479#elif defined(J9VM_GC_COMBINATION_SPEC)480fj9object_t *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, fj9object_t);481482preMixedObjectReadObject(vmThread, srcObject, actualAddress);483484protectIfVolatileBefore(isVolatile, true);485j9object_t result = readObjectImpl(vmThread, actualAddress, isVolatile);486protectIfVolatileAfter(isVolatile, true);487488return result;489#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */490#error unsupported barrier491#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */492}493494/**495* Store an object pointer into an object.496*497* This function performs all of the necessary barriers and calls OOL when it can not handle498* the barrier itself.499*500* @param srcObject the object being stored into501* @param srcOffset the offset with in srcObject to store value502* @param value the value to be stored503* @param isVolatile non-zero if the field is volatile, zero otherwise504*/505VMINLINE void506inlineMixedObjectStoreObject(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, j9object_t value, bool isVolatile = false)507{508#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)509vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreObject(vmThread, srcObject, srcOffset, value, isVolatile);510#elif defined(J9VM_GC_COMBINATION_SPEC)511if (j9gc_modron_wrtbar_always == _writeBarrierType) {512vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreObject(vmThread, srcObject, srcOffset, value, isVolatile);513} else {514fj9object_t *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, fj9object_t);515516preMixedObjectStoreObject(vmThread, srcObject, actualAddress, value);517518protectIfVolatileBefore(isVolatile, false);519storeObjectImpl(vmThread, actualAddress, value, isVolatile);520protectIfVolatileAfter(isVolatile, false);521522postMixedObjectStoreObject(vmThread, srcObject, actualAddress, value);523}524#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */525#error unsupported barrier526#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */527}528529/**530* Store an object pointer into an object atomically.531*532* This function performs all of the necessary barriers and calls OOL when it can not handle533* the barrier itself.534*535* @param destObject the object being stored into536* @param destOffset the offset with in srcObject to store value537* @param compareObject the object to compare with538* @param swapObject the value to be swapped in539* @param isVolatile non-zero if the field is volatile, zero otherwise540*541* @return true on success, false otherwise542*/543VMINLINE bool544inlineMixedObjectCompareAndSwapObject(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)545{546fj9object_t *destAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, fj9object_t);547548#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)549return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndSwapObject(vmThread, destObject, (J9Object **)destAddress, compareObject, swapObject));550#elif defined(J9VM_GC_COMBINATION_SPEC)551if (j9gc_modron_wrtbar_always == _writeBarrierType) {552return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndSwapObject(vmThread, destObject, (J9Object **)destAddress, compareObject, swapObject));553} else {554preMixedObjectReadObject(vmThread, destObject, destAddress);555preMixedObjectStoreObject(vmThread, destObject, destAddress, swapObject);556557protectIfVolatileBefore(isVolatile, false);558bool result = compareAndSwapObjectImpl(vmThread, destAddress, compareObject, swapObject, isVolatile);559protectIfVolatileAfter(isVolatile, false);560561if (result) {562postMixedObjectStoreObject(vmThread, destObject, destAddress, swapObject);563}564return result;565}566#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */567#error unsupported barrier568#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */569}570571/**572* Conditionally store an object pointer into an object atomically.573*574* This function performs all of the necessary barriers and calls OOL when it can not handle575* the barrier itself.576*577* @param destObject the object being stored into578* @param destOffset the offset with in srcObject to store value579* @param compareObject the object to compare with580* @param swapObject the value to be swapped in581* @param isVolatile non-zero if the field is volatile, zero otherwise582*583* @return the object stored in the object field before the update584*/585VMINLINE j9object_t586inlineMixedObjectCompareAndExchangeObject(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)587{588fj9object_t *destAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, fj9object_t);589590#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)591return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndExchangeObject(vmThread, destObject, (J9Object **)destAddress, compareObject, swapObject);592#elif defined(J9VM_GC_COMBINATION_SPEC)593if (j9gc_modron_wrtbar_always == _writeBarrierType) {594return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndExchangeObject(vmThread, destObject, (J9Object **)destAddress, compareObject, swapObject);595} else {596preMixedObjectReadObject(vmThread, destObject, destAddress);597preMixedObjectStoreObject(vmThread, destObject, destAddress, swapObject);598599protectIfVolatileBefore(isVolatile, false);600fj9object_t resultToken = compareAndExchangeObjectImpl(vmThread, destAddress, compareObject, swapObject, isVolatile);601protectIfVolatileAfter(isVolatile, false);602603j9object_t result = internalConvertPointerFromToken(resultToken);604605if (result == compareObject) {606postMixedObjectStoreObject(vmThread, destObject, destAddress, swapObject);607}608return result;609}610#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */611#error unsupported barrier612#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */613}614615/**616* Read an I_32 field: perform any pre-use barriers, calculate an effective address617* and perform the work.618*619* @param srcObject The object being used.620* @param srcOffset The offset of the field.621* @param isVolatile non-zero if the field is volatile.622*/623VMINLINE I_32624inlineMixedObjectReadI32(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, bool isVolatile = false)625{626#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)627return (I_32)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectReadI32(vmThread, srcObject, srcOffset, isVolatile);628#elif defined(J9VM_GC_COMBINATION_SPEC)629I_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, I_32);630631protectIfVolatileBefore(isVolatile, true);632I_32 result = readI32Impl(vmThread, actualAddress, isVolatile);633protectIfVolatileAfter(isVolatile, true);634635return result;636#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */637#error unsupported barrier638#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */639}640641/**642* Store an I_32 value into an object.643*644* This function performs all of the necessary barriers and calls OOL when it can not handle645* the barrier itself.646*647* @param srcObject the object being stored into648* @param srcOffset the offset with in srcObject to store value649* @param value the value to be stored650* @param isVolatile non-zero if the field is volatile, zero otherwise651*/652VMINLINE void653inlineMixedObjectStoreI32(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, I_32 value, bool isVolatile = false)654{655#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)656vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreI32(vmThread, srcObject, srcOffset, value, isVolatile);657#elif defined(J9VM_GC_COMBINATION_SPEC)658I_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, I_32);659660protectIfVolatileBefore(isVolatile, false);661storeI32Impl(vmThread, actualAddress, value, isVolatile);662protectIfVolatileAfter(isVolatile, false);663#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */664#error unsupported barrier665#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */666}667668/**669* Read a U_32 field: perform any pre-use barriers, calculate an effective address670* and perform the work.671*672* @param srcObject The object being used.673* @param srcOffset The offset of the field.674* @param isVolatile non-zero if the field is volatile.675*/676VMINLINE U_32677inlineMixedObjectReadU32(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, bool isVolatile = false)678{679#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)680return (U_32)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectReadU32(vmThread, srcObject, srcOffset, isVolatile);681#elif defined(J9VM_GC_COMBINATION_SPEC)682U_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, U_32);683684protectIfVolatileBefore(isVolatile, true);685U_32 result = readU32Impl(vmThread, actualAddress, isVolatile);686protectIfVolatileAfter(isVolatile, true);687688return result;689#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */690#error unsupported barrier691#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */692}693694/**695* Store an U_32 value into an object.696*697* This function performs all of the necessary barriers and calls OOL when it can not handle698* the barrier itself.699*700* @param srcObject the object being stored into701* @param srcOffset the offset with in srcObject to store value702* @param value the value to be stored703* @param isVolatile non-zero if the field is volatile, zero otherwise704*/705VMINLINE void706inlineMixedObjectStoreU32(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, U_32 value, bool isVolatile = false)707{708#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)709vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreU32(vmThread, srcObject, srcOffset, value, isVolatile);710#elif defined(J9VM_GC_COMBINATION_SPEC)711U_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, U_32);712713protectIfVolatileBefore(isVolatile, false);714storeU32Impl(vmThread, actualAddress, value, isVolatile);715protectIfVolatileAfter(isVolatile, false);716#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */717#error unsupported barrier718#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */719}720721/**722* Store an U_32 value into an object atomically723*724* This function performs all of the necessary barriers and calls OOL when it can not handle725* the barrier itself.726*727* @param destObject the object being stored into728* @param destOffset the offset with in srcObject to store value729* @param compareObject the object to compare with730* @param swapObject the value to be swapped in731* @param isVolatile non-zero if the field is volatile, zero otherwise732*733* @return true on success, false otherwise734*/735VMINLINE bool736inlineMixedObjectCompareAndSwapU32(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, U_32 compareValue, U_32 swapValue, bool isVolatile = false)737{738#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)739return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectCompareAndSwapInt(vmThread, destObject, destOffset, compareValue, swapValue));740#elif defined(J9VM_GC_COMBINATION_SPEC)741U_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, U_32);742743protectIfVolatileBefore(isVolatile, false);744bool result = compareAndSwapU32Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);745protectIfVolatileAfter(isVolatile, false);746747return result;748#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */749#error unsupported barrier750#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */751}752753/**754* Conditionally store a U_32 value into an object atomically755*756* This function performs all of the necessary barriers and calls OOL when it can not handle757* the barrier itself.758*759* @param destObject the object being stored into760* @param destOffset the offset with in srcObject to store value761* @param compareObject the object to compare with762* @param swapObject the value to be swapped in763* @param isVolatile non-zero if the field is volatile, zero otherwise764*765* @return the value stored in the object field before the update766*/767VMINLINE U_32768inlineMixedObjectCompareAndExchangeU32(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, U_32 compareValue, U_32 swapValue, bool isVolatile = false)769{770#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)771return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectCompareAndExchangeInt(vmThread, destObject, destOffset, compareValue, swapValue);772#elif defined(J9VM_GC_COMBINATION_SPEC)773U_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, U_32);774775protectIfVolatileBefore(isVolatile, false);776U_32 result = compareAndExchangeU32Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);777protectIfVolatileAfter(isVolatile, false);778779return result;780#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */781#error unsupported barrier782#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */783}784785/**786* Read an I_64 field: perform any pre-use barriers, calculate an effective address787* and perform the work.788*789* @param srcObject The object being used.790* @param srcOffset The offset of the field.791* @param isVolatile non-zero if the field is volatile.792*/793VMINLINE I_64794inlineMixedObjectReadI64(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, bool isVolatile = false)795{796#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)797return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectReadI64(vmThread, srcObject, srcOffset, isVolatile);798#elif defined(J9VM_GC_COMBINATION_SPEC)799I_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, I_64);800801protectIfVolatileBefore(isVolatile, true);802I_64 result = readI64Impl(vmThread, actualAddress, isVolatile);803protectIfVolatileAfter(isVolatile, true);804805return result;806#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */807#error unsupported barrier808#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */809}810811/**812* Store an I_64 value into an object.813*814* This function performs all of the necessary barriers and calls OOL when it can not handle815* the barrier itself.816*817* @param srcObject the object being stored into818* @param srcOffset the offset with in srcObject to store value819* @param value the value to be stored820* @param isVolatile non-zero if the field is volatile, zero otherwise821*/822VMINLINE void823inlineMixedObjectStoreI64(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, I_64 value, bool isVolatile = false)824{825#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)826vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreI64(vmThread, srcObject, srcOffset, value, isVolatile);827#elif defined(J9VM_GC_COMBINATION_SPEC)828I_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, I_64);829830protectIfVolatileBefore(isVolatile, false);831storeI64Impl(vmThread, actualAddress, value, isVolatile);832protectIfVolatileAfter(isVolatile, false);833#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */834#error unsupported barrier835#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */836}837838/**839* Read a U_64 field: perform any pre-use barriers, calculate an effective address840* and perform the work.841*842* @param srcObject The object being used.843* @param srcOffset The offset of the field.844* @param isVolatile non-zero if the field is volatile.845*/846VMINLINE U_64847inlineMixedObjectReadU64(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, bool isVolatile = false)848{849#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)850return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectReadU64(vmThread, srcObject, srcOffset, isVolatile);851#elif defined(J9VM_GC_COMBINATION_SPEC)852U_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, U_64);853854protectIfVolatileBefore(isVolatile, true);855U_64 result = readU64Impl(vmThread, actualAddress, isVolatile);856protectIfVolatileAfter(isVolatile, true);857858return result;859#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */860#error unsupported barrier861#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */862}863864/**865* Store an U_64 value into an object.866*867* This function performs all of the necessary barriers and calls OOL when it can not handle868* the barrier itself.869*870* @param srcObject the object being stored into871* @param srcOffset the offset with in srcObject to store value872* @param value the value to be stored873* @param isVolatile non-zero if the field is volatile, zero otherwise874*/875VMINLINE void876inlineMixedObjectStoreU64(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, U_64 value, bool isVolatile = false)877{878#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)879vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreU64(vmThread, srcObject, srcOffset, value, isVolatile);880#elif defined(J9VM_GC_COMBINATION_SPEC)881U_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, U_64);882883protectIfVolatileBefore(isVolatile, false);884storeU64Impl(vmThread, actualAddress, value, isVolatile);885protectIfVolatileAfter(isVolatile, false);886#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */887#error unsupported barrier888#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */889}890891/**892* Store an U_64 value into an object atomically893*894* This function performs all of the necessary barriers and calls OOL when it can not handle895* the barrier itself.896*897* @param destObject the object being stored into898* @param destOffset the offset with in srcObject to store value899* @param compareObject the object to compare with900* @param swapObject the value to be swapped in901* @param isVolatile non-zero if the field is volatile, zero otherwise902*903* @return true on success, false otherwise904*/905VMINLINE bool906inlineMixedObjectCompareAndSwapU64(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, U_64 compareValue, U_64 swapValue, bool isVolatile = false)907{908#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)909return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectCompareAndSwapLong(vmThread, destObject, destOffset, compareValue, swapValue));910#elif defined(J9VM_GC_COMBINATION_SPEC)911U_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, U_64);912913protectIfVolatileBefore(isVolatile, false);914bool result = compareAndSwapU64Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);915protectIfVolatileAfter(isVolatile, false);916917return result;918#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */919#error unsupported barrier920#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */921}922923/**924* Conditionally store a U_64 value into an object atomically925*926* This function performs all of the necessary barriers and calls OOL when it can not handle927* the barrier itself.928*929* @param destObject the object being stored into930* @param destOffset the offset with in srcObject to store value931* @param compareObject the object to compare with932* @param swapObject the value to be swapped in933* @param isVolatile non-zero if the field is volatile, zero otherwise934*935* @return the value stored in the object field before the update936*/937VMINLINE U_64938inlineMixedObjectCompareAndExchangeU64(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, U_64 compareValue, U_64 swapValue, bool isVolatile = false)939{940#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)941return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectCompareAndExchangeLong(vmThread, destObject, destOffset, compareValue, swapValue);942#elif defined(J9VM_GC_COMBINATION_SPEC)943U_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, U_64);944945protectIfVolatileBefore(isVolatile, false);946U_64 result = compareAndExchangeU64Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);947protectIfVolatileAfter(isVolatile, false);948949return result;950#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */951#error unsupported barrier952#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */953}954955/**956* Read a static object field: perform any pre-use barriers, calculate an effective address957* and perform the work.958*959* @param clazz The J9Class being written to.960* @param srcAddress The offset of the field.961* @param isVolatile non-zero if the field is volatile.962*/963VMINLINE j9object_t964inlineStaticReadObject(J9VMThread *vmThread, J9Class *clazz, j9object_t *srcAddress, bool isVolatile = false)965{966#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)967return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticReadObject(vmThread, clazz, srcAddress, isVolatile);968#elif defined(J9VM_GC_COMBINATION_SPEC)969970preStaticReadObject(vmThread, clazz, srcAddress);971972protectIfVolatileBefore(isVolatile, true);973j9object_t result = staticReadObjectImpl(vmThread, srcAddress, isVolatile);974protectIfVolatileAfter(isVolatile, true);975976/* TODO handle postReadBarrier if RTJ every becomes combo */977978return result;979#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */980#error unsupported barrier981#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */982}983984/**985* Store an object value into a static.986*987* This function performs all of the necessary barriers and calls OOL when it can not handle988* the barrier itself.989*990* @param clazz the clazz whose static being stored into991* @param srcAddress the address of the static to store value992* @param value the value to be stored993* @param isVolatile non-zero if the field is volatile, zero otherwise994*/995VMINLINE void996inlineStaticStoreObject(J9VMThread *vmThread, J9Class *clazz, j9object_t *srcAddress, j9object_t value, bool isVolatile = false)997{998#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)999vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticStoreObject(vmThread, clazz, srcAddress, value, isVolatile);1000#elif defined(J9VM_GC_COMBINATION_SPEC)1001if (j9gc_modron_wrtbar_always == _writeBarrierType) {1002vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticStoreObject(vmThread, clazz, srcAddress, value, isVolatile);1003} else {1004j9object_t classObject = J9VM_J9CLASS_TO_HEAPCLASS(clazz);10051006preStaticStoreObject(vmThread, classObject, srcAddress, value);10071008protectIfVolatileBefore(isVolatile, false);1009staticStoreObjectImpl(vmThread, srcAddress, value, isVolatile);1010protectIfVolatileAfter(isVolatile, false);10111012postStaticStoreObject(vmThread, classObject, srcAddress, value);1013}1014#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1015#error unsupported barrier1016#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1017}10181019/**1020* Store an object value into a static atomically1021*1022* This function performs all of the necessary barriers and calls OOL when it can not handle1023* the barrier itself.1024*1025* @param clazz the clazz whose static being stored into1026* @param destAddress the address of the static to store value1027* @param compareObject the object to compare with1028* @param swapObject the value to be swapped in1029* @param isVolatile non-zero if the field is volatile, zero otherwise1030*1031* @return true on success, false otherwise1032*/1033VMINLINE bool1034inlineStaticCompareAndSwapObject(J9VMThread *vmThread, J9Class *clazz, j9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)1035{1036#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1037return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndSwapObject(vmThread, clazz, destAddress, compareObject, swapObject));1038#elif defined(J9VM_GC_COMBINATION_SPEC)1039if (j9gc_modron_wrtbar_always == _writeBarrierType) {1040return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndSwapObject(vmThread, clazz, destAddress, compareObject, swapObject));1041} else {1042j9object_t classObject = J9VM_J9CLASS_TO_HEAPCLASS(clazz);10431044preStaticReadObject(vmThread, clazz, destAddress);1045preStaticStoreObject(vmThread, classObject, destAddress, swapObject);10461047protectIfVolatileBefore(isVolatile, false);1048bool result = staticCompareAndSwapObjectImpl(vmThread, destAddress, compareObject, swapObject, isVolatile);1049protectIfVolatileAfter(isVolatile, false);10501051if (result) {1052postStaticStoreObject(vmThread, classObject, destAddress, swapObject);1053}1054return result;1055}1056#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1057#error unsupported barrier1058#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1059}10601061/**1062* Conditionally store an object value into a static atomically1063*1064* This function performs all of the necessary barriers and calls OOL when it can not handle1065* the barrier itself.1066*1067* @param clazz the clazz whose static being stored into1068* @param destAddress the address of the static to store value1069* @param compareObject the object to compare with1070* @param swapObject the value to be swapped in1071* @param isVolatile non-zero if the field is volatile, zero otherwise1072*1073* @return the object stored in the static field before the update1074*/1075VMINLINE j9object_t1076inlineStaticCompareAndExchangeObject(J9VMThread *vmThread, J9Class *clazz, j9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)1077{1078#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1079return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndExchangeObject(vmThread, clazz, destAddress, compareObject, swapObject);1080#elif defined(J9VM_GC_COMBINATION_SPEC)1081if (j9gc_modron_wrtbar_always == _writeBarrierType) {1082return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndExchangeObject(vmThread, clazz, destAddress, compareObject, swapObject);1083} else {1084j9object_t classObject = J9VM_J9CLASS_TO_HEAPCLASS(clazz);10851086preStaticReadObject(vmThread, clazz, destAddress);1087preStaticStoreObject(vmThread, classObject, destAddress, swapObject);10881089protectIfVolatileBefore(isVolatile, false);1090j9object_t result = staticCompareAndExchangeObjectImpl(vmThread, destAddress, compareObject, swapObject, isVolatile);1091protectIfVolatileAfter(isVolatile, false);10921093if (result == compareObject) {1094postStaticStoreObject(vmThread, classObject, destAddress, swapObject);1095}1096return result;1097}1098#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1099#error unsupported barrier1100#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1101}11021103/**1104* Read a static U_32 field: perform any pre-use barriers, calculate an effective address1105* and perform the work.1106*1107* @param clazz The J9Class being written to.1108* @param srcAddress The offset of the field.1109* @param isVolatile non-zero if the field is volatile.1110*/1111VMINLINE U_321112inlineStaticReadU32(J9VMThread *vmThread, J9Class *clazz, U_32 *srcAddress, bool isVolatile = false)1113{1114#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1115return (U_32)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticReadU32(vmThread, clazz, srcAddress, isVolatile);1116#elif defined(J9VM_GC_COMBINATION_SPEC)11171118protectIfVolatileBefore(isVolatile, true);1119U_32 result = readU32Impl(vmThread, srcAddress, isVolatile);1120protectIfVolatileAfter(isVolatile, true);11211122return result;1123#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1124#error unsupported barrier1125#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1126}11271128/**1129* Store a U_32 value into a static.1130*1131* This function performs all of the necessary barriers and calls OOL when it can not handle1132* the barrier itself.1133*1134* @param clazz the clazz whose static being stored into1135* @param srcAddress the address of the static to store value1136* @param value the value to be stored1137* @param isVolatile non-zero if the field is volatile, zero otherwise1138*/1139VMINLINE void1140inlineStaticStoreU32(J9VMThread *vmThread, J9Class *clazz, U_32 *srcAddress, U_32 value, bool isVolatile = false)1141{1142#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1143vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticStoreU32(vmThread, clazz, srcAddress, value, isVolatile);1144#elif defined(J9VM_GC_COMBINATION_SPEC)11451146protectIfVolatileBefore(isVolatile, false);1147storeU32Impl(vmThread, srcAddress, value, isVolatile);1148protectIfVolatileAfter(isVolatile, false);1149#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1150#error unsupported barrier1151#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1152}11531154/**1155* Store a U_32 value into a static atomically1156*1157* This function performs all of the necessary barriers and calls OOL when it can not handle1158* the barrier itself.1159*1160* @param clazz the clazz whose static being stored into1161* @param destAddress the address of the static to store value1162* @param compareObject the object to compare with1163* @param swapObject the value to be swapped in1164* @param isVolatile non-zero if the field is volatile, zero otherwise1165*1166* @return true on success, false otherwise1167*/1168VMINLINE bool1169inlineStaticCompareAndSwapU32(J9VMThread *vmThread, J9Class *clazz, U_32 *destAddress, U_32 compareValue, U_32 swapValue, bool isVolatile = false)1170{1171#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1172return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndSwapInt(vmThread, clazz, destAddress, compareValue, swapValue));1173#elif defined(J9VM_GC_COMBINATION_SPEC)11741175protectIfVolatileBefore(isVolatile, false);1176bool result = compareAndSwapU32Impl(vmThread, destAddress, compareValue, swapValue, isVolatile);1177protectIfVolatileAfter(isVolatile, false);11781179return result;1180#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1181#error unsupported barrier1182#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1183}11841185/**1186* Conditionally store a U_32 value into a static atomically1187*1188* This function performs all of the necessary barriers and calls OOL when it can not handle1189* the barrier itself.1190*1191* @param clazz the clazz whose static being stored into1192* @param destAddress the address of the static to store value1193* @param compareObject the object to compare with1194* @param swapObject the value to be swapped in1195* @param isVolatile non-zero if the field is volatile, zero otherwise1196*1197* @return the value stored in the static field before the update1198*/1199VMINLINE U_321200inlineStaticCompareAndExchangeU32(J9VMThread *vmThread, J9Class *clazz, U_32 *destAddress, U_32 compareValue, U_32 swapValue, bool isVolatile = false)1201{1202#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1203return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndExchangeInt(vmThread, clazz, destAddress, compareValue, swapValue);1204#elif defined(J9VM_GC_COMBINATION_SPEC)12051206protectIfVolatileBefore(isVolatile, false);1207U_32 result = compareAndExchangeU32Impl(vmThread, destAddress, compareValue, swapValue, isVolatile);1208protectIfVolatileAfter(isVolatile, false);12091210return result;1211#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1212#error unsupported barrier1213#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1214}12151216/**1217* Read static U_64 field: perform any pre-use barriers, calculate an effective address1218* and perform the work.1219* @param clazz The J9Class being written to.1220* @param srcAddress The offset of the field.1221* @param isVolatile non-zero if the field is volatile.1222*/1223VMINLINE U_641224inlineStaticReadU64(J9VMThread *vmThread, J9Class *clazz, U_64 *srcAddress, bool isVolatile = false)1225{1226#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1227return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticReadU64(vmThread, clazz, srcAddress, isVolatile);1228#elif defined(J9VM_GC_COMBINATION_SPEC)12291230protectIfVolatileBefore(isVolatile, true);1231U_64 result = readU64Impl(vmThread, srcAddress, isVolatile);1232protectIfVolatileAfter(isVolatile, true);12331234return result;1235#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1236#error unsupported barrier1237#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1238}12391240/**1241* Store a U_64 value into a static.1242*1243* This function performs all of the necessary barriers and calls OOL when it can not handle1244* the barrier itself.1245*1246* @param clazz the clazz whose static being stored into1247* @param srcAddress the address of the static to store value1248* @param value the value to be stored1249* @param isVolatile non-zero if the field is volatile, zero otherwise1250*/1251VMINLINE void1252inlineStaticStoreU64(J9VMThread *vmThread, J9Class *clazz, U_64 *srcAddress, U_64 value, bool isVolatile = false)1253{1254#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1255vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticStoreU64(vmThread, clazz, srcAddress, value, isVolatile);1256#elif defined(J9VM_GC_COMBINATION_SPEC)12571258protectIfVolatileBefore(isVolatile, false);1259storeU64Impl(vmThread, srcAddress, value, isVolatile);1260protectIfVolatileAfter(isVolatile, false);1261#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1262#error unsupported barrier1263#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1264}12651266/**1267* Store a U_64 value into a static atomically1268*1269* This function performs all of the necessary barriers and calls OOL when it can not handle1270* the barrier itself.1271*1272* @param clazz the clazz whose static being stored into1273* @param destAddress the address of the static to store value1274* @param compareObject the object to compare with1275* @param swapObject the value to be swapped in1276* @param isVolatile non-zero if the field is volatile, zero otherwise1277*1278* @return true on success, false otherwise1279*/1280VMINLINE bool1281inlineStaticCompareAndSwapU64(J9VMThread *vmThread, J9Class *clazz, U_64 *destAddress, U_64 compareValue, U_64 swapValue, bool isVolatile = false)1282{1283#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1284return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndSwapLong(vmThread, clazz, destAddress, compareValue, swapValue));1285#elif defined(J9VM_GC_COMBINATION_SPEC)12861287protectIfVolatileBefore(isVolatile, false);1288bool result = compareAndSwapU64Impl(vmThread, destAddress, compareValue, swapValue, isVolatile);1289protectIfVolatileAfter(isVolatile, false);12901291return result;1292#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1293#error unsupported barrier1294#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1295}12961297/**1298* Conditionally store a U_64 value into a static atomically1299*1300* This function performs all of the necessary barriers and calls OOL when it can not handle1301* the barrier itself.1302*1303* @param clazz the clazz whose static being stored into1304* @param destAddress the address of the static to store value1305* @param compareObject the object to compare with1306* @param swapObject the value to be swapped in1307* @param isVolatile non-zero if the field is volatile, zero otherwise1308*1309* @return the value stored in the static field before the update1310*/1311VMINLINE U_641312inlineStaticCompareAndExchangeU64(J9VMThread *vmThread, J9Class *clazz, U_64 *destAddress, U_64 compareValue, U_64 swapValue, bool isVolatile = false)1313{1314#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1315return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndExchangeLong(vmThread, clazz, destAddress, compareValue, swapValue));1316#elif defined(J9VM_GC_COMBINATION_SPEC)13171318protectIfVolatileBefore(isVolatile, false);1319U_64 result = compareAndExchangeU64Impl(vmThread, destAddress, compareValue, swapValue, isVolatile);1320protectIfVolatileAfter(isVolatile, false);13211322return result;1323#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1324#error unsupported barrier1325#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1326}13271328/**1329* Read an I_8 from an array.1330*1331* This function performs all of the necessary barriers and calls OOL when it can not handle1332* the barrier itself.1333*1334* @param srcArray the array being read from1335* @param srcIndex the index to be read1336*/1337VMINLINE I_81338inlineIndexableObjectReadI8(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)1339{1340#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1341return (I_8)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadI8(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);1342#elif defined(J9VM_GC_COMBINATION_SPEC)1343I_8 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_8);13441345protectIfVolatileBefore(isVolatile, true);1346I_8 result = readI8Impl(vmThread, actualAddress, isVolatile);1347protectIfVolatileAfter(isVolatile, true);13481349return result;1350#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1351#error unsupported barrier1352#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1353}13541355/**1356* Store a I_8 into an array1357*1358* This function performs all of the necessary barriers and calls OOL when it can not handle1359* the barrier itself.1360*1361* @param srcArray the array being stored to1362* @param srcIndex the index to be stored at1363* @param value the value being store1364*/1365VMINLINE void1366inlineIndexableObjectStoreI8(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, I_8 value, bool isVolatile = false)1367{1368#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1369vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreI8(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, (I_32)value, isVolatile);1370#elif defined(J9VM_GC_COMBINATION_SPEC)1371I_8 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_8);13721373protectIfVolatileBefore(isVolatile, false);1374storeI8Impl(vmThread, actualAddress, value, isVolatile);1375protectIfVolatileAfter(isVolatile, false);1376#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1377#error unsupported barrier1378#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1379}13801381/**1382* Read an U_8 from an array.1383*1384* This function performs all of the necessary barriers and calls OOL when it can not handle1385* the barrier itself.1386*1387* @param srcArray the array being read from1388* @param srcIndex the index to be read1389*/1390VMINLINE U_81391inlineIndexableObjectReadU8(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)1392{1393#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1394return (U_8)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadU8(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);1395#elif defined(J9VM_GC_COMBINATION_SPEC)1396U_8 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_8);13971398protectIfVolatileBefore(isVolatile, true);1399U_8 result = readU8Impl(vmThread, actualAddress, isVolatile);1400protectIfVolatileAfter(isVolatile, true);14011402return result;1403#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1404#error unsupported barrier1405#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1406}14071408/**1409* Store a U_8 into an array1410*1411* This function performs all of the necessary barriers and calls OOL when it can not handle1412* the barrier itself.1413*1414* @param srcArray the array being stored to1415* @param srcIndex the index to be stored at1416* @param value the value being store1417*/1418VMINLINE void1419inlineIndexableObjectStoreU8(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, U_8 value, bool isVolatile = false)1420{1421#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1422vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreU8(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);1423#elif defined(J9VM_GC_COMBINATION_SPEC)1424U_8 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_8);14251426protectIfVolatileBefore(isVolatile, false);1427storeU8Impl(vmThread, actualAddress, value, isVolatile);1428protectIfVolatileAfter(isVolatile, false);1429#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1430#error unsupported barrier1431#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1432}14331434/**1435* Read an I_16 from an array.1436*1437* This function performs all of the necessary barriers and calls OOL when it can not handle1438* the barrier itself.1439*1440* @param srcArray the array being read from1441* @param srcIndex the index to be read1442*/1443VMINLINE I_161444inlineIndexableObjectReadI16(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)1445{1446#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1447return (I_16)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadI16(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);1448#elif defined(J9VM_GC_COMBINATION_SPEC)1449I_16 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_16);14501451protectIfVolatileBefore(isVolatile, true);1452I_16 result = readI16Impl(vmThread, actualAddress, isVolatile);1453protectIfVolatileAfter(isVolatile, true);14541455return result;1456#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1457#error unsupported barrier1458#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1459}14601461/**1462* Store a I_16 into an array1463*1464* This function performs all of the necessary barriers and calls OOL when it can not handle1465* the barrier itself.1466*1467* @param srcArray the array being stored to1468* @param srcIndex the index to be stored at1469* @param value the value being store1470*/1471VMINLINE void1472inlineIndexableObjectStoreI16(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, I_16 value, bool isVolatile = false)1473{1474#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1475vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreI16(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);1476#elif defined(J9VM_GC_COMBINATION_SPEC)1477I_16 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_16);14781479protectIfVolatileBefore(isVolatile, false);1480storeI16Impl(vmThread, actualAddress, value, isVolatile);1481protectIfVolatileAfter(isVolatile, false);1482#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1483#error unsupported barrier1484#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1485}14861487/**1488* Read an U_16 from an array.1489*1490* This function performs all of the necessary barriers and calls OOL when it can not handle1491* the barrier itself.1492*1493* @param srcArray the array being read from1494* @param srcIndex the index to be read1495*/1496VMINLINE U_161497inlineIndexableObjectReadU16(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)1498{1499#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1500return (U_16)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadU16(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);1501#elif defined(J9VM_GC_COMBINATION_SPEC)1502U_16 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_16);15031504protectIfVolatileBefore(isVolatile, true);1505U_16 result = readU16Impl(vmThread, actualAddress, isVolatile);1506protectIfVolatileAfter(isVolatile, true);15071508return result;1509#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1510#error unsupported barrier1511#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1512}15131514/**1515* Store a U_16 into an array1516*1517* This function performs all of the necessary barriers and calls OOL when it can not handle1518* the barrier itself.1519*1520* @param srcArray the array being stored to1521* @param srcIndex the index to be stored at1522* @param value the value being store1523*/1524VMINLINE void1525inlineIndexableObjectStoreU16(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, U_16 value, bool isVolatile = false)1526{1527#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1528vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreU16(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);1529#elif defined(J9VM_GC_COMBINATION_SPEC)1530U_16 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_16);15311532protectIfVolatileBefore(isVolatile, false);1533storeU16Impl(vmThread, actualAddress, value, isVolatile);1534protectIfVolatileAfter(isVolatile, false);1535#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1536#error unsupported barrier1537#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1538}15391540/**1541* Read an I_32 from an array.1542*1543* This function performs all of the necessary barriers and calls OOL when it can not handle1544* the barrier itself.1545*1546* @param srcArray the array being read from1547* @param srcIndex the index to be read1548*/1549VMINLINE I_321550inlineIndexableObjectReadI32(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)1551{1552#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1553return (I_32)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadI32(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);1554#elif defined(J9VM_GC_COMBINATION_SPEC)1555I_32 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_32);15561557protectIfVolatileBefore(isVolatile, true);1558I_32 result = readI32Impl(vmThread, actualAddress, isVolatile);1559protectIfVolatileAfter(isVolatile, true);15601561return result;1562#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1563#error unsupported barrier1564#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1565}15661567/**1568* Store a I_32 into an array1569*1570* This function performs all of the necessary barriers and calls OOL when it can not handle1571* the barrier itself.1572*1573* @param srcArray the array being stored to1574* @param srcIndex the index to be stored at1575* @param value the value being store1576*/1577VMINLINE void1578inlineIndexableObjectStoreI32(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, I_32 value, bool isVolatile = false)1579{1580#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1581vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreI32(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);1582#elif defined(J9VM_GC_COMBINATION_SPEC)1583I_32 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_32);15841585protectIfVolatileBefore(isVolatile, false);1586storeI32Impl(vmThread, actualAddress, value, isVolatile);1587protectIfVolatileAfter(isVolatile, false);1588#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1589#error unsupported barrier1590#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1591}15921593/**1594* Read an U_32 from an array.1595*1596* This function performs all of the necessary barriers and calls OOL when it can not handle1597* the barrier itself.1598*1599* @param srcArray the array being read from1600* @param srcIndex the index to be read1601*/1602VMINLINE U_321603inlineIndexableObjectReadU32(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)1604{1605#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1606return (U_32)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadU32(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);1607#elif defined(J9VM_GC_COMBINATION_SPEC)1608U_32 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_32);16091610protectIfVolatileBefore(isVolatile, true);1611U_32 result = readU32Impl(vmThread, actualAddress, isVolatile);1612protectIfVolatileAfter(isVolatile, true);16131614return result;1615#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1616#error unsupported barrier1617#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1618}16191620/**1621* Store a U_32 into an array1622*1623* This function performs all of the necessary barriers and calls OOL when it can not handle1624* the barrier itself.1625*1626* @param srcArray the array being stored to1627* @param srcIndex the index to be stored at1628* @param value the value being store1629*/1630VMINLINE void1631inlineIndexableObjectStoreU32(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, U_32 value, bool isVolatile = false)1632{1633#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1634vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreI32(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);1635#elif defined(J9VM_GC_COMBINATION_SPEC)1636U_32 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_32);16371638protectIfVolatileBefore(isVolatile, false);1639storeU32Impl(vmThread, actualAddress, value, isVolatile);1640protectIfVolatileAfter(isVolatile, false);1641#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1642#error unsupported barrier1643#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1644}16451646/**1647* Store a U_32 into an array atomically1648*1649* This function performs all of the necessary barriers and calls OOL when it can not handle1650* the barrier itself.1651*1652* @param destArray the array being stored to1653* @param destIndex the index to be stored at1654* @param compareObject the object to compare with1655* @param swapObject the value to be swapped in1656* @param isVolatile non-zero if the field is volatile, zero otherwise1657*1658* @return true on success, false otherwise1659*/1660VMINLINE bool1661inlineIndexableObjectCompareAndSwapU32(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, U_32 compareValue, U_32 swapValue, bool isVolatile = false)1662{1663#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) || defined(J9VM_GC_COMBINATION_SPEC)1664U_32 *actualAddress = J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_32);16651666protectIfVolatileBefore(isVolatile, false);1667bool result = compareAndSwapU32Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);1668protectIfVolatileAfter(isVolatile, false);16691670return result;1671#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1672#error unsupported barrier1673#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1674}16751676/**1677* Conditionally store a U_32 into an array atomically1678*1679* This function performs all of the necessary barriers and calls OOL when it can not handle1680* the barrier itself.1681*1682* @param destArray the array being stored to1683* @param destIndex the index to be stored at1684* @param compareObject the object to compare with1685* @param swapObject the value to be swapped in1686* @param isVolatile non-zero if the field is volatile, zero otherwise1687*1688* @return the value stored in the array before the update1689*/1690VMINLINE U_321691inlineIndexableObjectCompareAndExchangeU32(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, U_32 compareValue, U_32 swapValue, bool isVolatile = false)1692{1693#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) || defined(J9VM_GC_COMBINATION_SPEC)1694U_32 *actualAddress = J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_32);16951696protectIfVolatileBefore(isVolatile, false);1697U_32 result = compareAndExchangeU32Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);1698protectIfVolatileAfter(isVolatile, false);16991700return result;1701#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1702#error unsupported barrier1703#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1704}17051706/**1707* Read an I_64 from an array.1708*1709* This function performs all of the necessary barriers and calls OOL when it can not handle1710* the barrier itself.1711*1712* @param srcArray the array being read from1713* @param srcIndex the index to be read1714*/1715VMINLINE I_641716inlineIndexableObjectReadI64(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)1717{1718#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1719return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadI64(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);1720#elif defined(J9VM_GC_COMBINATION_SPEC)1721I_64 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_64);17221723protectIfVolatileBefore(isVolatile, true);1724I_64 result = readI64Impl(vmThread, actualAddress, isVolatile);1725protectIfVolatileAfter(isVolatile, true);17261727return result;1728#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1729#error unsupported barrier1730#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1731}17321733/**1734* Store a I_64 into an array1735*1736* This function performs all of the necessary barriers and calls OOL when it can not handle1737* the barrier itself.1738*1739* @param srcArray the array being stored to1740* @param srcIndex the index to be stored at1741* @param value the value being store1742*/1743VMINLINE void1744inlineIndexableObjectStoreI64(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, I_64 value, bool isVolatile = false)1745{1746#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1747vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreI64(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);1748#elif defined(J9VM_GC_COMBINATION_SPEC)1749I_64 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_64);17501751protectIfVolatileBefore(isVolatile, false);1752storeI64Impl(vmThread, actualAddress, value, isVolatile);1753protectIfVolatileAfter(isVolatile, false);1754#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1755#error unsupported barrier1756#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1757}17581759/**1760* Read an U_64 from an array.1761*1762* This function performs all of the necessary barriers and calls OOL when it can not handle1763* the barrier itself.1764*1765* @param srcArray the array being read from1766* @param srcIndex the index to be read1767*/1768VMINLINE U_641769inlineIndexableObjectReadU64(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)1770{1771#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1772return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadU64(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);1773#elif defined(J9VM_GC_COMBINATION_SPEC)1774U_64 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_64);17751776protectIfVolatileBefore(isVolatile, true);1777U_64 result = readU64Impl(vmThread, actualAddress, isVolatile);1778protectIfVolatileAfter(isVolatile, true);17791780return result;1781#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1782#error unsupported barrier1783#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1784}17851786/**1787* Store a U_64 into an array1788*1789* This function performs all of the necessary barriers and calls OOL when it can not handle1790* the barrier itself.1791*1792* @param srcArray the array being stored to1793* @param srcIndex the index to be stored at1794* @param value the value being store1795*/1796VMINLINE void1797inlineIndexableObjectStoreU64(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, U_64 value, bool isVolatile = false)1798{1799#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1800vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreU64(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);1801#elif defined(J9VM_GC_COMBINATION_SPEC)1802U_64 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_64);18031804protectIfVolatileBefore(isVolatile, false);1805storeU64Impl(vmThread, actualAddress, value, isVolatile);1806protectIfVolatileAfter(isVolatile, false);1807#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1808#error unsupported barrier1809#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1810}18111812/**1813* Store a U_64 into an array atomically1814*1815* This function performs all of the necessary barriers and calls OOL when it can not handle1816* the barrier itself.1817*1818* @param destArray the array being stored to1819* @param destIndex the index to be stored at1820* @param compareObject the object to compare with1821* @param swapObject the value to be swapped in1822* @param isVolatile non-zero if the field is volatile, zero otherwise1823*1824* @return true on success, false otherwise1825*/1826VMINLINE bool1827inlineIndexableObjectCompareAndSwapU64(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, U_64 compareValue, U_64 swapValue, bool isVolatile = false)1828{1829#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) || defined(J9VM_GC_COMBINATION_SPEC)1830U_64 *actualAddress = J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_64);18311832protectIfVolatileBefore(isVolatile, false);1833bool result = compareAndSwapU64Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);1834protectIfVolatileAfter(isVolatile, false);18351836return result;1837#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1838#error unsupported barrier1839#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1840}18411842/**1843* Conditionally store a U_64 into an array atomically1844*1845* This function performs all of the necessary barriers and calls OOL when it can not handle1846* the barrier itself.1847*1848* @param destArray the array being stored to1849* @param destIndex the index to be stored at1850* @param compareObject the object to compare with1851* @param swapObject the value to be swapped in1852* @param isVolatile non-zero if the field is volatile, zero otherwise1853*1854* @return the value stored in the array before the update1855*/1856VMINLINE U_641857inlineIndexableObjectCompareAndExchangeU64(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, U_64 compareValue, U_64 swapValue, bool isVolatile = false)1858{1859#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) || defined(J9VM_GC_COMBINATION_SPEC)1860U_64 *actualAddress = J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_64);18611862protectIfVolatileBefore(isVolatile, false);1863U_64 result = compareAndExchangeU64Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);1864protectIfVolatileAfter(isVolatile, false);18651866return result;1867#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1868#error unsupported barrier1869#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1870}18711872/**1873* Read an object from an array.1874*1875* This function performs all of the necessary barriers and calls OOL when it can not handle1876* the barrier itself.1877*1878* @param srcArray the array being read from1879* @param srcIndex the index to be read1880*/1881VMINLINE j9object_t1882inlineIndexableObjectReadObject(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)1883{1884#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1885return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadObject(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);1886#elif defined(J9VM_GC_COMBINATION_SPEC)1887fj9object_t *actualAddress = NULL;1888if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {1889actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_32);1890} else {1891actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, UDATA);1892}18931894preIndexableObjectReadObject(vmThread, srcArray, actualAddress);18951896protectIfVolatileBefore(isVolatile, true);1897j9object_t result = readObjectImpl(vmThread, actualAddress, isVolatile);1898protectIfVolatileAfter(isVolatile, true);18991900return result;1901#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1902#error unsupported barrier1903#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1904}19051906/**1907* Store an object into an array1908*1909* This function performs all of the necessary barriers and calls OOL when it can not handle1910* the barrier itself.1911*1912* @param srcArray the array being stored to1913* @param srcIndex the index to be stored at1914* @param value the value being store1915*/1916VMINLINE void1917inlineIndexableObjectStoreObject(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, j9object_t value, bool isVolatile = false)1918{1919#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1920vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreObject(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);1921#elif defined(J9VM_GC_COMBINATION_SPEC)1922if (j9gc_modron_wrtbar_always == _writeBarrierType) {1923vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreObject(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);1924} else {1925fj9object_t *actualAddress = NULL;1926if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {1927actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_32);1928} else {1929actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, UDATA);1930}19311932preIndexableObjectStoreObject(vmThread, srcArray, actualAddress, value);19331934protectIfVolatileBefore(isVolatile, false);1935storeObjectImpl(vmThread, actualAddress, value, isVolatile);1936protectIfVolatileAfter(isVolatile, false);19371938postIndexableObjectStoreObject(vmThread, srcArray, actualAddress, value);1939}1940#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1941#error unsupported barrier1942#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1943}19441945/**1946* Store an object into an array atomically1947*1948* This function performs all of the necessary barriers and calls OOL when it can not handle1949* the barrier itself.1950*1951* @param destArray the array being stored to1952* @param destIndex the index to be stored at1953* @param compareObject the object to compare with1954* @param swapObject the value to be swapped in1955* @param isVolatile non-zero if the field is volatile, zero otherwise1956*1957* @return true on success, false otherwise1958*/1959VMINLINE bool1960inlineIndexableObjectCompareAndSwapObject(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)1961{1962fj9object_t *actualAddress = NULL;1963if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {1964actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_32);1965} else {1966actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, destArray, destIndex, UDATA);1967}19681969#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)1970return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndSwapObject(vmThread, destArray, (J9Object **)actualAddress, compareObject, swapObject));1971#elif defined(J9VM_GC_COMBINATION_SPEC)1972if (j9gc_modron_wrtbar_always == _writeBarrierType) {1973return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndSwapObject(vmThread, destArray, (J9Object **)actualAddress, compareObject, swapObject));1974} else {1975preIndexableObjectReadObject(vmThread, destArray, actualAddress);1976preIndexableObjectStoreObject(vmThread, destArray, actualAddress, swapObject);19771978protectIfVolatileBefore(isVolatile, false);1979bool result = compareAndSwapObjectImpl(vmThread, actualAddress, compareObject, swapObject, isVolatile);1980protectIfVolatileAfter(isVolatile, false);19811982if (result) {1983postIndexableObjectStoreObject(vmThread, destArray, actualAddress, swapObject);1984}1985return result;1986}1987#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1988#error unsupported barrier1989#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */1990}19911992/**1993* Conditionally store an object into an array atomically1994*1995* This function performs all of the necessary barriers and calls OOL when it can not handle1996* the barrier itself.1997*1998* @param destArray the array being stored to1999* @param destIndex the index to be stored at2000* @param compareObject the object to compare with2001* @param swapObject the value to be swapped in2002* @param isVolatile non-zero if the field is volatile, zero otherwise2003*2004* @return the object stored in the array before the update2005*/2006VMINLINE j9object_t2007inlineIndexableObjectCompareAndExchangeObject(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)2008{2009fj9object_t *actualAddress = NULL;2010if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {2011actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_32);2012} else {2013actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, destArray, destIndex, UDATA);2014}20152016#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)2017return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndExchangeObject(vmThread, destArray, (J9Object **)actualAddress, compareObject, swapObject);2018#elif defined(J9VM_GC_COMBINATION_SPEC)2019if (j9gc_modron_wrtbar_always == _writeBarrierType) {2020return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndExchangeObject(vmThread, destArray, (J9Object **)actualAddress, compareObject, swapObject);2021} else {2022preIndexableObjectReadObject(vmThread, destArray, actualAddress);2023preIndexableObjectStoreObject(vmThread, destArray, actualAddress, swapObject);20242025protectIfVolatileBefore(isVolatile, false);2026fj9object_t resultToken = compareAndExchangeObjectImpl(vmThread, actualAddress, compareObject, swapObject, isVolatile);2027protectIfVolatileAfter(isVolatile, false);20282029j9object_t result = internalConvertPointerFromToken(resultToken);20302031if (result == compareObject) {2032postIndexableObjectStoreObject(vmThread, destArray, actualAddress, swapObject);2033}2034return result;2035}2036#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */2037#error unsupported barrier2038#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */2039}20402041/* Return an j9object_t that can be stored in the constantpool.2042*2043* Not all collectors scan the constantpool on every GC and therefore for2044* these collectors the objects must be in tenure space.2045*2046* Note, the stack must be walkable as a GC may occur during this function.2047*2048* Note, this doesn't handle arrays.2049*2050* @param vmThread The current vmThread2051* @param toConvert The object to convert to a constantpool allowed form.2052*2053* @return an object that can be put in the constantpool or null if OOM.2054*/2055static VMINLINE j9object_t2056asConstantPoolObject(J9VMThread *vmThread, j9object_t toConvert, UDATA allocateFlags)2057{2058return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_asConstantPoolObject(vmThread, toConvert, allocateFlags);2059}20602061protected:20622063/**2064* Called before object references are stored into mixed objects to perform an prebarrier work.2065*2066* @param object - the object being stored into2067* @param destAddress - the address being stored into2068* @param value - the value being stored2069*2070*/2071VMINLINE void2072preMixedObjectStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)2073{2074internalPreStoreObject(vmThread, object, destAddress, value);2075}20762077/**2078* Called before object references are stored into arrays to perform an prebarrier work.2079*2080* @param object - the object being stored into2081* @param destAddress - the address being stored into2082* @param value - the value being stored2083*2084*/2085VMINLINE void2086preIndexableObjectStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)2087{2088internalPreStoreObject(vmThread, object, destAddress, value);2089}20902091/**2092* Called before object references are stored into class statics to perform an prebarrier work.2093*2094* @param dstClassObject - the class object being stored into2095* @param destAddress - the address being stored into2096* @param value - the value being stored2097*2098*/2099VMINLINE void2100preStaticStoreObject(J9VMThread *vmThread, j9object_t dstClassObject, j9object_t *destAddress, j9object_t value)2101{2102internalStaticPreStoreObject(vmThread, dstClassObject, destAddress, value);2103}21042105/**2106* Called after object references are stored into mixed objects to perform an postbarrier work.2107*2108* @param object - the object being stored into2109* @param destAddress - the address being stored into2110* @param value - the value being stored2111*2112*/2113VMINLINE void2114postMixedObjectStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)2115{2116internalPostStoreObject(vmThread, object, value);2117}21182119/**2120* Called after object references are stored into arrays to perform an postbarrier work.2121*2122* @param object - the object being stored into2123* @param destAddress - the address being stored into2124* @param value - the value being stored2125*2126*/2127VMINLINE void2128postIndexableObjectStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)2129{2130internalPostStoreObject(vmThread, object, value);2131}21322133/**2134* Called after object references are stored into class statics to perform an postbarrier work.2135*2136* @param object - the class object being stored into2137* @param destAddress - the address being stored into2138* @param value - the value being stored2139*2140*/2141VMINLINE void2142postStaticStoreObject(J9VMThread *vmThread, j9object_t object, j9object_t *destAddress, j9object_t value)2143{2144internalPostStoreObject(vmThread, object, value);2145}21462147VMINLINE void2148postBatchStoreObject(J9VMThread *vmThread, j9object_t object)2149{2150internalPostBatchStoreObject(vmThread, object);2151}21522153/**2154* Perform the preRead barrier for a reference slot within a mixed heap object2155*2156* @param object this is the heap object being read from2157* @param sreAddress the address of the slot being read2158*/2159VMINLINE void2160preMixedObjectReadObject(J9VMThread *vmThread, j9object_t object, fj9object_t *srcAddress)2161{2162internalPreReadObject(vmThread, object, srcAddress);2163}21642165/**2166* Perform the preRead barrier for a reference slot within an indexable heap object2167*2168* @param object this is the heap object being read from2169* @param sreAddress the address of the slot being read2170*/2171VMINLINE void2172preIndexableObjectReadObject(J9VMThread *vmThread, j9object_t object, fj9object_t *srcAddress)2173{2174internalPreReadObject(vmThread, object, srcAddress);2175}21762177/**2178* Read a non-object address (pointer to internal VM data) from an object.2179* This function is only concerned with moving the actual data. Do not re-implement2180* unless the value is stored in a non-native format (e.g. compressed object pointers).2181*2182* @param srcAddress the address of the field to be read2183* @param isVolatile non-zero if the field is volatile, zero otherwise2184*/2185VMINLINE void *2186readAddressImpl(J9VMThread *vmThread, void **srcAddress, bool isVolatile)2187{2188return *srcAddress;2189}21902191/**2192* Read a I_16 from an object.2193* This function is only concerned with moving the actual data. Do not re-implement2194* unless the value is stored in a non-native format (e.g. compressed object pointers).2195*2196* @param srcAddress the address of the field to be read2197* @param isVolatile non-zero if the field is volatile, zero otherwise2198*/2199VMINLINE I_162200readI16Impl(J9VMThread *vmThread, I_16 *srcAddress, bool isVolatile)2201{2202return *srcAddress;2203}22042205/**2206* Read a U_16 from an object.2207* This function is only concerned with moving the actual data. Do not re-implement2208* unless the value is stored in a non-native format (e.g. compressed object pointers).2209*2210* @param srcAddress the address of the field to be read2211* @param isVolatile non-zero if the field is volatile, zero otherwise2212*/2213VMINLINE U_162214readU16Impl(J9VMThread *vmThread, U_16 *srcAddress, bool isVolatile)2215{2216return *srcAddress;2217}22182219/**2220* Read a I_32 from an object.2221* This function is only concerned with moving the actual data. Do not re-implement2222* unless the value is stored in a non-native format (e.g. compressed object pointers).2223*2224* @param srcAddress the address of the field to be read2225* @param isVolatile non-zero if the field is volatile, zero otherwise2226*/2227VMINLINE I_322228readI32Impl(J9VMThread *vmThread, I_32 *srcAddress, bool isVolatile)2229{2230return *srcAddress;2231}22322233/**2234* Read a U_32 from an object.2235* This function is only concerned with moving the actual data. Do not re-implement2236* unless the value is stored in a non-native format (e.g. compressed object pointers).2237*2238* @param srcAddress the address of the field to be read2239* @param isVolatile non-zero if the field is volatile, zero otherwise2240*/2241VMINLINE U_322242readU32Impl(J9VMThread *vmThread, U_32 *srcAddress, bool isVolatile)2243{2244return *srcAddress;2245}22462247/**2248* Read a I_64 from an object.2249* This function is only concerned with moving the actual data. Do not re-implement2250* unless the value is stored in a non-native format (e.g. compressed object pointers).2251*2252* @param srcAddress the address of the field to be read2253* @param isVolatile non-zero if the field is volatile, zero otherwise2254*/2255VMINLINE I_642256readI64Impl(J9VMThread *vmThread, I_64 *srcAddress, bool isVolatile)2257{2258#if !defined(J9VM_ENV_DATA64)2259if (isVolatile) {2260return longVolatileRead(vmThread, (U_64 *)srcAddress);2261}2262#endif /* J9VM_ENV_DATA64 */2263return *srcAddress;2264}22652266/**2267* Read a U_64 from an object.2268* This function is only concerned with moving the actual data. Do not re-implement2269* unless the value is stored in a non-native format (e.g. compressed object pointers).2270*2271* @param srcAddress the address of the field to be read2272* @param isVolatile non-zero if the field is volatile, zero otherwise2273*/2274VMINLINE U_642275readU64Impl(J9VMThread *vmThread, U_64 *srcAddress, bool isVolatile)2276{2277#if !defined(J9VM_ENV_DATA64)2278if (isVolatile) {2279return longVolatileRead(vmThread, srcAddress);2280}2281#endif /* J9VM_ENV_DATA64 */2282return *srcAddress;2283}22842285/**2286* Read a I_8 from an object.2287* This function is only concerned with moving the actual data. Do not re-implement2288* unless the value is stored in a non-native format (e.g. compressed object pointers).2289*2290* @param srcAddress the address of the field to be read2291* @param isVolatile non-zero if the field is volatile, zero otherwise2292*/2293VMINLINE I_82294readI8Impl(J9VMThread *vmThread, I_8 *srcAddress, bool isVolatile)2295{2296return *srcAddress;2297}22982299/**2300* Read a U_8 from an object.2301* This function is only concerned with moving the actual data. Do not re-implement2302* unless the value is stored in a non-native format (e.g. compressed object pointers).2303*2304* @param srcAddress the address of the field to be read2305* @param isVolatile non-zero if the field is volatile, zero otherwise2306*/2307VMINLINE U_82308readU8Impl(J9VMThread *vmThread, U_8 *srcAddress, bool isVolatile)2309{2310return *srcAddress;2311}23122313/**2314* Read an object pointer from an object.2315* This function is only concerned with moving the actual data. Do not re-implement2316* unless the value is stored in a non-native format (e.g. compressed object pointers).2317*2318* @param srcAddress the address of the field to be read2319* @param isVolatile non-zero if the field is volatile, zero otherwise2320*/2321VMINLINE mm_j9object_t2322readObjectImpl(J9VMThread *vmThread, fj9object_t *srcAddress, bool isVolatile)2323{2324mm_j9object_t result = NULL;2325if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {2326result = internalConvertPointerFromToken((fj9object_t)(UDATA)*(U_32*)srcAddress);2327} else {2328result = (mm_j9object_t)*(UDATA*)srcAddress;2329}2330return result;2331}23322333/**2334* Called before reading a reference class static slot2335*2336* @param object - the class object being read from2337* @param srcAddress - the address the slot read from2338*/2339VMINLINE void2340preStaticReadObject(J9VMThread *vmThread, J9Class *clazz, j9object_t *srcAddress)2341{2342if (j9gc_modron_readbar_none != _readBarrierType) {2343vmThread->javaVM->memoryManagerFunctions->J9ReadBarrierClass(vmThread, srcAddress);2344}2345}234623472348/**2349* Read a static object field.2350* This function is only concerned with moving the actual data. Do not re-implement2351* unless the value is stored in a non-native format (e.g. compressed object pointers).2352*2353* @param srcAddress the address of the field to be read2354* @param isVolatile non-zero if the field is volatile, zero otherwise2355*/2356VMINLINE mm_j9object_t2357staticReadObjectImpl(J9VMThread *vmThread, j9object_t *srcAddress, bool isVolatile)2358{2359return *srcAddress;2360}23612362/**2363* Store a non-object address into an object.2364* This function is only concerned with moving the actual data. Do not re-implement2365* unless the value is stored in a non-native format (e.g. compressed object pointers).2366*2367* @param destAddress the address of the field to be read2368* @param value the value to be stored2369* @param isVolatile non-zero if the field is volatile, zero otherwise2370*/2371VMINLINE void2372storeAddressImpl(J9VMThread *vmThread, void **destAddress, void *value, bool isVolatile)2373{2374*destAddress = value;2375}23762377/**2378* Store a I_16 into an object.2379* This function is only concerned with moving the actual data. Do not re-implement2380* unless the value is stored in a non-native format (e.g. compressed object pointers).2381*2382* @param destAddress the address of the field to be read2383* @param value the value to be stored2384* @param isVolatile non-zero if the field is volatile, zero otherwise2385*/2386VMINLINE void2387storeI16Impl(J9VMThread *vmThread, I_16 *destAddress, I_16 value, bool isVolatile)2388{2389*destAddress = value;2390}23912392/**2393* Store a U_16 into an object.2394* This function is only concerned with moving the actual data. Do not re-implement2395* unless the value is stored in a non-native format (e.g. compressed object pointers).2396*2397* @param destAddress the address of the field to be read2398* @param value the value to be stored2399* @param isVolatile non-zero if the field is volatile, zero otherwise2400*/2401VMINLINE void2402storeU16Impl(J9VMThread *vmThread, U_16 *destAddress, U_16 value, bool isVolatile)2403{2404*destAddress = value;2405}24062407/**2408* Store a I_32 into an object.2409* This function is only concerned with moving the actual data. Do not re-implement2410* unless the value is stored in a non-native format (e.g. compressed object pointers).2411*2412* @param destAddress the address of the field to be read2413* @param value the value to be stored2414* @param isVolatile non-zero if the field is volatile, zero otherwise2415*/2416VMINLINE void2417storeI32Impl(J9VMThread *vmThread, I_32 *destAddress, I_32 value, bool isVolatile)2418{2419*destAddress = value;2420}24212422/**2423* Store a U_32 into an object.2424* This function is only concerned with moving the actual data. Do not re-implement2425* unless the value is stored in a non-native format (e.g. compressed object pointers).2426*2427* @param destAddress the address of the field to be read2428* @param value the value to be stored2429* @param isVolatile non-zero if the field is volatile, zero otherwise2430*/2431VMINLINE void2432storeU32Impl(J9VMThread *vmThread, U_32 *destAddress, U_32 value, bool isVolatile)2433{2434*destAddress = value;2435}24362437VMINLINE bool2438compareAndSwapU32Impl(J9VMThread *vmThread, U_32 *destAddress, U_32 compareValue, U_32 swapValue, bool isVolatile)2439{2440return (compareValue == VM_AtomicSupport::lockCompareExchangeU32(destAddress, compareValue, swapValue));2441}24422443VMINLINE U_322444compareAndExchangeU32Impl(J9VMThread *vmThread, U_32 *destAddress, U_32 compareValue, U_32 swapValue, bool isVolatile)2445{2446return VM_AtomicSupport::lockCompareExchangeU32(destAddress, compareValue, swapValue);2447}24482449/**2450* Store an I_64 into an object.2451* This function is only concerned with moving the actual data. Do not re-implement2452* unless the value is stored in a non-native format (e.g. compressed object pointers).2453*2454* @param destAddress the address of the field to be read2455* @param value the value to be stored2456* @param isVolatile non-zero if the field is volatile, zero otherwise2457*/2458VMINLINE void2459storeI64Impl(J9VMThread *vmThread, I_64 *destAddress, I_64 value, bool isVolatile)2460{2461#if !defined(J9VM_ENV_DATA64)2462if (isVolatile) {2463longVolatileWrite(vmThread, (U_64 *)destAddress, (U_64 *)&value);2464return;2465}2466#endif /* J9VM_ENV_DATA64 */2467*destAddress = value;2468}24692470/**2471* Store an U_64 into an object.2472* This function is only concerned with moving the actual data. Do not re-implement2473* unless the value is stored in a non-native format (e.g. compressed object pointers).2474*2475* @param destAddress the address of the field to be read2476* @param value the value to be stored2477* @param isVolatile non-zero if the field is volatile, zero otherwise2478*/2479VMINLINE void2480storeU64Impl(J9VMThread *vmThread, U_64 *destAddress, U_64 value, bool isVolatile)2481{2482#if !defined(J9VM_ENV_DATA64)2483if (isVolatile) {2484longVolatileWrite(vmThread, destAddress, &value);2485return;2486}2487#endif /* J9VM_ENV_DATA64 */2488*destAddress = value;2489}24902491VMINLINE bool2492compareAndSwapU64Impl(J9VMThread *vmThread, U_64 *destAddress, U_64 compareValue, U_64 swapValue, bool isVolatile)2493{2494return (compareValue == VM_AtomicSupport::lockCompareExchangeU64(destAddress, compareValue, swapValue));2495}24962497VMINLINE U_642498compareAndExchangeU64Impl(J9VMThread *vmThread, U_64 *destAddress, U_64 compareValue, U_64 swapValue, bool isVolatile)2499{2500return VM_AtomicSupport::lockCompareExchangeU64(destAddress, compareValue, swapValue);2501}25022503/**2504* Store a I_8 into an object.2505* This function is only concerned with moving the actual data. Do not re-implement2506* unless the value is stored in a non-native format (e.g. compressed object pointers).2507*2508* @param destAddress the address of the field to be read2509* @param value the value to be stored2510* @param isVolatile non-zero if the field is volatile, zero otherwise2511*/2512VMINLINE void2513storeI8Impl(J9VMThread *vmThread, I_8 *destAddress, I_8 value, bool isVolatile)2514{2515*destAddress = value;2516}25172518/**2519* Store a U_8 into an object.2520* This function is only concerned with moving the actual data. Do not re-implement2521* unless the value is stored in a non-native format (e.g. compressed object pointers).2522*2523* @param destAddress the address of the field to be read2524* @param value the value to be stored2525* @param isVolatile non-zero if the field is volatile, zero otherwise2526*/2527VMINLINE void2528storeU8Impl(J9VMThread *vmThread, U_8 *destAddress, U_8 value, bool isVolatile)2529{2530*destAddress = value;2531}25322533/**2534* Store an object pointer into an object.2535* This function is only concerned with moving the actual data. Do not re-implement2536*2537* @param destAddress the address of the field to be read2538* @param value the value to be stored2539* @param isVolatile non-zero if the field is volatile, zero otherwise2540*/2541VMINLINE void2542storeObjectImpl(J9VMThread *vmThread, fj9object_t *destAddress, mm_j9object_t value, bool isVolatile)2543{2544if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {2545*(U_32*)destAddress = (U_32)internalConvertTokenFromPointer(value);2546} else {2547*(UDATA*)destAddress = (UDATA)value;2548}2549}25502551VMINLINE bool2552compareAndSwapObjectImpl(J9VMThread *vmThread, fj9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile)2553{2554fj9object_t compareValue = internalConvertTokenFromPointer(compareObject);2555fj9object_t swapValue = internalConvertTokenFromPointer(swapObject);2556bool result = true;25572558if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {2559result = ((U_32)(UDATA)compareValue == VM_AtomicSupport::lockCompareExchangeU32((U_32 *)destAddress, (U_32)(UDATA)compareValue, (U_32)(UDATA)swapValue));2560} else {2561result = ((UDATA)compareValue == VM_AtomicSupport::lockCompareExchange((UDATA *)destAddress, (UDATA)compareValue, (UDATA)swapValue));2562}25632564return result;2565}25662567VMINLINE fj9object_t2568compareAndExchangeObjectImpl(J9VMThread *vmThread, fj9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile)2569{2570fj9object_t compareValue = internalConvertTokenFromPointer(compareObject);2571fj9object_t swapValue = internalConvertTokenFromPointer(swapObject);2572fj9object_t result = (fj9object_t)NULL;25732574if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {2575result = (fj9object_t)VM_AtomicSupport::lockCompareExchangeU32((U_32 *)destAddress, (U_32)(UDATA)compareValue, (U_32)(UDATA)swapValue);2576} else {2577result = (fj9object_t)VM_AtomicSupport::lockCompareExchange((UDATA *)destAddress, (UDATA)compareValue, (UDATA)swapValue);2578}25792580return result;2581}25822583/**2584* Store a static field.2585* This function is only concerned with moving the actual data. Do not re-implement2586*2587* @param destAddress the address of the field to be read2588* @param value the value to be stored2589* @param isVolatile non-zero if the field is volatile, zero otherwise2590*/2591VMINLINE void2592staticStoreObjectImpl(J9VMThread *vmThread, j9object_t *destAddress, mm_j9object_t value, bool isVolatile)2593{2594*destAddress = value;2595}25962597VMINLINE bool2598staticCompareAndSwapObjectImpl(J9VMThread *vmThread, j9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile)2599{2600return ((UDATA)compareObject == VM_AtomicSupport::lockCompareExchange((UDATA *)destAddress, (UDATA)compareObject, (UDATA)swapObject));2601}26022603VMINLINE j9object_t2604staticCompareAndExchangeObjectImpl(J9VMThread *vmThread, j9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile)2605{2606return (j9object_t)VM_AtomicSupport::lockCompareExchange((UDATA *)destAddress, (UDATA)compareObject, (UDATA)swapObject);2607}26082609/**2610* Call before a read or write of a possibly volatile field.2611*2612* @note This must be used in tandem with protectIfVolatileAfter()2613* @param isVolatile true if the field is volatile, false otherwise2614* @param isRead true if the field is being read, false if it is being written2615*/2616VMINLINE static void2617protectIfVolatileBefore(bool isVolatile, bool isRead)2618{2619if (isVolatile) {2620if (!isRead) {2621VM_AtomicSupport::writeBarrier();2622}2623}2624}26252626/**2627* Call after a read or write of a possibly volatile field.2628*2629* @note This must be used in tandem with protectIfVolatileBefore()2630* @param isVolatile true if the field is volatile, false otherwise2631* @param isRead true if the field is being read, false if it is being written2632*/2633VMINLINE static void2634protectIfVolatileAfter(bool isVolatile, bool isRead)2635{2636if (isVolatile) {2637if (isRead) {2638VM_AtomicSupport::readBarrier();2639} else {2640VM_AtomicSupport::readWriteBarrier();2641}2642}2643}26442645/**2646* Call to convert an object pointer to an object token2647*2648* @param pointer the object pointer to convert2649* @return the object token2650*/2651VMINLINE fj9object_t2652internalConvertTokenFromPointer(j9object_t pointer)2653{2654#if defined (OMR_GC_COMPRESSED_POINTERS)2655if (compressObjectReferences()) {2656return (fj9object_t)((UDATA)pointer >> _compressedPointersShift);2657} else2658#endif /* OMR_GC_COMPRESSED_POINTERS */2659{2660return (fj9object_t)(UDATA)pointer;2661}2662}26632664/**2665* Call to convert an object token to an object pointer2666*2667* @param token the object token to convert2668* @return the object pointer2669*/2670VMINLINE j9object_t2671internalConvertPointerFromToken(fj9object_t token)2672{2673#if defined (OMR_GC_COMPRESSED_POINTERS)2674if (compressObjectReferences()) {2675return (mm_j9object_t)((UDATA)token << _compressedPointersShift);2676} else2677#endif /* OMR_GC_COMPRESSED_POINTERS */2678{2679return (mm_j9object_t)(UDATA)token;2680}2681}26822683private:26842685/**2686* Perform the preStore barrier2687*2688* Currently pre store barriers are only required for WRT. Check the barrier type2689* and forward accordingly2690*2691* @param object this is the class object being stored into2692* @param destAddress the address being stored at2693* @param value the value being stored2694*2695*/2696VMINLINE void2697internalPreStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)2698{2699if ((j9gc_modron_wrtbar_satb == _writeBarrierType) ||2700(j9gc_modron_wrtbar_satb_and_oldcheck == _writeBarrierType)) {2701internalPreStoreObjectSATB(vmThread, object, destAddress, value);2702}2703}27042705/**2706* Perform the static preStore barrier2707*2708* Currently pre store barriers are only required for WRT. Check the barrier type2709* and forward accordingly2710*2711* @param dstClassObject this is the class object being stored into2712* @param destAddress the address being stored at2713* @param value the value being stored2714*2715*/2716VMINLINE void2717internalStaticPreStoreObject(J9VMThread *vmThread, j9object_t dstClassObject, j9object_t *destAddress, j9object_t value)2718{2719if ((j9gc_modron_wrtbar_satb == _writeBarrierType) ||2720(j9gc_modron_wrtbar_satb_and_oldcheck == _writeBarrierType)) {2721internalStaticPreStoreObjectSATB(vmThread, dstClassObject, destAddress, value);2722}2723}27242725/**2726* Perform the preStore barrier for WRT2727*2728* @param object this is the class object being stored into2729* @param destAddress the address being stored at2730* @param value the value being stored2731*2732*/2733VMINLINE void2734internalPreStoreObjectSATB(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)2735{2736#if defined(J9VM_GC_REALTIME)2737MM_GCRememberedSetFragment *fragment = &vmThread->sATBBarrierRememberedSetFragment;2738MM_GCRememberedSet *parent = fragment->fragmentParent;2739/* Check if the barrier is enabled. No work if barrier is not enabled */2740if (0 != parent->globalFragmentIndex) {2741/* if the double barrier is enabled call OOL */2742if (0 == fragment->localFragmentIndex) {2743vmThread->javaVM->memoryManagerFunctions->J9WriteBarrierPre(vmThread, object, destAddress, value);2744} else {2745j9object_t oldObject = readObjectImpl(vmThread, destAddress, false);2746if (NULL != oldObject) {2747if (!isMarked(vmThread, oldObject)) {2748vmThread->javaVM->memoryManagerFunctions->J9WriteBarrierPre(vmThread, object, destAddress, value);2749}2750}2751}2752}2753#endif /* J9VM_GC_REALTIME */2754}27552756/**2757* Perform the static preStore barrier for WRT2758*2759* @param dstClassObject this is the class object being stored into2760* @param destAddress the address being stored at2761* @param value the value being stored2762*2763*/2764VMINLINE void2765internalStaticPreStoreObjectSATB(J9VMThread *vmThread, j9object_t dstClassObject, j9object_t *destAddress, j9object_t value)2766{2767#if defined(J9VM_GC_REALTIME)2768MM_GCRememberedSetFragment *fragment = &vmThread->sATBBarrierRememberedSetFragment;2769MM_GCRememberedSet *parent = fragment->fragmentParent;2770/* Check if the barrier is enabled. No work if barrier is not enabled */2771if (0 != parent->globalFragmentIndex) {2772/* if the double barrier is enabled call OOL */2773if (0 == fragment->localFragmentIndex) {2774vmThread->javaVM->memoryManagerFunctions->J9WriteBarrierPreClass(vmThread, dstClassObject, destAddress, value);2775} else {2776j9object_t oldObject = *destAddress;2777if (NULL != oldObject) {2778if (!isMarked(vmThread, oldObject)) {2779vmThread->javaVM->memoryManagerFunctions->J9WriteBarrierPreClass(vmThread, dstClassObject, destAddress, value);2780}2781}2782}2783}2784#endif /* J9VM_GC_REALTIME */2785}27862787#if defined(J9VM_GC_REALTIME)2788/**2789* Check to see if the object is marked2790*2791* @NOTE only for SATB Concurrent Mark2792*2793* @param object to check2794* @return true if the object was marked, false otherwise2795*/2796VMINLINE bool2797isMarked(J9VMThread *vmThread, j9object_t object)2798{2799J9JavaVM *const javaVM = vmThread->javaVM;28002801if (J9_GC_POLICY_METRONOME == javaVM->gcPolicy) {2802UDATA heapMapBits = 0;2803UDATA heapDelta = (UDATA)object - javaVM->realtimeHeapMapBasePageRounded;2804UDATA slotIndex = heapDelta >> J9VMGC_SIZECLASSES_LOG_SMALLEST;2805UDATA bitIndex = slotIndex & J9_GC_MARK_MAP_UDATA_MASK;2806UDATA bitMask = ((UDATA)1) << bitIndex;2807slotIndex = slotIndex >> J9_GC_MARK_MAP_LOG_SIZEOF_UDATA;28082809UDATA *heapMapBitsBase = javaVM->realtimeHeapMapBits;2810heapMapBits = heapMapBitsBase[slotIndex];2811heapMapBits &= bitMask;28122813return 0 != heapMapBits;2814} else {2815/* TODO: Inline for SATB Standard Configuration */2816return 0 != javaVM->memoryManagerFunctions->j9gc_ext_is_marked(vmThread->javaVM, object);2817}2818}2819#endif /* J9VM_GC_REALTIME */282028212822/**2823* Call after storing an object reference2824*2825* @param object the object being stored into2826* @param value the object reference being stored2827*/2828VMINLINE void2829internalPostStoreObject(J9VMThread *vmThread, j9object_t object, j9object_t value)2830{2831switch(_writeBarrierType) {2832case j9gc_modron_wrtbar_cardmark_and_oldcheck:2833internalPostObjectStoreCardTableAndGenerational(vmThread, object, value);2834break;2835case j9gc_modron_wrtbar_oldcheck:2836internalPostObjectStoreGenerational(vmThread, object, value);2837break;2838case j9gc_modron_wrtbar_cardmark_incremental:2839internalPostObjectStoreCardTableIncremental(vmThread, object, value);2840break;2841case j9gc_modron_wrtbar_cardmark:2842internalPostObjectStoreCardTable(vmThread, object, value);2843break;2844case j9gc_modron_wrtbar_none:2845case j9gc_modron_wrtbar_satb:2846case j9gc_modron_wrtbar_satb_and_oldcheck:2847//TODO SATB change to handle gencon, decide where to do it in pre/post store2848break;2849default:2850/* Should assert as all real types are handled. Should never get here2851* with always or illegal2852*/2853break;2854}2855}28562857VMINLINE void2858internalPostBatchStoreObject(J9VMThread *vmThread, j9object_t object)2859{2860switch(_writeBarrierType) {2861case j9gc_modron_wrtbar_cardmark_and_oldcheck:2862internalPostBatchStoreObjectCardTableAndGenerational(vmThread, object);2863break;2864case j9gc_modron_wrtbar_oldcheck:2865internalPostBatchStoreObjectGenerational(vmThread, object);2866break;2867case j9gc_modron_wrtbar_cardmark_incremental:2868internalPostBatchStoreObjectCardTableIncremental(vmThread, object);2869break;2870case j9gc_modron_wrtbar_cardmark:2871internalPostBatchStoreObjectCardTable(vmThread, object);2872break;2873case j9gc_modron_wrtbar_none:2874case j9gc_modron_wrtbar_satb:2875case j9gc_modron_wrtbar_satb_and_oldcheck:2876break;2877default:2878/* Should assert as all real types are handled. Should never get here2879* with always or illegal2880*/2881break;2882}2883}28842885/**2886* Perform the preRead barrier for heap object reference slot2887* It's common API for both mixed and indexable objects2888*2889* @param object this is the heap object being read from2890* @param sreAddress the address of the slot being read2891*/2892VMINLINE void2893internalPreReadObject(J9VMThread *vmThread, j9object_t object, fj9object_t *srcAddress)2894{2895if (j9gc_modron_readbar_none != _readBarrierType) {2896vmThread->javaVM->memoryManagerFunctions->J9ReadBarrier(vmThread, srcAddress);2897}2898}28992900/**2901* Dirty the appropriate card for card table barriers2902*2903* @param objectDelta the delta from the object to heap start2904*2905*/2906static VMINLINE void2907dirtyCard(J9VMThread *vmThread, UDATA objectDelta)2908{2909/* calculate the delta with in the card table */2910UDATA shiftedDelta = objectDelta >> CARD_SIZE_SHIFT;29112912/* find the card and dirty it */2913U_8* card = (U_8*)vmThread->activeCardTableBase + shiftedDelta;2914*card = (U_8)CARD_DIRTY;2915}29162917/**2918* Add the object to the remembered set for generational barriers2919*2920* @param object the object to remember2921*2922*/2923static VMINLINE void2924rememberObject(J9VMThread *vmThread, j9object_t object)2925{2926#if defined (J9VM_GC_GENERATIONAL)2927if (atomicSetRemembered(vmThread, object)) {2928J9VMGCSublistFragment *fragment = &vmThread->gcRememberedSet;2929do {2930UDATA *slot = fragment->fragmentCurrent;2931UDATA *next = slot + 1;2932if (next > fragment->fragmentTop) {2933if (0 != vmThread->javaVM->memoryManagerFunctions->allocateMemoryForSublistFragment(vmThread->omrVMThread,(J9VMGC_SublistFragment*)fragment)) {2934break;2935}2936} else {2937fragment->fragmentCurrent = next;2938fragment->count += 1;2939*slot = (UDATA)object;2940break;2941}2942} while (true);2943}2944#endif /* J9VM_GC_GENERATIONAL */2945}29462947#if defined (J9VM_GC_GENERATIONAL)2948/**2949* Set the remembered but for the object pointer atomically2950*2951* @param object the object to set the remembered bit on2952* @return true if the bit was set, false otherwise2953*/2954static VMINLINE bool2955atomicSetRemembered(J9VMThread *currentThread, j9object_t objectPtr)2956{2957bool result = true;29582959if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(currentThread)) {2960volatile U_32* flagsPtr = &(((J9ObjectCompressed*)objectPtr)->clazz);2961U_32 oldFlags = 0;2962U_32 newFlags = 0;2963do {2964oldFlags = *flagsPtr;2965if((oldFlags & J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST) >= J9_OBJECT_HEADER_REMEMBERED_BITS_TO_SET) {2966/* Remembered state in age was set by somebody else */2967result = false;2968break;2969}2970newFlags = (oldFlags & ~J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_CLEAR) | J9_OBJECT_HEADER_REMEMBERED_BITS_TO_SET;2971} while (oldFlags != VM_AtomicSupport::lockCompareExchangeU32(flagsPtr, oldFlags, newFlags));2972} else {2973volatile UDATA* flagsPtr = &(((J9ObjectFull*)objectPtr)->clazz);2974UDATA oldFlags = 0;2975UDATA newFlags = 0;2976do {2977oldFlags = *flagsPtr;2978if((oldFlags & J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST) >= J9_OBJECT_HEADER_REMEMBERED_BITS_TO_SET) {2979/* Remembered state in age was set by somebody else */2980result = false;2981break;2982}2983newFlags = (oldFlags & ~J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_CLEAR) | J9_OBJECT_HEADER_REMEMBERED_BITS_TO_SET;2984} while (oldFlags != VM_AtomicSupport::lockCompareExchange(flagsPtr, oldFlags, newFlags));2985}29862987return result;2988}2989#endif /* J9VM_GC_GENERATIONAL */299029912992};29932994#endif /* OBJECTACCESSBARRIERAPI_HPP_ */299529962997