Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_include/ObjectAccessBarrierAPI.hpp
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2021 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* 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-exception
21
*******************************************************************************/
22
23
#if !defined(OBJECTACCESSBARRIERAPI_HPP_)
24
25
#define OBJECTACCESSBARRIERAPI_HPP_
26
27
#include "j9cfg.h"
28
29
#if defined(OMR_OVERRIDE_COMPRESS_OBJECT_REFERENCES)
30
#if OMR_OVERRIDE_COMPRESS_OBJECT_REFERENCES
31
#define MM_ObjectAccessBarrierAPI MM_ObjectAccessBarrierAPICompressed
32
#else /* OMR_OVERRIDE_COMPRESS_OBJECT_REFERENCES */
33
#define MM_ObjectAccessBarrierAPI MM_ObjectAccessBarrierAPIFull
34
#endif /* OMR_OVERRIDE_COMPRESS_OBJECT_REFERENCES */
35
#endif /* OMR_OVERRIDE_COMPRESS_OBJECT_REFERENCES */
36
37
#include "j9.h"
38
#include "j9modron.h"
39
#include "omrmodroncore.h"
40
#include "omr.h"
41
42
#include "AtomicSupport.hpp"
43
#include "ArrayCopyHelpers.hpp"
44
#include "j9nongenerated.h"
45
46
#define J9OAB_MIXEDOBJECT_EA(object, offset, type) (type *)(((U_8 *)(object)) + offset)
47
48
class MM_ObjectAccessBarrierAPI
49
{
50
friend class MM_ObjectAccessBarrier;
51
friend class MM_RealtimeAccessBarrier;
52
53
/* Data members & types */
54
public:
55
56
private:
57
const UDATA _writeBarrierType;
58
const UDATA _readBarrierType;
59
#if defined(OMR_GC_COMPRESSED_POINTERS)
60
const UDATA _compressedPointersShift;
61
#endif /* defined(OMR_GC_COMPRESSED_POINTERS) */
62
63
protected:
64
#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)
65
bool const _compressObjectReferences;
66
#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */
67
68
/* Methods */
69
public:
70
71
/**
72
* Create an instance.
73
*/
74
MM_ObjectAccessBarrierAPI(J9VMThread *currentThread)
75
: _writeBarrierType(currentThread->javaVM->gcWriteBarrierType)
76
, _readBarrierType(currentThread->javaVM->gcReadBarrierType)
77
#if defined(OMR_GC_COMPRESSED_POINTERS)
78
, _compressedPointersShift(currentThread->javaVM->compressedPointersShift)
79
#endif /* defined(OMR_GC_COMPRESSED_POINTERS) */
80
#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)
81
, _compressObjectReferences(J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(currentThread))
82
#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */
83
{}
84
85
/**
86
* Return back true if object references are compressed
87
* @return true, if object references are compressed
88
*/
89
MMINLINE bool compressObjectReferences() {
90
return OMR_COMPRESS_OBJECT_REFERENCES(_compressObjectReferences);
91
}
92
93
static VMINLINE void
94
internalPostBatchStoreObjectCardTableAndGenerational(J9VMThread *vmThread, j9object_t object)
95
{
96
/* Check to see if object is old. If object is not old neither barrier is required
97
* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old
98
*
99
* Since card dirtying also requires this calculation remember these values
100
*/
101
UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;
102
UDATA objectDelta = (UDATA)object - base;
103
UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;
104
if (objectDelta < size) {
105
/* object is old so check for concurrent barrier */
106
if (0 != (vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE)) {
107
/* concurrent barrier is enabled so dirty the card for object */
108
dirtyCard(vmThread, objectDelta);
109
}
110
111
/* generational barrier is required if object is old*/
112
rememberObject(vmThread, object);
113
}
114
}
115
116
static VMINLINE void
117
internalPostBatchStoreObjectGenerational(J9VMThread *vmThread, j9object_t object)
118
{
119
/* Check to see if object is old. If object is not old neither barrier is required
120
* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old
121
*
122
* Since card dirtying also requires this calculation remember these values
123
*/
124
UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;
125
UDATA objectDelta = (UDATA)object - base;
126
UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;
127
if (objectDelta < size) {
128
/* generational barrier is required if object is old*/
129
rememberObject(vmThread, object);
130
}
131
}
132
133
static VMINLINE void
134
internalPostBatchStoreObjectCardTableIncremental(J9VMThread *vmThread, j9object_t object)
135
{
136
/* Check to see if object is within the barrier range.
137
* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0)
138
*
139
* Since card dirtying also requires this calculation remember these values
140
*/
141
UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;
142
UDATA objectDelta = (UDATA)object - base;
143
UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;
144
if (objectDelta < size) {
145
/* Object is within the barrier range. Dirty the card */
146
dirtyCard(vmThread, objectDelta);
147
}
148
}
149
150
static VMINLINE void
151
internalPostBatchStoreObjectCardTable(J9VMThread *vmThread, j9object_t object)
152
{
153
/* Check to see if object is old. If object is not old neither barrier is required
154
* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old
155
*
156
* Since card dirtying also requires this calculation remember these values
157
*/
158
UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;
159
UDATA objectDelta = (UDATA)object - base;
160
UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;
161
if (objectDelta < size) {
162
/* object is old so check for concurrent barrier */
163
if (0 != (vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE)) {
164
/* concurrent barrier is enabled so dirty the card for object */
165
dirtyCard(vmThread, objectDelta);
166
}
167
}
168
}
169
170
/**
171
* Call after storing an object reference for barrier type
172
* j9gc_modron_wrtbar_cardmark_and_oldcheck
173
*
174
* @param object the object being stored into
175
* @param value the object reference being stored
176
*
177
*/
178
static VMINLINE void
179
internalPostObjectStoreCardTableAndGenerational(J9VMThread *vmThread, j9object_t object, j9object_t value)
180
{
181
/* if value is NULL neither barrier is required */
182
if (NULL != value) {
183
/* Check to see if object is old. If object is not old neither barrier is required
184
* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old
185
*
186
* Since card dirtying also requires this calculation remember these values
187
*/
188
UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;
189
UDATA objectDelta = (UDATA)object - base;
190
UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;
191
if (objectDelta < size) {
192
/* object is old so check for concurrent barrier */
193
if (0 != (vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE)) {
194
/* concurrent barrier is enabled so dirty the card for object */
195
dirtyCard(vmThread, objectDelta);
196
}
197
198
/* generational barrier is required if object is old and value is new */
199
/* Check to see if value is new using the same optimization as above */
200
UDATA valueDelta = (UDATA)value - base;
201
if (valueDelta >= size) {
202
/* value is in new space so do generational barrier */
203
rememberObject(vmThread, object);
204
}
205
}
206
}
207
}
208
209
/**
210
* Call after storing an object reference for barrier type
211
* j9gc_modron_wrtbar_cardmark
212
*
213
* @param object the object being stored into
214
* @param value the object reference being stored
215
*
216
*/
217
static VMINLINE void
218
internalPostObjectStoreCardTable(J9VMThread *vmThread, j9object_t object, j9object_t value)
219
{
220
/* if value is NULL neither barrier is required */
221
if (NULL != value) {
222
/* Check to see if object is old.
223
* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old
224
*
225
* Since card dirtying also requires this calculation remember these values
226
*/
227
UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;
228
UDATA objectDelta = (UDATA)object - base;
229
UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;
230
if (objectDelta < size) {
231
/* object is old so check for concurrent barrier */
232
if (0 != (vmThread->privateFlags & J9_PRIVATE_FLAGS_CONCURRENT_MARK_ACTIVE)) {
233
/* concurrent barrier is enabled so dirty the card for object */
234
dirtyCard(vmThread, objectDelta);
235
}
236
}
237
}
238
}
239
240
/**
241
* Call after storing an object reference for barrier type
242
* j9gc_modron_wrtbar_cardmark_incremental
243
*
244
* @param object the object being stored into
245
* @param value the object reference being stored
246
*
247
*/
248
static VMINLINE void
249
internalPostObjectStoreCardTableIncremental(J9VMThread *vmThread, j9object_t object, j9object_t value)
250
{
251
/* if value is NULL neither barrier is required */
252
if (NULL != value) {
253
/* Check to see if object is within the barrier range.
254
* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0)
255
*
256
* Since card dirtying also requires this calculation remember these values
257
*/
258
UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;
259
UDATA objectDelta = (UDATA)object - base;
260
UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;
261
if (objectDelta < size) {
262
/* Object is within the barrier range. Dirty the card */
263
dirtyCard(vmThread, objectDelta);
264
}
265
}
266
}
267
268
/**
269
* Call after storing an object reference for barrier type
270
* j9gc_modron_wrtbar_oldcheck
271
*
272
* @param object the object being stored into
273
* @param value the object reference being stored
274
*
275
*/
276
static VMINLINE void
277
internalPostObjectStoreGenerational(J9VMThread *vmThread, j9object_t object, j9object_t value)
278
{
279
/* if value is NULL neither barrier is required */
280
if (NULL != value) {
281
/* Check to see if object is old.
282
* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old
283
*
284
* Since card dirtying also requires this calculation remember these values
285
*/
286
UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;
287
UDATA objectDelta = (UDATA)object - base;
288
UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;
289
if (objectDelta < size) {
290
/* generational barrier is required if object is old and value is new */
291
/* Check to see if value is new using the same optimization as above */
292
UDATA valueDelta = (UDATA)value - base;
293
if (valueDelta >= size) {
294
/* value is in new space so do generational barrier */
295
rememberObject(vmThread, object);
296
}
297
}
298
}
299
}
300
301
/**
302
* Call after storing an object reference for barrier type
303
* j9gc_modron_wrtbar_oldcheck
304
*
305
* @param object the object being stored into
306
* @param value the object reference being stored
307
*
308
*/
309
static VMINLINE void
310
internalPostObjectStoreGenerationalNoValueCheck(J9VMThread *vmThread, j9object_t object)
311
{
312
/* Check to see if object is old.
313
* if ((object - vmThread->omrVMThread->heapBaseForBarrierRange0) < vmThread->omrVMThread->heapSizeForBarrierRange0) then old
314
*
315
* Since card dirtying also requires this calculation remember these values
316
*/
317
UDATA base = (UDATA)vmThread->omrVMThread->heapBaseForBarrierRange0;
318
UDATA objectDelta = (UDATA)object - base;
319
UDATA size = vmThread->omrVMThread->heapSizeForBarrierRange0;
320
if (objectDelta < size) {
321
rememberObject(vmThread, object);
322
}
323
}
324
325
/**
326
* Return the address of the lockword for the given object, or NULL if it
327
* does not have an inline lockword.
328
*/
329
VMINLINE j9objectmonitor_t *
330
getLockwordAddress(J9VMThread *currentThread, J9Object *object)
331
{
332
j9objectmonitor_t *lockwordAddress = NULL;
333
J9Class *clazz = J9OBJECT_CLAZZ(currentThread, object);
334
if (!J9_IS_J9CLASS_VALUETYPE(clazz)) {
335
UDATA lockOffset = clazz->lockOffset;
336
if ((IDATA) lockOffset >= 0) {
337
lockwordAddress = (j9objectmonitor_t *)(((U_8 *)object) + lockOffset);
338
}
339
}
340
return lockwordAddress;
341
}
342
343
VMINLINE void
344
cloneArray(J9VMThread *currentThread, j9object_t original, j9object_t copy, J9Class *objectClass, U_32 size)
345
{
346
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
347
currentThread->javaVM->memoryManagerFunctions->j9gc_objaccess_cloneIndexableObject(currentThread, (J9IndexableObject*)original, (J9IndexableObject*)copy);
348
#else /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */
349
bool copyLockword = true;
350
351
if (OBJECT_HEADER_SHAPE_POINTERS == J9CLASS_SHAPE(objectClass)) {
352
VM_ArrayCopyHelpers::referenceArrayCopy(currentThread, original, 0, copy, 0, size);
353
} else {
354
VM_ArrayCopyHelpers::primitiveArrayCopy(currentThread, original, 0, copy, 0, size, (((J9ROMArrayClass*)objectClass->romClass)->arrayShape & 0x0000FFFF));
355
}
356
if (copyLockword) {
357
/* zero lockword, if present */
358
j9objectmonitor_t *lockwordAddress = getLockwordAddress(currentThread, copy);
359
if (NULL != lockwordAddress) {
360
J9_STORE_LOCKWORD(currentThread, lockwordAddress, 0);
361
}
362
}
363
#endif /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */
364
}
365
366
VMINLINE UDATA
367
mixedObjectGetHeaderSize(J9Class *objectClass)
368
{
369
return (compressObjectReferences() ? sizeof(J9ObjectCompressed) : sizeof(J9ObjectFull)) + J9CLASS_PREPADDING_SIZE(objectClass);
370
}
371
372
VMINLINE UDATA
373
mixedObjectGetDataSize(J9Class *objectClass)
374
{
375
return J9CLASS_UNPADDED_INSTANCE_SIZE(objectClass);
376
}
377
378
VMINLINE void
379
cloneObject(J9VMThread *currentThread, j9object_t original, j9object_t copy, J9Class *objectClass)
380
{
381
UDATA offset = mixedObjectGetHeaderSize(objectClass);
382
383
copyObjectFields(currentThread, objectClass, original, offset, copy, offset);
384
}
385
386
VMINLINE void
387
copyObjectFieldsToFlattenedArrayElement(J9VMThread *vmThread, J9ArrayClass *arrayClazz, j9object_t srcObject, J9IndexableObject *arrayRef, UDATA index)
388
{
389
/* TODO optimizations for non-arraylet path will be added in the future */
390
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_copyObjectFieldsToFlattenedArrayElement(vmThread, arrayClazz, srcObject, arrayRef, (I_32)index);
391
}
392
393
VMINLINE void
394
copyObjectFieldsFromFlattenedArrayElement(J9VMThread *vmThread, J9ArrayClass *arrayClazz, j9object_t destObject, J9IndexableObject *arrayRef, UDATA index)
395
{
396
/* TODO optimizations for non-arraylet path will be added in the future */
397
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_copyObjectFieldsFromFlattenedArrayElement(vmThread, arrayClazz, destObject, arrayRef, (I_32)index);
398
}
399
400
VMINLINE BOOLEAN
401
structuralFlattenedCompareObjects(J9VMThread *vmThread, J9Class *valueClass, j9object_t lhsObject, j9object_t rhsObject, UDATA startOffset)
402
{
403
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
404
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_structuralCompareFlattenedObjects(vmThread, valueClass, lhsObject, rhsObject, startOffset);
405
#else /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */
406
bool hasReferences = J9CLASS_HAS_REFERENCES(valueClass);
407
if (hasReferences && (j9gc_modron_readbar_none != _readBarrierType)) {
408
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_structuralCompareFlattenedObjects(vmThread, valueClass, lhsObject, rhsObject, startOffset);
409
} else {
410
UDATA compareSize = mixedObjectGetDataSize(valueClass);
411
startOffset += J9CLASS_PREPADDING_SIZE(valueClass);
412
413
return (0 == memcmp((void*)((UDATA)lhsObject + startOffset), (void*)((UDATA)rhsObject + startOffset), (size_t)compareSize));
414
}
415
#endif /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */
416
}
417
418
/**
419
* Copy valueType from sourceObject to destObject
420
* See MM_ObjectAccessBarrier::copyObjectFields for detailed description
421
*
422
* @param vmThread vmthread token
423
* @param valueClass The valueType class
424
* @param srcObject The object being used.
425
* @param srcOffset The offset of the field.
426
* @param destObject The object being used.
427
* @param destOffset The offset of the field.
428
*/
429
VMINLINE void
430
copyObjectFields(J9VMThread *vmThread, J9Class *objectClass, j9object_t srcObject, UDATA srcOffset, j9object_t destObject, UDATA destOffset)
431
{
432
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
433
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_copyObjectFields(vmThread, objectClass, srcObject, srcOffset, destObject, destOffset);
434
#else /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */
435
bool hasReferences = J9CLASS_HAS_REFERENCES(objectClass);
436
if (hasReferences && ((j9gc_modron_readbar_none != _readBarrierType) || (j9gc_modron_wrtbar_always == _writeBarrierType))) {
437
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_copyObjectFields(vmThread, objectClass, srcObject, srcOffset, destObject, destOffset);
438
} else {
439
UDATA offset = 0;
440
UDATA limit = mixedObjectGetDataSize(objectClass);
441
442
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
443
while (offset < limit) {
444
*(uint32_t*)((UDATA)destObject + offset + destOffset) = *(uint32_t*)((UDATA)srcObject + offset + srcOffset);
445
offset += sizeof(uint32_t);
446
}
447
} else {
448
while (offset < limit) {
449
*(uintptr_t*)((UDATA)destObject + offset + destOffset) = *(uintptr_t*)((UDATA)srcObject + offset + srcOffset);
450
offset += sizeof(uintptr_t);
451
}
452
}
453
454
/* zero lockword, if present */
455
j9objectmonitor_t *lockwordAddress = getLockwordAddress(vmThread, destObject);
456
if (NULL != lockwordAddress) {
457
J9_STORE_LOCKWORD(vmThread, lockwordAddress, 0);
458
}
459
if (hasReferences) {
460
postBatchStoreObject(vmThread, destObject);
461
}
462
}
463
#endif /* defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) */
464
}
465
466
/**
467
* Read an object field: perform any pre-use barriers, calculate an effective address
468
* and perform the work.
469
*
470
* @param srcObject The object being used.
471
* @param srcOffset The offset of the field.
472
* @param isVolatile non-zero if the field is volatile.
473
* @return result The object stored at srcOffset in srcObject
474
*/
475
VMINLINE j9object_t
476
inlineMixedObjectReadObject(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, bool isVolatile = false)
477
{
478
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
479
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectReadObject(vmThread, srcObject, srcOffset, isVolatile);
480
#elif defined(J9VM_GC_COMBINATION_SPEC)
481
fj9object_t *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, fj9object_t);
482
483
preMixedObjectReadObject(vmThread, srcObject, actualAddress);
484
485
protectIfVolatileBefore(isVolatile, true);
486
j9object_t result = readObjectImpl(vmThread, actualAddress, isVolatile);
487
protectIfVolatileAfter(isVolatile, true);
488
489
return result;
490
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
491
#error unsupported barrier
492
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
493
}
494
495
/**
496
* Store an object pointer into an object.
497
*
498
* This function performs all of the necessary barriers and calls OOL when it can not handle
499
* the barrier itself.
500
*
501
* @param srcObject the object being stored into
502
* @param srcOffset the offset with in srcObject to store value
503
* @param value the value to be stored
504
* @param isVolatile non-zero if the field is volatile, zero otherwise
505
*/
506
VMINLINE void
507
inlineMixedObjectStoreObject(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, j9object_t value, bool isVolatile = false)
508
{
509
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
510
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreObject(vmThread, srcObject, srcOffset, value, isVolatile);
511
#elif defined(J9VM_GC_COMBINATION_SPEC)
512
if (j9gc_modron_wrtbar_always == _writeBarrierType) {
513
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreObject(vmThread, srcObject, srcOffset, value, isVolatile);
514
} else {
515
fj9object_t *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, fj9object_t);
516
517
preMixedObjectStoreObject(vmThread, srcObject, actualAddress, value);
518
519
protectIfVolatileBefore(isVolatile, false);
520
storeObjectImpl(vmThread, actualAddress, value, isVolatile);
521
protectIfVolatileAfter(isVolatile, false);
522
523
postMixedObjectStoreObject(vmThread, srcObject, actualAddress, value);
524
}
525
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
526
#error unsupported barrier
527
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
528
}
529
530
/**
531
* Store an object pointer into an object atomically.
532
*
533
* This function performs all of the necessary barriers and calls OOL when it can not handle
534
* the barrier itself.
535
*
536
* @param destObject the object being stored into
537
* @param destOffset the offset with in srcObject to store value
538
* @param compareObject the object to compare with
539
* @param swapObject the value to be swapped in
540
* @param isVolatile non-zero if the field is volatile, zero otherwise
541
*
542
* @return true on success, false otherwise
543
*/
544
VMINLINE bool
545
inlineMixedObjectCompareAndSwapObject(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)
546
{
547
fj9object_t *destAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, fj9object_t);
548
549
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
550
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndSwapObject(vmThread, destObject, (J9Object **)destAddress, compareObject, swapObject));
551
#elif defined(J9VM_GC_COMBINATION_SPEC)
552
if (j9gc_modron_wrtbar_always == _writeBarrierType) {
553
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndSwapObject(vmThread, destObject, (J9Object **)destAddress, compareObject, swapObject));
554
} else {
555
preMixedObjectReadObject(vmThread, destObject, destAddress);
556
preMixedObjectStoreObject(vmThread, destObject, destAddress, swapObject);
557
558
protectIfVolatileBefore(isVolatile, false);
559
bool result = compareAndSwapObjectImpl(vmThread, destAddress, compareObject, swapObject, isVolatile);
560
protectIfVolatileAfter(isVolatile, false);
561
562
if (result) {
563
postMixedObjectStoreObject(vmThread, destObject, destAddress, swapObject);
564
}
565
return result;
566
}
567
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
568
#error unsupported barrier
569
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
570
}
571
572
/**
573
* Conditionally store an object pointer into an object atomically.
574
*
575
* This function performs all of the necessary barriers and calls OOL when it can not handle
576
* the barrier itself.
577
*
578
* @param destObject the object being stored into
579
* @param destOffset the offset with in srcObject to store value
580
* @param compareObject the object to compare with
581
* @param swapObject the value to be swapped in
582
* @param isVolatile non-zero if the field is volatile, zero otherwise
583
*
584
* @return the object stored in the object field before the update
585
*/
586
VMINLINE j9object_t
587
inlineMixedObjectCompareAndExchangeObject(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)
588
{
589
fj9object_t *destAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, fj9object_t);
590
591
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
592
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndExchangeObject(vmThread, destObject, (J9Object **)destAddress, compareObject, swapObject);
593
#elif defined(J9VM_GC_COMBINATION_SPEC)
594
if (j9gc_modron_wrtbar_always == _writeBarrierType) {
595
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndExchangeObject(vmThread, destObject, (J9Object **)destAddress, compareObject, swapObject);
596
} else {
597
preMixedObjectReadObject(vmThread, destObject, destAddress);
598
preMixedObjectStoreObject(vmThread, destObject, destAddress, swapObject);
599
600
protectIfVolatileBefore(isVolatile, false);
601
fj9object_t resultToken = compareAndExchangeObjectImpl(vmThread, destAddress, compareObject, swapObject, isVolatile);
602
protectIfVolatileAfter(isVolatile, false);
603
604
j9object_t result = internalConvertPointerFromToken(resultToken);
605
606
if (result == compareObject) {
607
postMixedObjectStoreObject(vmThread, destObject, destAddress, swapObject);
608
}
609
return result;
610
}
611
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
612
#error unsupported barrier
613
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
614
}
615
616
/**
617
* Read an I_32 field: perform any pre-use barriers, calculate an effective address
618
* and perform the work.
619
*
620
* @param srcObject The object being used.
621
* @param srcOffset The offset of the field.
622
* @param isVolatile non-zero if the field is volatile.
623
*/
624
VMINLINE I_32
625
inlineMixedObjectReadI32(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, bool isVolatile = false)
626
{
627
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
628
return (I_32)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectReadI32(vmThread, srcObject, srcOffset, isVolatile);
629
#elif defined(J9VM_GC_COMBINATION_SPEC)
630
I_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, I_32);
631
632
protectIfVolatileBefore(isVolatile, true);
633
I_32 result = readI32Impl(vmThread, actualAddress, isVolatile);
634
protectIfVolatileAfter(isVolatile, true);
635
636
return result;
637
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
638
#error unsupported barrier
639
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
640
}
641
642
/**
643
* Store an I_32 value into an object.
644
*
645
* This function performs all of the necessary barriers and calls OOL when it can not handle
646
* the barrier itself.
647
*
648
* @param srcObject the object being stored into
649
* @param srcOffset the offset with in srcObject to store value
650
* @param value the value to be stored
651
* @param isVolatile non-zero if the field is volatile, zero otherwise
652
*/
653
VMINLINE void
654
inlineMixedObjectStoreI32(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, I_32 value, bool isVolatile = false)
655
{
656
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
657
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreI32(vmThread, srcObject, srcOffset, value, isVolatile);
658
#elif defined(J9VM_GC_COMBINATION_SPEC)
659
I_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, I_32);
660
661
protectIfVolatileBefore(isVolatile, false);
662
storeI32Impl(vmThread, actualAddress, value, isVolatile);
663
protectIfVolatileAfter(isVolatile, false);
664
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
665
#error unsupported barrier
666
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
667
}
668
669
/**
670
* Read a U_32 field: perform any pre-use barriers, calculate an effective address
671
* and perform the work.
672
*
673
* @param srcObject The object being used.
674
* @param srcOffset The offset of the field.
675
* @param isVolatile non-zero if the field is volatile.
676
*/
677
VMINLINE U_32
678
inlineMixedObjectReadU32(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, bool isVolatile = false)
679
{
680
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
681
return (U_32)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectReadU32(vmThread, srcObject, srcOffset, isVolatile);
682
#elif defined(J9VM_GC_COMBINATION_SPEC)
683
U_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, U_32);
684
685
protectIfVolatileBefore(isVolatile, true);
686
U_32 result = readU32Impl(vmThread, actualAddress, isVolatile);
687
protectIfVolatileAfter(isVolatile, true);
688
689
return result;
690
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
691
#error unsupported barrier
692
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
693
}
694
695
/**
696
* Store an U_32 value into an object.
697
*
698
* This function performs all of the necessary barriers and calls OOL when it can not handle
699
* the barrier itself.
700
*
701
* @param srcObject the object being stored into
702
* @param srcOffset the offset with in srcObject to store value
703
* @param value the value to be stored
704
* @param isVolatile non-zero if the field is volatile, zero otherwise
705
*/
706
VMINLINE void
707
inlineMixedObjectStoreU32(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, U_32 value, bool isVolatile = false)
708
{
709
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
710
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreU32(vmThread, srcObject, srcOffset, value, isVolatile);
711
#elif defined(J9VM_GC_COMBINATION_SPEC)
712
U_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, U_32);
713
714
protectIfVolatileBefore(isVolatile, false);
715
storeU32Impl(vmThread, actualAddress, value, isVolatile);
716
protectIfVolatileAfter(isVolatile, false);
717
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
718
#error unsupported barrier
719
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
720
}
721
722
/**
723
* Store an U_32 value into an object atomically
724
*
725
* This function performs all of the necessary barriers and calls OOL when it can not handle
726
* the barrier itself.
727
*
728
* @param destObject the object being stored into
729
* @param destOffset the offset with in srcObject to store value
730
* @param compareObject the object to compare with
731
* @param swapObject the value to be swapped in
732
* @param isVolatile non-zero if the field is volatile, zero otherwise
733
*
734
* @return true on success, false otherwise
735
*/
736
VMINLINE bool
737
inlineMixedObjectCompareAndSwapU32(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, U_32 compareValue, U_32 swapValue, bool isVolatile = false)
738
{
739
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
740
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectCompareAndSwapInt(vmThread, destObject, destOffset, compareValue, swapValue));
741
#elif defined(J9VM_GC_COMBINATION_SPEC)
742
U_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, U_32);
743
744
protectIfVolatileBefore(isVolatile, false);
745
bool result = compareAndSwapU32Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);
746
protectIfVolatileAfter(isVolatile, false);
747
748
return result;
749
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
750
#error unsupported barrier
751
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
752
}
753
754
/**
755
* Conditionally store a U_32 value into an object atomically
756
*
757
* This function performs all of the necessary barriers and calls OOL when it can not handle
758
* the barrier itself.
759
*
760
* @param destObject the object being stored into
761
* @param destOffset the offset with in srcObject to store value
762
* @param compareObject the object to compare with
763
* @param swapObject the value to be swapped in
764
* @param isVolatile non-zero if the field is volatile, zero otherwise
765
*
766
* @return the value stored in the object field before the update
767
*/
768
VMINLINE U_32
769
inlineMixedObjectCompareAndExchangeU32(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, U_32 compareValue, U_32 swapValue, bool isVolatile = false)
770
{
771
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
772
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectCompareAndExchangeInt(vmThread, destObject, destOffset, compareValue, swapValue);
773
#elif defined(J9VM_GC_COMBINATION_SPEC)
774
U_32 *actualAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, U_32);
775
776
protectIfVolatileBefore(isVolatile, false);
777
U_32 result = compareAndExchangeU32Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);
778
protectIfVolatileAfter(isVolatile, false);
779
780
return result;
781
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
782
#error unsupported barrier
783
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
784
}
785
786
/**
787
* Read an I_64 field: perform any pre-use barriers, calculate an effective address
788
* and perform the work.
789
*
790
* @param srcObject The object being used.
791
* @param srcOffset The offset of the field.
792
* @param isVolatile non-zero if the field is volatile.
793
*/
794
VMINLINE I_64
795
inlineMixedObjectReadI64(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, bool isVolatile = false)
796
{
797
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
798
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectReadI64(vmThread, srcObject, srcOffset, isVolatile);
799
#elif defined(J9VM_GC_COMBINATION_SPEC)
800
I_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, I_64);
801
802
protectIfVolatileBefore(isVolatile, true);
803
I_64 result = readI64Impl(vmThread, actualAddress, isVolatile);
804
protectIfVolatileAfter(isVolatile, true);
805
806
return result;
807
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
808
#error unsupported barrier
809
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
810
}
811
812
/**
813
* Store an I_64 value into an object.
814
*
815
* This function performs all of the necessary barriers and calls OOL when it can not handle
816
* the barrier itself.
817
*
818
* @param srcObject the object being stored into
819
* @param srcOffset the offset with in srcObject to store value
820
* @param value the value to be stored
821
* @param isVolatile non-zero if the field is volatile, zero otherwise
822
*/
823
VMINLINE void
824
inlineMixedObjectStoreI64(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, I_64 value, bool isVolatile = false)
825
{
826
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
827
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreI64(vmThread, srcObject, srcOffset, value, isVolatile);
828
#elif defined(J9VM_GC_COMBINATION_SPEC)
829
I_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, I_64);
830
831
protectIfVolatileBefore(isVolatile, false);
832
storeI64Impl(vmThread, actualAddress, value, isVolatile);
833
protectIfVolatileAfter(isVolatile, false);
834
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
835
#error unsupported barrier
836
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
837
}
838
839
/**
840
* Read a U_64 field: perform any pre-use barriers, calculate an effective address
841
* and perform the work.
842
*
843
* @param srcObject The object being used.
844
* @param srcOffset The offset of the field.
845
* @param isVolatile non-zero if the field is volatile.
846
*/
847
VMINLINE U_64
848
inlineMixedObjectReadU64(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, bool isVolatile = false)
849
{
850
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
851
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectReadU64(vmThread, srcObject, srcOffset, isVolatile);
852
#elif defined(J9VM_GC_COMBINATION_SPEC)
853
U_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, U_64);
854
855
protectIfVolatileBefore(isVolatile, true);
856
U_64 result = readU64Impl(vmThread, actualAddress, isVolatile);
857
protectIfVolatileAfter(isVolatile, true);
858
859
return result;
860
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
861
#error unsupported barrier
862
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
863
}
864
865
/**
866
* Store an U_64 value into an object.
867
*
868
* This function performs all of the necessary barriers and calls OOL when it can not handle
869
* the barrier itself.
870
*
871
* @param srcObject the object being stored into
872
* @param srcOffset the offset with in srcObject to store value
873
* @param value the value to be stored
874
* @param isVolatile non-zero if the field is volatile, zero otherwise
875
*/
876
VMINLINE void
877
inlineMixedObjectStoreU64(J9VMThread *vmThread, j9object_t srcObject, UDATA srcOffset, U_64 value, bool isVolatile = false)
878
{
879
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
880
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreU64(vmThread, srcObject, srcOffset, value, isVolatile);
881
#elif defined(J9VM_GC_COMBINATION_SPEC)
882
U_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(srcObject, srcOffset, U_64);
883
884
protectIfVolatileBefore(isVolatile, false);
885
storeU64Impl(vmThread, actualAddress, value, isVolatile);
886
protectIfVolatileAfter(isVolatile, false);
887
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
888
#error unsupported barrier
889
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
890
}
891
892
/**
893
* Store an U_64 value into an object atomically
894
*
895
* This function performs all of the necessary barriers and calls OOL when it can not handle
896
* the barrier itself.
897
*
898
* @param destObject the object being stored into
899
* @param destOffset the offset with in srcObject to store value
900
* @param compareObject the object to compare with
901
* @param swapObject the value to be swapped in
902
* @param isVolatile non-zero if the field is volatile, zero otherwise
903
*
904
* @return true on success, false otherwise
905
*/
906
VMINLINE bool
907
inlineMixedObjectCompareAndSwapU64(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, U_64 compareValue, U_64 swapValue, bool isVolatile = false)
908
{
909
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
910
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectCompareAndSwapLong(vmThread, destObject, destOffset, compareValue, swapValue));
911
#elif defined(J9VM_GC_COMBINATION_SPEC)
912
U_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, U_64);
913
914
protectIfVolatileBefore(isVolatile, false);
915
bool result = compareAndSwapU64Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);
916
protectIfVolatileAfter(isVolatile, false);
917
918
return result;
919
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
920
#error unsupported barrier
921
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
922
}
923
924
/**
925
* Conditionally store a U_64 value into an object atomically
926
*
927
* This function performs all of the necessary barriers and calls OOL when it can not handle
928
* the barrier itself.
929
*
930
* @param destObject the object being stored into
931
* @param destOffset the offset with in srcObject to store value
932
* @param compareObject the object to compare with
933
* @param swapObject the value to be swapped in
934
* @param isVolatile non-zero if the field is volatile, zero otherwise
935
*
936
* @return the value stored in the object field before the update
937
*/
938
VMINLINE U_64
939
inlineMixedObjectCompareAndExchangeU64(J9VMThread *vmThread, j9object_t destObject, UDATA destOffset, U_64 compareValue, U_64 swapValue, bool isVolatile = false)
940
{
941
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
942
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectCompareAndExchangeLong(vmThread, destObject, destOffset, compareValue, swapValue);
943
#elif defined(J9VM_GC_COMBINATION_SPEC)
944
U_64 *actualAddress = J9OAB_MIXEDOBJECT_EA(destObject, destOffset, U_64);
945
946
protectIfVolatileBefore(isVolatile, false);
947
U_64 result = compareAndExchangeU64Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);
948
protectIfVolatileAfter(isVolatile, false);
949
950
return result;
951
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
952
#error unsupported barrier
953
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
954
}
955
956
/**
957
* Read a static object field: perform any pre-use barriers, calculate an effective address
958
* and perform the work.
959
*
960
* @param clazz The J9Class being written to.
961
* @param srcAddress The offset of the field.
962
* @param isVolatile non-zero if the field is volatile.
963
*/
964
VMINLINE j9object_t
965
inlineStaticReadObject(J9VMThread *vmThread, J9Class *clazz, j9object_t *srcAddress, bool isVolatile = false)
966
{
967
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
968
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticReadObject(vmThread, clazz, srcAddress, isVolatile);
969
#elif defined(J9VM_GC_COMBINATION_SPEC)
970
971
preStaticReadObject(vmThread, clazz, srcAddress);
972
973
protectIfVolatileBefore(isVolatile, true);
974
j9object_t result = staticReadObjectImpl(vmThread, srcAddress, isVolatile);
975
protectIfVolatileAfter(isVolatile, true);
976
977
/* TODO handle postReadBarrier if RTJ every becomes combo */
978
979
return result;
980
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
981
#error unsupported barrier
982
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
983
}
984
985
/**
986
* Store an object value into a static.
987
*
988
* This function performs all of the necessary barriers and calls OOL when it can not handle
989
* the barrier itself.
990
*
991
* @param clazz the clazz whose static being stored into
992
* @param srcAddress the address of the static to store value
993
* @param value the value to be stored
994
* @param isVolatile non-zero if the field is volatile, zero otherwise
995
*/
996
VMINLINE void
997
inlineStaticStoreObject(J9VMThread *vmThread, J9Class *clazz, j9object_t *srcAddress, j9object_t value, bool isVolatile = false)
998
{
999
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1000
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticStoreObject(vmThread, clazz, srcAddress, value, isVolatile);
1001
#elif defined(J9VM_GC_COMBINATION_SPEC)
1002
if (j9gc_modron_wrtbar_always == _writeBarrierType) {
1003
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticStoreObject(vmThread, clazz, srcAddress, value, isVolatile);
1004
} else {
1005
j9object_t classObject = J9VM_J9CLASS_TO_HEAPCLASS(clazz);
1006
1007
preStaticStoreObject(vmThread, classObject, srcAddress, value);
1008
1009
protectIfVolatileBefore(isVolatile, false);
1010
staticStoreObjectImpl(vmThread, srcAddress, value, isVolatile);
1011
protectIfVolatileAfter(isVolatile, false);
1012
1013
postStaticStoreObject(vmThread, classObject, srcAddress, value);
1014
}
1015
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1016
#error unsupported barrier
1017
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1018
}
1019
1020
/**
1021
* Store an object value into a static atomically
1022
*
1023
* This function performs all of the necessary barriers and calls OOL when it can not handle
1024
* the barrier itself.
1025
*
1026
* @param clazz the clazz whose static being stored into
1027
* @param destAddress the address of the static to store value
1028
* @param compareObject the object to compare with
1029
* @param swapObject the value to be swapped in
1030
* @param isVolatile non-zero if the field is volatile, zero otherwise
1031
*
1032
* @return true on success, false otherwise
1033
*/
1034
VMINLINE bool
1035
inlineStaticCompareAndSwapObject(J9VMThread *vmThread, J9Class *clazz, j9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)
1036
{
1037
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1038
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndSwapObject(vmThread, clazz, destAddress, compareObject, swapObject));
1039
#elif defined(J9VM_GC_COMBINATION_SPEC)
1040
if (j9gc_modron_wrtbar_always == _writeBarrierType) {
1041
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndSwapObject(vmThread, clazz, destAddress, compareObject, swapObject));
1042
} else {
1043
j9object_t classObject = J9VM_J9CLASS_TO_HEAPCLASS(clazz);
1044
1045
preStaticReadObject(vmThread, clazz, destAddress);
1046
preStaticStoreObject(vmThread, classObject, destAddress, swapObject);
1047
1048
protectIfVolatileBefore(isVolatile, false);
1049
bool result = staticCompareAndSwapObjectImpl(vmThread, destAddress, compareObject, swapObject, isVolatile);
1050
protectIfVolatileAfter(isVolatile, false);
1051
1052
if (result) {
1053
postStaticStoreObject(vmThread, classObject, destAddress, swapObject);
1054
}
1055
return result;
1056
}
1057
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1058
#error unsupported barrier
1059
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1060
}
1061
1062
/**
1063
* Conditionally store an object value into a static atomically
1064
*
1065
* This function performs all of the necessary barriers and calls OOL when it can not handle
1066
* the barrier itself.
1067
*
1068
* @param clazz the clazz whose static being stored into
1069
* @param destAddress the address of the static to store value
1070
* @param compareObject the object to compare with
1071
* @param swapObject the value to be swapped in
1072
* @param isVolatile non-zero if the field is volatile, zero otherwise
1073
*
1074
* @return the object stored in the static field before the update
1075
*/
1076
VMINLINE j9object_t
1077
inlineStaticCompareAndExchangeObject(J9VMThread *vmThread, J9Class *clazz, j9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)
1078
{
1079
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1080
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndExchangeObject(vmThread, clazz, destAddress, compareObject, swapObject);
1081
#elif defined(J9VM_GC_COMBINATION_SPEC)
1082
if (j9gc_modron_wrtbar_always == _writeBarrierType) {
1083
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndExchangeObject(vmThread, clazz, destAddress, compareObject, swapObject);
1084
} else {
1085
j9object_t classObject = J9VM_J9CLASS_TO_HEAPCLASS(clazz);
1086
1087
preStaticReadObject(vmThread, clazz, destAddress);
1088
preStaticStoreObject(vmThread, classObject, destAddress, swapObject);
1089
1090
protectIfVolatileBefore(isVolatile, false);
1091
j9object_t result = staticCompareAndExchangeObjectImpl(vmThread, destAddress, compareObject, swapObject, isVolatile);
1092
protectIfVolatileAfter(isVolatile, false);
1093
1094
if (result == compareObject) {
1095
postStaticStoreObject(vmThread, classObject, destAddress, swapObject);
1096
}
1097
return result;
1098
}
1099
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1100
#error unsupported barrier
1101
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1102
}
1103
1104
/**
1105
* Read a static U_32 field: perform any pre-use barriers, calculate an effective address
1106
* and perform the work.
1107
*
1108
* @param clazz The J9Class being written to.
1109
* @param srcAddress The offset of the field.
1110
* @param isVolatile non-zero if the field is volatile.
1111
*/
1112
VMINLINE U_32
1113
inlineStaticReadU32(J9VMThread *vmThread, J9Class *clazz, U_32 *srcAddress, bool isVolatile = false)
1114
{
1115
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1116
return (U_32)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticReadU32(vmThread, clazz, srcAddress, isVolatile);
1117
#elif defined(J9VM_GC_COMBINATION_SPEC)
1118
1119
protectIfVolatileBefore(isVolatile, true);
1120
U_32 result = readU32Impl(vmThread, srcAddress, isVolatile);
1121
protectIfVolatileAfter(isVolatile, true);
1122
1123
return result;
1124
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1125
#error unsupported barrier
1126
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1127
}
1128
1129
/**
1130
* Store a U_32 value into a static.
1131
*
1132
* This function performs all of the necessary barriers and calls OOL when it can not handle
1133
* the barrier itself.
1134
*
1135
* @param clazz the clazz whose static being stored into
1136
* @param srcAddress the address of the static to store value
1137
* @param value the value to be stored
1138
* @param isVolatile non-zero if the field is volatile, zero otherwise
1139
*/
1140
VMINLINE void
1141
inlineStaticStoreU32(J9VMThread *vmThread, J9Class *clazz, U_32 *srcAddress, U_32 value, bool isVolatile = false)
1142
{
1143
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1144
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticStoreU32(vmThread, clazz, srcAddress, value, isVolatile);
1145
#elif defined(J9VM_GC_COMBINATION_SPEC)
1146
1147
protectIfVolatileBefore(isVolatile, false);
1148
storeU32Impl(vmThread, srcAddress, value, isVolatile);
1149
protectIfVolatileAfter(isVolatile, false);
1150
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1151
#error unsupported barrier
1152
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1153
}
1154
1155
/**
1156
* Store a U_32 value into a static atomically
1157
*
1158
* This function performs all of the necessary barriers and calls OOL when it can not handle
1159
* the barrier itself.
1160
*
1161
* @param clazz the clazz whose static being stored into
1162
* @param destAddress the address of the static to store value
1163
* @param compareObject the object to compare with
1164
* @param swapObject the value to be swapped in
1165
* @param isVolatile non-zero if the field is volatile, zero otherwise
1166
*
1167
* @return true on success, false otherwise
1168
*/
1169
VMINLINE bool
1170
inlineStaticCompareAndSwapU32(J9VMThread *vmThread, J9Class *clazz, U_32 *destAddress, U_32 compareValue, U_32 swapValue, bool isVolatile = false)
1171
{
1172
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1173
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndSwapInt(vmThread, clazz, destAddress, compareValue, swapValue));
1174
#elif defined(J9VM_GC_COMBINATION_SPEC)
1175
1176
protectIfVolatileBefore(isVolatile, false);
1177
bool result = compareAndSwapU32Impl(vmThread, destAddress, compareValue, swapValue, isVolatile);
1178
protectIfVolatileAfter(isVolatile, false);
1179
1180
return result;
1181
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1182
#error unsupported barrier
1183
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1184
}
1185
1186
/**
1187
* Conditionally store a U_32 value into a static atomically
1188
*
1189
* This function performs all of the necessary barriers and calls OOL when it can not handle
1190
* the barrier itself.
1191
*
1192
* @param clazz the clazz whose static being stored into
1193
* @param destAddress the address of the static to store value
1194
* @param compareObject the object to compare with
1195
* @param swapObject the value to be swapped in
1196
* @param isVolatile non-zero if the field is volatile, zero otherwise
1197
*
1198
* @return the value stored in the static field before the update
1199
*/
1200
VMINLINE U_32
1201
inlineStaticCompareAndExchangeU32(J9VMThread *vmThread, J9Class *clazz, U_32 *destAddress, U_32 compareValue, U_32 swapValue, bool isVolatile = false)
1202
{
1203
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1204
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndExchangeInt(vmThread, clazz, destAddress, compareValue, swapValue);
1205
#elif defined(J9VM_GC_COMBINATION_SPEC)
1206
1207
protectIfVolatileBefore(isVolatile, false);
1208
U_32 result = compareAndExchangeU32Impl(vmThread, destAddress, compareValue, swapValue, isVolatile);
1209
protectIfVolatileAfter(isVolatile, false);
1210
1211
return result;
1212
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1213
#error unsupported barrier
1214
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1215
}
1216
1217
/**
1218
* Read static U_64 field: perform any pre-use barriers, calculate an effective address
1219
* and perform the work.
1220
* @param clazz The J9Class being written to.
1221
* @param srcAddress The offset of the field.
1222
* @param isVolatile non-zero if the field is volatile.
1223
*/
1224
VMINLINE U_64
1225
inlineStaticReadU64(J9VMThread *vmThread, J9Class *clazz, U_64 *srcAddress, bool isVolatile = false)
1226
{
1227
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1228
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticReadU64(vmThread, clazz, srcAddress, isVolatile);
1229
#elif defined(J9VM_GC_COMBINATION_SPEC)
1230
1231
protectIfVolatileBefore(isVolatile, true);
1232
U_64 result = readU64Impl(vmThread, srcAddress, isVolatile);
1233
protectIfVolatileAfter(isVolatile, true);
1234
1235
return result;
1236
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1237
#error unsupported barrier
1238
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1239
}
1240
1241
/**
1242
* Store a U_64 value into a static.
1243
*
1244
* This function performs all of the necessary barriers and calls OOL when it can not handle
1245
* the barrier itself.
1246
*
1247
* @param clazz the clazz whose static being stored into
1248
* @param srcAddress the address of the static to store value
1249
* @param value the value to be stored
1250
* @param isVolatile non-zero if the field is volatile, zero otherwise
1251
*/
1252
VMINLINE void
1253
inlineStaticStoreU64(J9VMThread *vmThread, J9Class *clazz, U_64 *srcAddress, U_64 value, bool isVolatile = false)
1254
{
1255
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1256
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticStoreU64(vmThread, clazz, srcAddress, value, isVolatile);
1257
#elif defined(J9VM_GC_COMBINATION_SPEC)
1258
1259
protectIfVolatileBefore(isVolatile, false);
1260
storeU64Impl(vmThread, srcAddress, value, isVolatile);
1261
protectIfVolatileAfter(isVolatile, false);
1262
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1263
#error unsupported barrier
1264
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1265
}
1266
1267
/**
1268
* Store a U_64 value into a static atomically
1269
*
1270
* This function performs all of the necessary barriers and calls OOL when it can not handle
1271
* the barrier itself.
1272
*
1273
* @param clazz the clazz whose static being stored into
1274
* @param destAddress the address of the static to store value
1275
* @param compareObject the object to compare with
1276
* @param swapObject the value to be swapped in
1277
* @param isVolatile non-zero if the field is volatile, zero otherwise
1278
*
1279
* @return true on success, false otherwise
1280
*/
1281
VMINLINE bool
1282
inlineStaticCompareAndSwapU64(J9VMThread *vmThread, J9Class *clazz, U_64 *destAddress, U_64 compareValue, U_64 swapValue, bool isVolatile = false)
1283
{
1284
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1285
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndSwapLong(vmThread, clazz, destAddress, compareValue, swapValue));
1286
#elif defined(J9VM_GC_COMBINATION_SPEC)
1287
1288
protectIfVolatileBefore(isVolatile, false);
1289
bool result = compareAndSwapU64Impl(vmThread, destAddress, compareValue, swapValue, isVolatile);
1290
protectIfVolatileAfter(isVolatile, false);
1291
1292
return result;
1293
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1294
#error unsupported barrier
1295
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1296
}
1297
1298
/**
1299
* Conditionally store a U_64 value into a static atomically
1300
*
1301
* This function performs all of the necessary barriers and calls OOL when it can not handle
1302
* the barrier itself.
1303
*
1304
* @param clazz the clazz whose static being stored into
1305
* @param destAddress the address of the static to store value
1306
* @param compareObject the object to compare with
1307
* @param swapObject the value to be swapped in
1308
* @param isVolatile non-zero if the field is volatile, zero otherwise
1309
*
1310
* @return the value stored in the static field before the update
1311
*/
1312
VMINLINE U_64
1313
inlineStaticCompareAndExchangeU64(J9VMThread *vmThread, J9Class *clazz, U_64 *destAddress, U_64 compareValue, U_64 swapValue, bool isVolatile = false)
1314
{
1315
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1316
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_staticCompareAndExchangeLong(vmThread, clazz, destAddress, compareValue, swapValue));
1317
#elif defined(J9VM_GC_COMBINATION_SPEC)
1318
1319
protectIfVolatileBefore(isVolatile, false);
1320
U_64 result = compareAndExchangeU64Impl(vmThread, destAddress, compareValue, swapValue, isVolatile);
1321
protectIfVolatileAfter(isVolatile, false);
1322
1323
return result;
1324
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1325
#error unsupported barrier
1326
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1327
}
1328
1329
/**
1330
* Read an I_8 from an array.
1331
*
1332
* This function performs all of the necessary barriers and calls OOL when it can not handle
1333
* the barrier itself.
1334
*
1335
* @param srcArray the array being read from
1336
* @param srcIndex the index to be read
1337
*/
1338
VMINLINE I_8
1339
inlineIndexableObjectReadI8(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)
1340
{
1341
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1342
return (I_8)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadI8(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);
1343
#elif defined(J9VM_GC_COMBINATION_SPEC)
1344
I_8 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_8);
1345
1346
protectIfVolatileBefore(isVolatile, true);
1347
I_8 result = readI8Impl(vmThread, actualAddress, isVolatile);
1348
protectIfVolatileAfter(isVolatile, true);
1349
1350
return result;
1351
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1352
#error unsupported barrier
1353
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1354
}
1355
1356
/**
1357
* Store a I_8 into an array
1358
*
1359
* This function performs all of the necessary barriers and calls OOL when it can not handle
1360
* the barrier itself.
1361
*
1362
* @param srcArray the array being stored to
1363
* @param srcIndex the index to be stored at
1364
* @param value the value being store
1365
*/
1366
VMINLINE void
1367
inlineIndexableObjectStoreI8(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, I_8 value, bool isVolatile = false)
1368
{
1369
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1370
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreI8(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, (I_32)value, isVolatile);
1371
#elif defined(J9VM_GC_COMBINATION_SPEC)
1372
I_8 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_8);
1373
1374
protectIfVolatileBefore(isVolatile, false);
1375
storeI8Impl(vmThread, actualAddress, value, isVolatile);
1376
protectIfVolatileAfter(isVolatile, false);
1377
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1378
#error unsupported barrier
1379
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1380
}
1381
1382
/**
1383
* Read an U_8 from an array.
1384
*
1385
* This function performs all of the necessary barriers and calls OOL when it can not handle
1386
* the barrier itself.
1387
*
1388
* @param srcArray the array being read from
1389
* @param srcIndex the index to be read
1390
*/
1391
VMINLINE U_8
1392
inlineIndexableObjectReadU8(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)
1393
{
1394
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1395
return (U_8)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadU8(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);
1396
#elif defined(J9VM_GC_COMBINATION_SPEC)
1397
U_8 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_8);
1398
1399
protectIfVolatileBefore(isVolatile, true);
1400
U_8 result = readU8Impl(vmThread, actualAddress, isVolatile);
1401
protectIfVolatileAfter(isVolatile, true);
1402
1403
return result;
1404
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1405
#error unsupported barrier
1406
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1407
}
1408
1409
/**
1410
* Store a U_8 into an array
1411
*
1412
* This function performs all of the necessary barriers and calls OOL when it can not handle
1413
* the barrier itself.
1414
*
1415
* @param srcArray the array being stored to
1416
* @param srcIndex the index to be stored at
1417
* @param value the value being store
1418
*/
1419
VMINLINE void
1420
inlineIndexableObjectStoreU8(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, U_8 value, bool isVolatile = false)
1421
{
1422
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1423
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreU8(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);
1424
#elif defined(J9VM_GC_COMBINATION_SPEC)
1425
U_8 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_8);
1426
1427
protectIfVolatileBefore(isVolatile, false);
1428
storeU8Impl(vmThread, actualAddress, value, isVolatile);
1429
protectIfVolatileAfter(isVolatile, false);
1430
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1431
#error unsupported barrier
1432
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1433
}
1434
1435
/**
1436
* Read an I_16 from an array.
1437
*
1438
* This function performs all of the necessary barriers and calls OOL when it can not handle
1439
* the barrier itself.
1440
*
1441
* @param srcArray the array being read from
1442
* @param srcIndex the index to be read
1443
*/
1444
VMINLINE I_16
1445
inlineIndexableObjectReadI16(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)
1446
{
1447
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1448
return (I_16)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadI16(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);
1449
#elif defined(J9VM_GC_COMBINATION_SPEC)
1450
I_16 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_16);
1451
1452
protectIfVolatileBefore(isVolatile, true);
1453
I_16 result = readI16Impl(vmThread, actualAddress, isVolatile);
1454
protectIfVolatileAfter(isVolatile, true);
1455
1456
return result;
1457
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1458
#error unsupported barrier
1459
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1460
}
1461
1462
/**
1463
* Store a I_16 into an array
1464
*
1465
* This function performs all of the necessary barriers and calls OOL when it can not handle
1466
* the barrier itself.
1467
*
1468
* @param srcArray the array being stored to
1469
* @param srcIndex the index to be stored at
1470
* @param value the value being store
1471
*/
1472
VMINLINE void
1473
inlineIndexableObjectStoreI16(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, I_16 value, bool isVolatile = false)
1474
{
1475
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1476
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreI16(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);
1477
#elif defined(J9VM_GC_COMBINATION_SPEC)
1478
I_16 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_16);
1479
1480
protectIfVolatileBefore(isVolatile, false);
1481
storeI16Impl(vmThread, actualAddress, value, isVolatile);
1482
protectIfVolatileAfter(isVolatile, false);
1483
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1484
#error unsupported barrier
1485
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1486
}
1487
1488
/**
1489
* Read an U_16 from an array.
1490
*
1491
* This function performs all of the necessary barriers and calls OOL when it can not handle
1492
* the barrier itself.
1493
*
1494
* @param srcArray the array being read from
1495
* @param srcIndex the index to be read
1496
*/
1497
VMINLINE U_16
1498
inlineIndexableObjectReadU16(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)
1499
{
1500
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1501
return (U_16)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadU16(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);
1502
#elif defined(J9VM_GC_COMBINATION_SPEC)
1503
U_16 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_16);
1504
1505
protectIfVolatileBefore(isVolatile, true);
1506
U_16 result = readU16Impl(vmThread, actualAddress, isVolatile);
1507
protectIfVolatileAfter(isVolatile, true);
1508
1509
return result;
1510
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1511
#error unsupported barrier
1512
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1513
}
1514
1515
/**
1516
* Store a U_16 into an array
1517
*
1518
* This function performs all of the necessary barriers and calls OOL when it can not handle
1519
* the barrier itself.
1520
*
1521
* @param srcArray the array being stored to
1522
* @param srcIndex the index to be stored at
1523
* @param value the value being store
1524
*/
1525
VMINLINE void
1526
inlineIndexableObjectStoreU16(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, U_16 value, bool isVolatile = false)
1527
{
1528
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1529
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreU16(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);
1530
#elif defined(J9VM_GC_COMBINATION_SPEC)
1531
U_16 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_16);
1532
1533
protectIfVolatileBefore(isVolatile, false);
1534
storeU16Impl(vmThread, actualAddress, value, isVolatile);
1535
protectIfVolatileAfter(isVolatile, false);
1536
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1537
#error unsupported barrier
1538
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1539
}
1540
1541
/**
1542
* Read an I_32 from an array.
1543
*
1544
* This function performs all of the necessary barriers and calls OOL when it can not handle
1545
* the barrier itself.
1546
*
1547
* @param srcArray the array being read from
1548
* @param srcIndex the index to be read
1549
*/
1550
VMINLINE I_32
1551
inlineIndexableObjectReadI32(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)
1552
{
1553
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1554
return (I_32)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadI32(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);
1555
#elif defined(J9VM_GC_COMBINATION_SPEC)
1556
I_32 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_32);
1557
1558
protectIfVolatileBefore(isVolatile, true);
1559
I_32 result = readI32Impl(vmThread, actualAddress, isVolatile);
1560
protectIfVolatileAfter(isVolatile, true);
1561
1562
return result;
1563
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1564
#error unsupported barrier
1565
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1566
}
1567
1568
/**
1569
* Store a I_32 into an array
1570
*
1571
* This function performs all of the necessary barriers and calls OOL when it can not handle
1572
* the barrier itself.
1573
*
1574
* @param srcArray the array being stored to
1575
* @param srcIndex the index to be stored at
1576
* @param value the value being store
1577
*/
1578
VMINLINE void
1579
inlineIndexableObjectStoreI32(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, I_32 value, bool isVolatile = false)
1580
{
1581
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1582
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreI32(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);
1583
#elif defined(J9VM_GC_COMBINATION_SPEC)
1584
I_32 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_32);
1585
1586
protectIfVolatileBefore(isVolatile, false);
1587
storeI32Impl(vmThread, actualAddress, value, isVolatile);
1588
protectIfVolatileAfter(isVolatile, false);
1589
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1590
#error unsupported barrier
1591
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1592
}
1593
1594
/**
1595
* Read an U_32 from an array.
1596
*
1597
* This function performs all of the necessary barriers and calls OOL when it can not handle
1598
* the barrier itself.
1599
*
1600
* @param srcArray the array being read from
1601
* @param srcIndex the index to be read
1602
*/
1603
VMINLINE U_32
1604
inlineIndexableObjectReadU32(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)
1605
{
1606
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1607
return (U_32)vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadU32(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);
1608
#elif defined(J9VM_GC_COMBINATION_SPEC)
1609
U_32 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_32);
1610
1611
protectIfVolatileBefore(isVolatile, true);
1612
U_32 result = readU32Impl(vmThread, actualAddress, isVolatile);
1613
protectIfVolatileAfter(isVolatile, true);
1614
1615
return result;
1616
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1617
#error unsupported barrier
1618
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1619
}
1620
1621
/**
1622
* Store a U_32 into an array
1623
*
1624
* This function performs all of the necessary barriers and calls OOL when it can not handle
1625
* the barrier itself.
1626
*
1627
* @param srcArray the array being stored to
1628
* @param srcIndex the index to be stored at
1629
* @param value the value being store
1630
*/
1631
VMINLINE void
1632
inlineIndexableObjectStoreU32(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, U_32 value, bool isVolatile = false)
1633
{
1634
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1635
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreI32(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);
1636
#elif defined(J9VM_GC_COMBINATION_SPEC)
1637
U_32 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_32);
1638
1639
protectIfVolatileBefore(isVolatile, false);
1640
storeU32Impl(vmThread, actualAddress, value, isVolatile);
1641
protectIfVolatileAfter(isVolatile, false);
1642
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1643
#error unsupported barrier
1644
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1645
}
1646
1647
/**
1648
* Store a U_32 into an array atomically
1649
*
1650
* This function performs all of the necessary barriers and calls OOL when it can not handle
1651
* the barrier itself.
1652
*
1653
* @param destArray the array being stored to
1654
* @param destIndex the index to be stored at
1655
* @param compareObject the object to compare with
1656
* @param swapObject the value to be swapped in
1657
* @param isVolatile non-zero if the field is volatile, zero otherwise
1658
*
1659
* @return true on success, false otherwise
1660
*/
1661
VMINLINE bool
1662
inlineIndexableObjectCompareAndSwapU32(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, U_32 compareValue, U_32 swapValue, bool isVolatile = false)
1663
{
1664
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) || defined(J9VM_GC_COMBINATION_SPEC)
1665
U_32 *actualAddress = J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_32);
1666
1667
protectIfVolatileBefore(isVolatile, false);
1668
bool result = compareAndSwapU32Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);
1669
protectIfVolatileAfter(isVolatile, false);
1670
1671
return result;
1672
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1673
#error unsupported barrier
1674
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1675
}
1676
1677
/**
1678
* Conditionally store a U_32 into an array atomically
1679
*
1680
* This function performs all of the necessary barriers and calls OOL when it can not handle
1681
* the barrier itself.
1682
*
1683
* @param destArray the array being stored to
1684
* @param destIndex the index to be stored at
1685
* @param compareObject the object to compare with
1686
* @param swapObject the value to be swapped in
1687
* @param isVolatile non-zero if the field is volatile, zero otherwise
1688
*
1689
* @return the value stored in the array before the update
1690
*/
1691
VMINLINE U_32
1692
inlineIndexableObjectCompareAndExchangeU32(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, U_32 compareValue, U_32 swapValue, bool isVolatile = false)
1693
{
1694
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) || defined(J9VM_GC_COMBINATION_SPEC)
1695
U_32 *actualAddress = J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_32);
1696
1697
protectIfVolatileBefore(isVolatile, false);
1698
U_32 result = compareAndExchangeU32Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);
1699
protectIfVolatileAfter(isVolatile, false);
1700
1701
return result;
1702
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1703
#error unsupported barrier
1704
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1705
}
1706
1707
/**
1708
* Read an I_64 from an array.
1709
*
1710
* This function performs all of the necessary barriers and calls OOL when it can not handle
1711
* the barrier itself.
1712
*
1713
* @param srcArray the array being read from
1714
* @param srcIndex the index to be read
1715
*/
1716
VMINLINE I_64
1717
inlineIndexableObjectReadI64(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)
1718
{
1719
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1720
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadI64(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);
1721
#elif defined(J9VM_GC_COMBINATION_SPEC)
1722
I_64 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_64);
1723
1724
protectIfVolatileBefore(isVolatile, true);
1725
I_64 result = readI64Impl(vmThread, actualAddress, isVolatile);
1726
protectIfVolatileAfter(isVolatile, true);
1727
1728
return result;
1729
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1730
#error unsupported barrier
1731
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1732
}
1733
1734
/**
1735
* Store a I_64 into an array
1736
*
1737
* This function performs all of the necessary barriers and calls OOL when it can not handle
1738
* the barrier itself.
1739
*
1740
* @param srcArray the array being stored to
1741
* @param srcIndex the index to be stored at
1742
* @param value the value being store
1743
*/
1744
VMINLINE void
1745
inlineIndexableObjectStoreI64(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, I_64 value, bool isVolatile = false)
1746
{
1747
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1748
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreI64(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);
1749
#elif defined(J9VM_GC_COMBINATION_SPEC)
1750
I_64 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, I_64);
1751
1752
protectIfVolatileBefore(isVolatile, false);
1753
storeI64Impl(vmThread, actualAddress, value, isVolatile);
1754
protectIfVolatileAfter(isVolatile, false);
1755
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1756
#error unsupported barrier
1757
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1758
}
1759
1760
/**
1761
* Read an U_64 from an array.
1762
*
1763
* This function performs all of the necessary barriers and calls OOL when it can not handle
1764
* the barrier itself.
1765
*
1766
* @param srcArray the array being read from
1767
* @param srcIndex the index to be read
1768
*/
1769
VMINLINE U_64
1770
inlineIndexableObjectReadU64(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)
1771
{
1772
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1773
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadU64(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);
1774
#elif defined(J9VM_GC_COMBINATION_SPEC)
1775
U_64 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_64);
1776
1777
protectIfVolatileBefore(isVolatile, true);
1778
U_64 result = readU64Impl(vmThread, actualAddress, isVolatile);
1779
protectIfVolatileAfter(isVolatile, true);
1780
1781
return result;
1782
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1783
#error unsupported barrier
1784
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1785
}
1786
1787
/**
1788
* Store a U_64 into an array
1789
*
1790
* This function performs all of the necessary barriers and calls OOL when it can not handle
1791
* the barrier itself.
1792
*
1793
* @param srcArray the array being stored to
1794
* @param srcIndex the index to be stored at
1795
* @param value the value being store
1796
*/
1797
VMINLINE void
1798
inlineIndexableObjectStoreU64(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, U_64 value, bool isVolatile = false)
1799
{
1800
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1801
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreU64(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);
1802
#elif defined(J9VM_GC_COMBINATION_SPEC)
1803
U_64 *actualAddress = J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_64);
1804
1805
protectIfVolatileBefore(isVolatile, false);
1806
storeU64Impl(vmThread, actualAddress, value, isVolatile);
1807
protectIfVolatileAfter(isVolatile, false);
1808
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1809
#error unsupported barrier
1810
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1811
}
1812
1813
/**
1814
* Store a U_64 into an array atomically
1815
*
1816
* This function performs all of the necessary barriers and calls OOL when it can not handle
1817
* the barrier itself.
1818
*
1819
* @param destArray the array being stored to
1820
* @param destIndex the index to be stored at
1821
* @param compareObject the object to compare with
1822
* @param swapObject the value to be swapped in
1823
* @param isVolatile non-zero if the field is volatile, zero otherwise
1824
*
1825
* @return true on success, false otherwise
1826
*/
1827
VMINLINE bool
1828
inlineIndexableObjectCompareAndSwapU64(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, U_64 compareValue, U_64 swapValue, bool isVolatile = false)
1829
{
1830
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) || defined(J9VM_GC_COMBINATION_SPEC)
1831
U_64 *actualAddress = J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_64);
1832
1833
protectIfVolatileBefore(isVolatile, false);
1834
bool result = compareAndSwapU64Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);
1835
protectIfVolatileAfter(isVolatile, false);
1836
1837
return result;
1838
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1839
#error unsupported barrier
1840
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1841
}
1842
1843
/**
1844
* Conditionally store a U_64 into an array atomically
1845
*
1846
* This function performs all of the necessary barriers and calls OOL when it can not handle
1847
* the barrier itself.
1848
*
1849
* @param destArray the array being stored to
1850
* @param destIndex the index to be stored at
1851
* @param compareObject the object to compare with
1852
* @param swapObject the value to be swapped in
1853
* @param isVolatile non-zero if the field is volatile, zero otherwise
1854
*
1855
* @return the value stored in the array before the update
1856
*/
1857
VMINLINE U_64
1858
inlineIndexableObjectCompareAndExchangeU64(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, U_64 compareValue, U_64 swapValue, bool isVolatile = false)
1859
{
1860
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER) || defined(J9VM_GC_COMBINATION_SPEC)
1861
U_64 *actualAddress = J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_64);
1862
1863
protectIfVolatileBefore(isVolatile, false);
1864
U_64 result = compareAndExchangeU64Impl(vmThread, actualAddress, compareValue, swapValue, isVolatile);
1865
protectIfVolatileAfter(isVolatile, false);
1866
1867
return result;
1868
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1869
#error unsupported barrier
1870
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1871
}
1872
1873
/**
1874
* Read an object from an array.
1875
*
1876
* This function performs all of the necessary barriers and calls OOL when it can not handle
1877
* the barrier itself.
1878
*
1879
* @param srcArray the array being read from
1880
* @param srcIndex the index to be read
1881
*/
1882
VMINLINE j9object_t
1883
inlineIndexableObjectReadObject(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, bool isVolatile = false)
1884
{
1885
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1886
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableReadObject(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, isVolatile);
1887
#elif defined(J9VM_GC_COMBINATION_SPEC)
1888
fj9object_t *actualAddress = NULL;
1889
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
1890
actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_32);
1891
} else {
1892
actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, UDATA);
1893
}
1894
1895
preIndexableObjectReadObject(vmThread, srcArray, actualAddress);
1896
1897
protectIfVolatileBefore(isVolatile, true);
1898
j9object_t result = readObjectImpl(vmThread, actualAddress, isVolatile);
1899
protectIfVolatileAfter(isVolatile, true);
1900
1901
return result;
1902
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1903
#error unsupported barrier
1904
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1905
}
1906
1907
/**
1908
* Store an object into an array
1909
*
1910
* This function performs all of the necessary barriers and calls OOL when it can not handle
1911
* the barrier itself.
1912
*
1913
* @param srcArray the array being stored to
1914
* @param srcIndex the index to be stored at
1915
* @param value the value being store
1916
*/
1917
VMINLINE void
1918
inlineIndexableObjectStoreObject(J9VMThread *vmThread, j9object_t srcArray, UDATA srcIndex, j9object_t value, bool isVolatile = false)
1919
{
1920
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1921
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreObject(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);
1922
#elif defined(J9VM_GC_COMBINATION_SPEC)
1923
if (j9gc_modron_wrtbar_always == _writeBarrierType) {
1924
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_indexableStoreObject(vmThread, (J9IndexableObject *)srcArray, (I_32)srcIndex, value, isVolatile);
1925
} else {
1926
fj9object_t *actualAddress = NULL;
1927
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
1928
actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, U_32);
1929
} else {
1930
actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, srcArray, srcIndex, UDATA);
1931
}
1932
1933
preIndexableObjectStoreObject(vmThread, srcArray, actualAddress, value);
1934
1935
protectIfVolatileBefore(isVolatile, false);
1936
storeObjectImpl(vmThread, actualAddress, value, isVolatile);
1937
protectIfVolatileAfter(isVolatile, false);
1938
1939
postIndexableObjectStoreObject(vmThread, srcArray, actualAddress, value);
1940
}
1941
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1942
#error unsupported barrier
1943
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1944
}
1945
1946
/**
1947
* Store an object into an array atomically
1948
*
1949
* This function performs all of the necessary barriers and calls OOL when it can not handle
1950
* the barrier itself.
1951
*
1952
* @param destArray the array being stored to
1953
* @param destIndex the index to be stored at
1954
* @param compareObject the object to compare with
1955
* @param swapObject the value to be swapped in
1956
* @param isVolatile non-zero if the field is volatile, zero otherwise
1957
*
1958
* @return true on success, false otherwise
1959
*/
1960
VMINLINE bool
1961
inlineIndexableObjectCompareAndSwapObject(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)
1962
{
1963
fj9object_t *actualAddress = NULL;
1964
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
1965
actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_32);
1966
} else {
1967
actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, destArray, destIndex, UDATA);
1968
}
1969
1970
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
1971
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndSwapObject(vmThread, destArray, (J9Object **)actualAddress, compareObject, swapObject));
1972
#elif defined(J9VM_GC_COMBINATION_SPEC)
1973
if (j9gc_modron_wrtbar_always == _writeBarrierType) {
1974
return (1 == vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndSwapObject(vmThread, destArray, (J9Object **)actualAddress, compareObject, swapObject));
1975
} else {
1976
preIndexableObjectReadObject(vmThread, destArray, actualAddress);
1977
preIndexableObjectStoreObject(vmThread, destArray, actualAddress, swapObject);
1978
1979
protectIfVolatileBefore(isVolatile, false);
1980
bool result = compareAndSwapObjectImpl(vmThread, actualAddress, compareObject, swapObject, isVolatile);
1981
protectIfVolatileAfter(isVolatile, false);
1982
1983
if (result) {
1984
postIndexableObjectStoreObject(vmThread, destArray, actualAddress, swapObject);
1985
}
1986
return result;
1987
}
1988
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1989
#error unsupported barrier
1990
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
1991
}
1992
1993
/**
1994
* Conditionally store an object into an array atomically
1995
*
1996
* This function performs all of the necessary barriers and calls OOL when it can not handle
1997
* the barrier itself.
1998
*
1999
* @param destArray the array being stored to
2000
* @param destIndex the index to be stored at
2001
* @param compareObject the object to compare with
2002
* @param swapObject the value to be swapped in
2003
* @param isVolatile non-zero if the field is volatile, zero otherwise
2004
*
2005
* @return the object stored in the array before the update
2006
*/
2007
VMINLINE j9object_t
2008
inlineIndexableObjectCompareAndExchangeObject(J9VMThread *vmThread, j9object_t destArray, UDATA destIndex, j9object_t compareObject, j9object_t swapObject, bool isVolatile = false)
2009
{
2010
fj9object_t *actualAddress = NULL;
2011
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
2012
actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, destArray, destIndex, U_32);
2013
} else {
2014
actualAddress = (fj9object_t*)J9JAVAARRAY_EA(vmThread, destArray, destIndex, UDATA);
2015
}
2016
2017
#if defined(J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER)
2018
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndExchangeObject(vmThread, destArray, (J9Object **)actualAddress, compareObject, swapObject);
2019
#elif defined(J9VM_GC_COMBINATION_SPEC)
2020
if (j9gc_modron_wrtbar_always == _writeBarrierType) {
2021
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_compareAndExchangeObject(vmThread, destArray, (J9Object **)actualAddress, compareObject, swapObject);
2022
} else {
2023
preIndexableObjectReadObject(vmThread, destArray, actualAddress);
2024
preIndexableObjectStoreObject(vmThread, destArray, actualAddress, swapObject);
2025
2026
protectIfVolatileBefore(isVolatile, false);
2027
fj9object_t resultToken = compareAndExchangeObjectImpl(vmThread, actualAddress, compareObject, swapObject, isVolatile);
2028
protectIfVolatileAfter(isVolatile, false);
2029
2030
j9object_t result = internalConvertPointerFromToken(resultToken);
2031
2032
if (result == compareObject) {
2033
postIndexableObjectStoreObject(vmThread, destArray, actualAddress, swapObject);
2034
}
2035
return result;
2036
}
2037
#else /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
2038
#error unsupported barrier
2039
#endif /* J9VM_GC_ALWAYS_CALL_OBJECT_ACCESS_BARRIER */
2040
}
2041
2042
/* Return an j9object_t that can be stored in the constantpool.
2043
*
2044
* Not all collectors scan the constantpool on every GC and therefore for
2045
* these collectors the objects must be in tenure space.
2046
*
2047
* Note, the stack must be walkable as a GC may occur during this function.
2048
*
2049
* Note, this doesn't handle arrays.
2050
*
2051
* @param vmThread The current vmThread
2052
* @param toConvert The object to convert to a constantpool allowed form.
2053
*
2054
* @return an object that can be put in the constantpool or null if OOM.
2055
*/
2056
static VMINLINE j9object_t
2057
asConstantPoolObject(J9VMThread *vmThread, j9object_t toConvert, UDATA allocateFlags)
2058
{
2059
return vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_asConstantPoolObject(vmThread, toConvert, allocateFlags);
2060
}
2061
2062
protected:
2063
2064
/**
2065
* Called before object references are stored into mixed objects to perform an prebarrier work.
2066
*
2067
* @param object - the object being stored into
2068
* @param destAddress - the address being stored into
2069
* @param value - the value being stored
2070
*
2071
*/
2072
VMINLINE void
2073
preMixedObjectStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)
2074
{
2075
internalPreStoreObject(vmThread, object, destAddress, value);
2076
}
2077
2078
/**
2079
* Called before object references are stored into arrays to perform an prebarrier work.
2080
*
2081
* @param object - the object being stored into
2082
* @param destAddress - the address being stored into
2083
* @param value - the value being stored
2084
*
2085
*/
2086
VMINLINE void
2087
preIndexableObjectStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)
2088
{
2089
internalPreStoreObject(vmThread, object, destAddress, value);
2090
}
2091
2092
/**
2093
* Called before object references are stored into class statics to perform an prebarrier work.
2094
*
2095
* @param dstClassObject - the class object being stored into
2096
* @param destAddress - the address being stored into
2097
* @param value - the value being stored
2098
*
2099
*/
2100
VMINLINE void
2101
preStaticStoreObject(J9VMThread *vmThread, j9object_t dstClassObject, j9object_t *destAddress, j9object_t value)
2102
{
2103
internalStaticPreStoreObject(vmThread, dstClassObject, destAddress, value);
2104
}
2105
2106
/**
2107
* Called after object references are stored into mixed objects to perform an postbarrier work.
2108
*
2109
* @param object - the object being stored into
2110
* @param destAddress - the address being stored into
2111
* @param value - the value being stored
2112
*
2113
*/
2114
VMINLINE void
2115
postMixedObjectStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)
2116
{
2117
internalPostStoreObject(vmThread, object, value);
2118
}
2119
2120
/**
2121
* Called after object references are stored into arrays to perform an postbarrier work.
2122
*
2123
* @param object - the object being stored into
2124
* @param destAddress - the address being stored into
2125
* @param value - the value being stored
2126
*
2127
*/
2128
VMINLINE void
2129
postIndexableObjectStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)
2130
{
2131
internalPostStoreObject(vmThread, object, value);
2132
}
2133
2134
/**
2135
* Called after object references are stored into class statics to perform an postbarrier work.
2136
*
2137
* @param object - the class object being stored into
2138
* @param destAddress - the address being stored into
2139
* @param value - the value being stored
2140
*
2141
*/
2142
VMINLINE void
2143
postStaticStoreObject(J9VMThread *vmThread, j9object_t object, j9object_t *destAddress, j9object_t value)
2144
{
2145
internalPostStoreObject(vmThread, object, value);
2146
}
2147
2148
VMINLINE void
2149
postBatchStoreObject(J9VMThread *vmThread, j9object_t object)
2150
{
2151
internalPostBatchStoreObject(vmThread, object);
2152
}
2153
2154
/**
2155
* Perform the preRead barrier for a reference slot within a mixed heap object
2156
*
2157
* @param object this is the heap object being read from
2158
* @param sreAddress the address of the slot being read
2159
*/
2160
VMINLINE void
2161
preMixedObjectReadObject(J9VMThread *vmThread, j9object_t object, fj9object_t *srcAddress)
2162
{
2163
internalPreReadObject(vmThread, object, srcAddress);
2164
}
2165
2166
/**
2167
* Perform the preRead barrier for a reference slot within an indexable heap object
2168
*
2169
* @param object this is the heap object being read from
2170
* @param sreAddress the address of the slot being read
2171
*/
2172
VMINLINE void
2173
preIndexableObjectReadObject(J9VMThread *vmThread, j9object_t object, fj9object_t *srcAddress)
2174
{
2175
internalPreReadObject(vmThread, object, srcAddress);
2176
}
2177
2178
/**
2179
* Read a non-object address (pointer to internal VM data) from an object.
2180
* This function is only concerned with moving the actual data. Do not re-implement
2181
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2182
*
2183
* @param srcAddress the address of the field to be read
2184
* @param isVolatile non-zero if the field is volatile, zero otherwise
2185
*/
2186
VMINLINE void *
2187
readAddressImpl(J9VMThread *vmThread, void **srcAddress, bool isVolatile)
2188
{
2189
return *srcAddress;
2190
}
2191
2192
/**
2193
* Read a I_16 from an object.
2194
* This function is only concerned with moving the actual data. Do not re-implement
2195
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2196
*
2197
* @param srcAddress the address of the field to be read
2198
* @param isVolatile non-zero if the field is volatile, zero otherwise
2199
*/
2200
VMINLINE I_16
2201
readI16Impl(J9VMThread *vmThread, I_16 *srcAddress, bool isVolatile)
2202
{
2203
return *srcAddress;
2204
}
2205
2206
/**
2207
* Read a U_16 from an object.
2208
* This function is only concerned with moving the actual data. Do not re-implement
2209
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2210
*
2211
* @param srcAddress the address of the field to be read
2212
* @param isVolatile non-zero if the field is volatile, zero otherwise
2213
*/
2214
VMINLINE U_16
2215
readU16Impl(J9VMThread *vmThread, U_16 *srcAddress, bool isVolatile)
2216
{
2217
return *srcAddress;
2218
}
2219
2220
/**
2221
* Read a I_32 from an object.
2222
* This function is only concerned with moving the actual data. Do not re-implement
2223
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2224
*
2225
* @param srcAddress the address of the field to be read
2226
* @param isVolatile non-zero if the field is volatile, zero otherwise
2227
*/
2228
VMINLINE I_32
2229
readI32Impl(J9VMThread *vmThread, I_32 *srcAddress, bool isVolatile)
2230
{
2231
return *srcAddress;
2232
}
2233
2234
/**
2235
* Read a U_32 from an object.
2236
* This function is only concerned with moving the actual data. Do not re-implement
2237
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2238
*
2239
* @param srcAddress the address of the field to be read
2240
* @param isVolatile non-zero if the field is volatile, zero otherwise
2241
*/
2242
VMINLINE U_32
2243
readU32Impl(J9VMThread *vmThread, U_32 *srcAddress, bool isVolatile)
2244
{
2245
return *srcAddress;
2246
}
2247
2248
/**
2249
* Read a I_64 from an object.
2250
* This function is only concerned with moving the actual data. Do not re-implement
2251
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2252
*
2253
* @param srcAddress the address of the field to be read
2254
* @param isVolatile non-zero if the field is volatile, zero otherwise
2255
*/
2256
VMINLINE I_64
2257
readI64Impl(J9VMThread *vmThread, I_64 *srcAddress, bool isVolatile)
2258
{
2259
#if !defined(J9VM_ENV_DATA64)
2260
if (isVolatile) {
2261
return longVolatileRead(vmThread, (U_64 *)srcAddress);
2262
}
2263
#endif /* J9VM_ENV_DATA64 */
2264
return *srcAddress;
2265
}
2266
2267
/**
2268
* Read a U_64 from an object.
2269
* This function is only concerned with moving the actual data. Do not re-implement
2270
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2271
*
2272
* @param srcAddress the address of the field to be read
2273
* @param isVolatile non-zero if the field is volatile, zero otherwise
2274
*/
2275
VMINLINE U_64
2276
readU64Impl(J9VMThread *vmThread, U_64 *srcAddress, bool isVolatile)
2277
{
2278
#if !defined(J9VM_ENV_DATA64)
2279
if (isVolatile) {
2280
return longVolatileRead(vmThread, srcAddress);
2281
}
2282
#endif /* J9VM_ENV_DATA64 */
2283
return *srcAddress;
2284
}
2285
2286
/**
2287
* Read a I_8 from an object.
2288
* This function is only concerned with moving the actual data. Do not re-implement
2289
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2290
*
2291
* @param srcAddress the address of the field to be read
2292
* @param isVolatile non-zero if the field is volatile, zero otherwise
2293
*/
2294
VMINLINE I_8
2295
readI8Impl(J9VMThread *vmThread, I_8 *srcAddress, bool isVolatile)
2296
{
2297
return *srcAddress;
2298
}
2299
2300
/**
2301
* Read a U_8 from an object.
2302
* This function is only concerned with moving the actual data. Do not re-implement
2303
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2304
*
2305
* @param srcAddress the address of the field to be read
2306
* @param isVolatile non-zero if the field is volatile, zero otherwise
2307
*/
2308
VMINLINE U_8
2309
readU8Impl(J9VMThread *vmThread, U_8 *srcAddress, bool isVolatile)
2310
{
2311
return *srcAddress;
2312
}
2313
2314
/**
2315
* Read an object pointer from an object.
2316
* This function is only concerned with moving the actual data. Do not re-implement
2317
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2318
*
2319
* @param srcAddress the address of the field to be read
2320
* @param isVolatile non-zero if the field is volatile, zero otherwise
2321
*/
2322
VMINLINE mm_j9object_t
2323
readObjectImpl(J9VMThread *vmThread, fj9object_t *srcAddress, bool isVolatile)
2324
{
2325
mm_j9object_t result = NULL;
2326
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
2327
result = internalConvertPointerFromToken((fj9object_t)(UDATA)*(U_32*)srcAddress);
2328
} else {
2329
result = (mm_j9object_t)*(UDATA*)srcAddress;
2330
}
2331
return result;
2332
}
2333
2334
/**
2335
* Called before reading a reference class static slot
2336
*
2337
* @param object - the class object being read from
2338
* @param srcAddress - the address the slot read from
2339
*/
2340
VMINLINE void
2341
preStaticReadObject(J9VMThread *vmThread, J9Class *clazz, j9object_t *srcAddress)
2342
{
2343
if (j9gc_modron_readbar_none != _readBarrierType) {
2344
vmThread->javaVM->memoryManagerFunctions->J9ReadBarrierClass(vmThread, srcAddress);
2345
}
2346
}
2347
2348
2349
/**
2350
* Read a static object field.
2351
* This function is only concerned with moving the actual data. Do not re-implement
2352
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2353
*
2354
* @param srcAddress the address of the field to be read
2355
* @param isVolatile non-zero if the field is volatile, zero otherwise
2356
*/
2357
VMINLINE mm_j9object_t
2358
staticReadObjectImpl(J9VMThread *vmThread, j9object_t *srcAddress, bool isVolatile)
2359
{
2360
return *srcAddress;
2361
}
2362
2363
/**
2364
* Store a non-object address into an object.
2365
* This function is only concerned with moving the actual data. Do not re-implement
2366
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2367
*
2368
* @param destAddress the address of the field to be read
2369
* @param value the value to be stored
2370
* @param isVolatile non-zero if the field is volatile, zero otherwise
2371
*/
2372
VMINLINE void
2373
storeAddressImpl(J9VMThread *vmThread, void **destAddress, void *value, bool isVolatile)
2374
{
2375
*destAddress = value;
2376
}
2377
2378
/**
2379
* Store a I_16 into an object.
2380
* This function is only concerned with moving the actual data. Do not re-implement
2381
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2382
*
2383
* @param destAddress the address of the field to be read
2384
* @param value the value to be stored
2385
* @param isVolatile non-zero if the field is volatile, zero otherwise
2386
*/
2387
VMINLINE void
2388
storeI16Impl(J9VMThread *vmThread, I_16 *destAddress, I_16 value, bool isVolatile)
2389
{
2390
*destAddress = value;
2391
}
2392
2393
/**
2394
* Store a U_16 into an object.
2395
* This function is only concerned with moving the actual data. Do not re-implement
2396
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2397
*
2398
* @param destAddress the address of the field to be read
2399
* @param value the value to be stored
2400
* @param isVolatile non-zero if the field is volatile, zero otherwise
2401
*/
2402
VMINLINE void
2403
storeU16Impl(J9VMThread *vmThread, U_16 *destAddress, U_16 value, bool isVolatile)
2404
{
2405
*destAddress = value;
2406
}
2407
2408
/**
2409
* Store a I_32 into an object.
2410
* This function is only concerned with moving the actual data. Do not re-implement
2411
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2412
*
2413
* @param destAddress the address of the field to be read
2414
* @param value the value to be stored
2415
* @param isVolatile non-zero if the field is volatile, zero otherwise
2416
*/
2417
VMINLINE void
2418
storeI32Impl(J9VMThread *vmThread, I_32 *destAddress, I_32 value, bool isVolatile)
2419
{
2420
*destAddress = value;
2421
}
2422
2423
/**
2424
* Store a U_32 into an object.
2425
* This function is only concerned with moving the actual data. Do not re-implement
2426
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2427
*
2428
* @param destAddress the address of the field to be read
2429
* @param value the value to be stored
2430
* @param isVolatile non-zero if the field is volatile, zero otherwise
2431
*/
2432
VMINLINE void
2433
storeU32Impl(J9VMThread *vmThread, U_32 *destAddress, U_32 value, bool isVolatile)
2434
{
2435
*destAddress = value;
2436
}
2437
2438
VMINLINE bool
2439
compareAndSwapU32Impl(J9VMThread *vmThread, U_32 *destAddress, U_32 compareValue, U_32 swapValue, bool isVolatile)
2440
{
2441
return (compareValue == VM_AtomicSupport::lockCompareExchangeU32(destAddress, compareValue, swapValue));
2442
}
2443
2444
VMINLINE U_32
2445
compareAndExchangeU32Impl(J9VMThread *vmThread, U_32 *destAddress, U_32 compareValue, U_32 swapValue, bool isVolatile)
2446
{
2447
return VM_AtomicSupport::lockCompareExchangeU32(destAddress, compareValue, swapValue);
2448
}
2449
2450
/**
2451
* Store an I_64 into an object.
2452
* This function is only concerned with moving the actual data. Do not re-implement
2453
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2454
*
2455
* @param destAddress the address of the field to be read
2456
* @param value the value to be stored
2457
* @param isVolatile non-zero if the field is volatile, zero otherwise
2458
*/
2459
VMINLINE void
2460
storeI64Impl(J9VMThread *vmThread, I_64 *destAddress, I_64 value, bool isVolatile)
2461
{
2462
#if !defined(J9VM_ENV_DATA64)
2463
if (isVolatile) {
2464
longVolatileWrite(vmThread, (U_64 *)destAddress, (U_64 *)&value);
2465
return;
2466
}
2467
#endif /* J9VM_ENV_DATA64 */
2468
*destAddress = value;
2469
}
2470
2471
/**
2472
* Store an U_64 into an object.
2473
* This function is only concerned with moving the actual data. Do not re-implement
2474
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2475
*
2476
* @param destAddress the address of the field to be read
2477
* @param value the value to be stored
2478
* @param isVolatile non-zero if the field is volatile, zero otherwise
2479
*/
2480
VMINLINE void
2481
storeU64Impl(J9VMThread *vmThread, U_64 *destAddress, U_64 value, bool isVolatile)
2482
{
2483
#if !defined(J9VM_ENV_DATA64)
2484
if (isVolatile) {
2485
longVolatileWrite(vmThread, destAddress, &value);
2486
return;
2487
}
2488
#endif /* J9VM_ENV_DATA64 */
2489
*destAddress = value;
2490
}
2491
2492
VMINLINE bool
2493
compareAndSwapU64Impl(J9VMThread *vmThread, U_64 *destAddress, U_64 compareValue, U_64 swapValue, bool isVolatile)
2494
{
2495
return (compareValue == VM_AtomicSupport::lockCompareExchangeU64(destAddress, compareValue, swapValue));
2496
}
2497
2498
VMINLINE U_64
2499
compareAndExchangeU64Impl(J9VMThread *vmThread, U_64 *destAddress, U_64 compareValue, U_64 swapValue, bool isVolatile)
2500
{
2501
return VM_AtomicSupport::lockCompareExchangeU64(destAddress, compareValue, swapValue);
2502
}
2503
2504
/**
2505
* Store a I_8 into an object.
2506
* This function is only concerned with moving the actual data. Do not re-implement
2507
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2508
*
2509
* @param destAddress the address of the field to be read
2510
* @param value the value to be stored
2511
* @param isVolatile non-zero if the field is volatile, zero otherwise
2512
*/
2513
VMINLINE void
2514
storeI8Impl(J9VMThread *vmThread, I_8 *destAddress, I_8 value, bool isVolatile)
2515
{
2516
*destAddress = value;
2517
}
2518
2519
/**
2520
* Store a U_8 into an object.
2521
* This function is only concerned with moving the actual data. Do not re-implement
2522
* unless the value is stored in a non-native format (e.g. compressed object pointers).
2523
*
2524
* @param destAddress the address of the field to be read
2525
* @param value the value to be stored
2526
* @param isVolatile non-zero if the field is volatile, zero otherwise
2527
*/
2528
VMINLINE void
2529
storeU8Impl(J9VMThread *vmThread, U_8 *destAddress, U_8 value, bool isVolatile)
2530
{
2531
*destAddress = value;
2532
}
2533
2534
/**
2535
* Store an object pointer into an object.
2536
* This function is only concerned with moving the actual data. Do not re-implement
2537
*
2538
* @param destAddress the address of the field to be read
2539
* @param value the value to be stored
2540
* @param isVolatile non-zero if the field is volatile, zero otherwise
2541
*/
2542
VMINLINE void
2543
storeObjectImpl(J9VMThread *vmThread, fj9object_t *destAddress, mm_j9object_t value, bool isVolatile)
2544
{
2545
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
2546
*(U_32*)destAddress = (U_32)internalConvertTokenFromPointer(value);
2547
} else {
2548
*(UDATA*)destAddress = (UDATA)value;
2549
}
2550
}
2551
2552
VMINLINE bool
2553
compareAndSwapObjectImpl(J9VMThread *vmThread, fj9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile)
2554
{
2555
fj9object_t compareValue = internalConvertTokenFromPointer(compareObject);
2556
fj9object_t swapValue = internalConvertTokenFromPointer(swapObject);
2557
bool result = true;
2558
2559
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
2560
result = ((U_32)(UDATA)compareValue == VM_AtomicSupport::lockCompareExchangeU32((U_32 *)destAddress, (U_32)(UDATA)compareValue, (U_32)(UDATA)swapValue));
2561
} else {
2562
result = ((UDATA)compareValue == VM_AtomicSupport::lockCompareExchange((UDATA *)destAddress, (UDATA)compareValue, (UDATA)swapValue));
2563
}
2564
2565
return result;
2566
}
2567
2568
VMINLINE fj9object_t
2569
compareAndExchangeObjectImpl(J9VMThread *vmThread, fj9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile)
2570
{
2571
fj9object_t compareValue = internalConvertTokenFromPointer(compareObject);
2572
fj9object_t swapValue = internalConvertTokenFromPointer(swapObject);
2573
fj9object_t result = (fj9object_t)NULL;
2574
2575
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(vmThread)) {
2576
result = (fj9object_t)VM_AtomicSupport::lockCompareExchangeU32((U_32 *)destAddress, (U_32)(UDATA)compareValue, (U_32)(UDATA)swapValue);
2577
} else {
2578
result = (fj9object_t)VM_AtomicSupport::lockCompareExchange((UDATA *)destAddress, (UDATA)compareValue, (UDATA)swapValue);
2579
}
2580
2581
return result;
2582
}
2583
2584
/**
2585
* Store a static field.
2586
* This function is only concerned with moving the actual data. Do not re-implement
2587
*
2588
* @param destAddress the address of the field to be read
2589
* @param value the value to be stored
2590
* @param isVolatile non-zero if the field is volatile, zero otherwise
2591
*/
2592
VMINLINE void
2593
staticStoreObjectImpl(J9VMThread *vmThread, j9object_t *destAddress, mm_j9object_t value, bool isVolatile)
2594
{
2595
*destAddress = value;
2596
}
2597
2598
VMINLINE bool
2599
staticCompareAndSwapObjectImpl(J9VMThread *vmThread, j9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile)
2600
{
2601
return ((UDATA)compareObject == VM_AtomicSupport::lockCompareExchange((UDATA *)destAddress, (UDATA)compareObject, (UDATA)swapObject));
2602
}
2603
2604
VMINLINE j9object_t
2605
staticCompareAndExchangeObjectImpl(J9VMThread *vmThread, j9object_t *destAddress, j9object_t compareObject, j9object_t swapObject, bool isVolatile)
2606
{
2607
return (j9object_t)VM_AtomicSupport::lockCompareExchange((UDATA *)destAddress, (UDATA)compareObject, (UDATA)swapObject);
2608
}
2609
2610
/**
2611
* Call before a read or write of a possibly volatile field.
2612
*
2613
* @note This must be used in tandem with protectIfVolatileAfter()
2614
* @param isVolatile true if the field is volatile, false otherwise
2615
* @param isRead true if the field is being read, false if it is being written
2616
*/
2617
VMINLINE static void
2618
protectIfVolatileBefore(bool isVolatile, bool isRead)
2619
{
2620
if (isVolatile) {
2621
if (!isRead) {
2622
VM_AtomicSupport::writeBarrier();
2623
}
2624
}
2625
}
2626
2627
/**
2628
* Call after a read or write of a possibly volatile field.
2629
*
2630
* @note This must be used in tandem with protectIfVolatileBefore()
2631
* @param isVolatile true if the field is volatile, false otherwise
2632
* @param isRead true if the field is being read, false if it is being written
2633
*/
2634
VMINLINE static void
2635
protectIfVolatileAfter(bool isVolatile, bool isRead)
2636
{
2637
if (isVolatile) {
2638
if (isRead) {
2639
VM_AtomicSupport::readBarrier();
2640
} else {
2641
VM_AtomicSupport::readWriteBarrier();
2642
}
2643
}
2644
}
2645
2646
/**
2647
* Call to convert an object pointer to an object token
2648
*
2649
* @param pointer the object pointer to convert
2650
* @return the object token
2651
*/
2652
VMINLINE fj9object_t
2653
internalConvertTokenFromPointer(j9object_t pointer)
2654
{
2655
#if defined (OMR_GC_COMPRESSED_POINTERS)
2656
if (compressObjectReferences()) {
2657
return (fj9object_t)((UDATA)pointer >> _compressedPointersShift);
2658
} else
2659
#endif /* OMR_GC_COMPRESSED_POINTERS */
2660
{
2661
return (fj9object_t)(UDATA)pointer;
2662
}
2663
}
2664
2665
/**
2666
* Call to convert an object token to an object pointer
2667
*
2668
* @param token the object token to convert
2669
* @return the object pointer
2670
*/
2671
VMINLINE j9object_t
2672
internalConvertPointerFromToken(fj9object_t token)
2673
{
2674
#if defined (OMR_GC_COMPRESSED_POINTERS)
2675
if (compressObjectReferences()) {
2676
return (mm_j9object_t)((UDATA)token << _compressedPointersShift);
2677
} else
2678
#endif /* OMR_GC_COMPRESSED_POINTERS */
2679
{
2680
return (mm_j9object_t)(UDATA)token;
2681
}
2682
}
2683
2684
private:
2685
2686
/**
2687
* Perform the preStore barrier
2688
*
2689
* Currently pre store barriers are only required for WRT. Check the barrier type
2690
* and forward accordingly
2691
*
2692
* @param object this is the class object being stored into
2693
* @param destAddress the address being stored at
2694
* @param value the value being stored
2695
*
2696
*/
2697
VMINLINE void
2698
internalPreStoreObject(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)
2699
{
2700
if ((j9gc_modron_wrtbar_satb == _writeBarrierType) ||
2701
(j9gc_modron_wrtbar_satb_and_oldcheck == _writeBarrierType)) {
2702
internalPreStoreObjectSATB(vmThread, object, destAddress, value);
2703
}
2704
}
2705
2706
/**
2707
* Perform the static preStore barrier
2708
*
2709
* Currently pre store barriers are only required for WRT. Check the barrier type
2710
* and forward accordingly
2711
*
2712
* @param dstClassObject this is the class object being stored into
2713
* @param destAddress the address being stored at
2714
* @param value the value being stored
2715
*
2716
*/
2717
VMINLINE void
2718
internalStaticPreStoreObject(J9VMThread *vmThread, j9object_t dstClassObject, j9object_t *destAddress, j9object_t value)
2719
{
2720
if ((j9gc_modron_wrtbar_satb == _writeBarrierType) ||
2721
(j9gc_modron_wrtbar_satb_and_oldcheck == _writeBarrierType)) {
2722
internalStaticPreStoreObjectSATB(vmThread, dstClassObject, destAddress, value);
2723
}
2724
}
2725
2726
/**
2727
* Perform the preStore barrier for WRT
2728
*
2729
* @param object this is the class object being stored into
2730
* @param destAddress the address being stored at
2731
* @param value the value being stored
2732
*
2733
*/
2734
VMINLINE void
2735
internalPreStoreObjectSATB(J9VMThread *vmThread, j9object_t object, fj9object_t *destAddress, j9object_t value)
2736
{
2737
#if defined(J9VM_GC_REALTIME)
2738
MM_GCRememberedSetFragment *fragment = &vmThread->sATBBarrierRememberedSetFragment;
2739
MM_GCRememberedSet *parent = fragment->fragmentParent;
2740
/* Check if the barrier is enabled. No work if barrier is not enabled */
2741
if (0 != parent->globalFragmentIndex) {
2742
/* if the double barrier is enabled call OOL */
2743
if (0 == fragment->localFragmentIndex) {
2744
vmThread->javaVM->memoryManagerFunctions->J9WriteBarrierPre(vmThread, object, destAddress, value);
2745
} else {
2746
j9object_t oldObject = readObjectImpl(vmThread, destAddress, false);
2747
if (NULL != oldObject) {
2748
if (!isMarked(vmThread, oldObject)) {
2749
vmThread->javaVM->memoryManagerFunctions->J9WriteBarrierPre(vmThread, object, destAddress, value);
2750
}
2751
}
2752
}
2753
}
2754
#endif /* J9VM_GC_REALTIME */
2755
}
2756
2757
/**
2758
* Perform the static preStore barrier for WRT
2759
*
2760
* @param dstClassObject this is the class object being stored into
2761
* @param destAddress the address being stored at
2762
* @param value the value being stored
2763
*
2764
*/
2765
VMINLINE void
2766
internalStaticPreStoreObjectSATB(J9VMThread *vmThread, j9object_t dstClassObject, j9object_t *destAddress, j9object_t value)
2767
{
2768
#if defined(J9VM_GC_REALTIME)
2769
MM_GCRememberedSetFragment *fragment = &vmThread->sATBBarrierRememberedSetFragment;
2770
MM_GCRememberedSet *parent = fragment->fragmentParent;
2771
/* Check if the barrier is enabled. No work if barrier is not enabled */
2772
if (0 != parent->globalFragmentIndex) {
2773
/* if the double barrier is enabled call OOL */
2774
if (0 == fragment->localFragmentIndex) {
2775
vmThread->javaVM->memoryManagerFunctions->J9WriteBarrierPreClass(vmThread, dstClassObject, destAddress, value);
2776
} else {
2777
j9object_t oldObject = *destAddress;
2778
if (NULL != oldObject) {
2779
if (!isMarked(vmThread, oldObject)) {
2780
vmThread->javaVM->memoryManagerFunctions->J9WriteBarrierPreClass(vmThread, dstClassObject, destAddress, value);
2781
}
2782
}
2783
}
2784
}
2785
#endif /* J9VM_GC_REALTIME */
2786
}
2787
2788
#if defined(J9VM_GC_REALTIME)
2789
/**
2790
* Check to see if the object is marked
2791
*
2792
* @NOTE only for SATB Concurrent Mark
2793
*
2794
* @param object to check
2795
* @return true if the object was marked, false otherwise
2796
*/
2797
VMINLINE bool
2798
isMarked(J9VMThread *vmThread, j9object_t object)
2799
{
2800
J9JavaVM *const javaVM = vmThread->javaVM;
2801
2802
if (J9_GC_POLICY_METRONOME == javaVM->gcPolicy) {
2803
UDATA heapMapBits = 0;
2804
UDATA heapDelta = (UDATA)object - javaVM->realtimeHeapMapBasePageRounded;
2805
UDATA slotIndex = heapDelta >> J9VMGC_SIZECLASSES_LOG_SMALLEST;
2806
UDATA bitIndex = slotIndex & J9_GC_MARK_MAP_UDATA_MASK;
2807
UDATA bitMask = ((UDATA)1) << bitIndex;
2808
slotIndex = slotIndex >> J9_GC_MARK_MAP_LOG_SIZEOF_UDATA;
2809
2810
UDATA *heapMapBitsBase = javaVM->realtimeHeapMapBits;
2811
heapMapBits = heapMapBitsBase[slotIndex];
2812
heapMapBits &= bitMask;
2813
2814
return 0 != heapMapBits;
2815
} else {
2816
/* TODO: Inline for SATB Standard Configuration */
2817
return 0 != javaVM->memoryManagerFunctions->j9gc_ext_is_marked(vmThread->javaVM, object);
2818
}
2819
}
2820
#endif /* J9VM_GC_REALTIME */
2821
2822
2823
/**
2824
* Call after storing an object reference
2825
*
2826
* @param object the object being stored into
2827
* @param value the object reference being stored
2828
*/
2829
VMINLINE void
2830
internalPostStoreObject(J9VMThread *vmThread, j9object_t object, j9object_t value)
2831
{
2832
switch(_writeBarrierType) {
2833
case j9gc_modron_wrtbar_cardmark_and_oldcheck:
2834
internalPostObjectStoreCardTableAndGenerational(vmThread, object, value);
2835
break;
2836
case j9gc_modron_wrtbar_oldcheck:
2837
internalPostObjectStoreGenerational(vmThread, object, value);
2838
break;
2839
case j9gc_modron_wrtbar_cardmark_incremental:
2840
internalPostObjectStoreCardTableIncremental(vmThread, object, value);
2841
break;
2842
case j9gc_modron_wrtbar_cardmark:
2843
internalPostObjectStoreCardTable(vmThread, object, value);
2844
break;
2845
case j9gc_modron_wrtbar_none:
2846
case j9gc_modron_wrtbar_satb:
2847
case j9gc_modron_wrtbar_satb_and_oldcheck:
2848
//TODO SATB change to handle gencon, decide where to do it in pre/post store
2849
break;
2850
default:
2851
/* Should assert as all real types are handled. Should never get here
2852
* with always or illegal
2853
*/
2854
break;
2855
}
2856
}
2857
2858
VMINLINE void
2859
internalPostBatchStoreObject(J9VMThread *vmThread, j9object_t object)
2860
{
2861
switch(_writeBarrierType) {
2862
case j9gc_modron_wrtbar_cardmark_and_oldcheck:
2863
internalPostBatchStoreObjectCardTableAndGenerational(vmThread, object);
2864
break;
2865
case j9gc_modron_wrtbar_oldcheck:
2866
internalPostBatchStoreObjectGenerational(vmThread, object);
2867
break;
2868
case j9gc_modron_wrtbar_cardmark_incremental:
2869
internalPostBatchStoreObjectCardTableIncremental(vmThread, object);
2870
break;
2871
case j9gc_modron_wrtbar_cardmark:
2872
internalPostBatchStoreObjectCardTable(vmThread, object);
2873
break;
2874
case j9gc_modron_wrtbar_none:
2875
case j9gc_modron_wrtbar_satb:
2876
case j9gc_modron_wrtbar_satb_and_oldcheck:
2877
break;
2878
default:
2879
/* Should assert as all real types are handled. Should never get here
2880
* with always or illegal
2881
*/
2882
break;
2883
}
2884
}
2885
2886
/**
2887
* Perform the preRead barrier for heap object reference slot
2888
* It's common API for both mixed and indexable objects
2889
*
2890
* @param object this is the heap object being read from
2891
* @param sreAddress the address of the slot being read
2892
*/
2893
VMINLINE void
2894
internalPreReadObject(J9VMThread *vmThread, j9object_t object, fj9object_t *srcAddress)
2895
{
2896
if (j9gc_modron_readbar_none != _readBarrierType) {
2897
vmThread->javaVM->memoryManagerFunctions->J9ReadBarrier(vmThread, srcAddress);
2898
}
2899
}
2900
2901
/**
2902
* Dirty the appropriate card for card table barriers
2903
*
2904
* @param objectDelta the delta from the object to heap start
2905
*
2906
*/
2907
static VMINLINE void
2908
dirtyCard(J9VMThread *vmThread, UDATA objectDelta)
2909
{
2910
/* calculate the delta with in the card table */
2911
UDATA shiftedDelta = objectDelta >> CARD_SIZE_SHIFT;
2912
2913
/* find the card and dirty it */
2914
U_8* card = (U_8*)vmThread->activeCardTableBase + shiftedDelta;
2915
*card = (U_8)CARD_DIRTY;
2916
}
2917
2918
/**
2919
* Add the object to the remembered set for generational barriers
2920
*
2921
* @param object the object to remember
2922
*
2923
*/
2924
static VMINLINE void
2925
rememberObject(J9VMThread *vmThread, j9object_t object)
2926
{
2927
#if defined (J9VM_GC_GENERATIONAL)
2928
if (atomicSetRemembered(vmThread, object)) {
2929
J9VMGCSublistFragment *fragment = &vmThread->gcRememberedSet;
2930
do {
2931
UDATA *slot = fragment->fragmentCurrent;
2932
UDATA *next = slot + 1;
2933
if (next > fragment->fragmentTop) {
2934
if (0 != vmThread->javaVM->memoryManagerFunctions->allocateMemoryForSublistFragment(vmThread->omrVMThread,(J9VMGC_SublistFragment*)fragment)) {
2935
break;
2936
}
2937
} else {
2938
fragment->fragmentCurrent = next;
2939
fragment->count += 1;
2940
*slot = (UDATA)object;
2941
break;
2942
}
2943
} while (true);
2944
}
2945
#endif /* J9VM_GC_GENERATIONAL */
2946
}
2947
2948
#if defined (J9VM_GC_GENERATIONAL)
2949
/**
2950
* Set the remembered but for the object pointer atomically
2951
*
2952
* @param object the object to set the remembered bit on
2953
* @return true if the bit was set, false otherwise
2954
*/
2955
static VMINLINE bool
2956
atomicSetRemembered(J9VMThread *currentThread, j9object_t objectPtr)
2957
{
2958
bool result = true;
2959
2960
if (J9VMTHREAD_COMPRESS_OBJECT_REFERENCES(currentThread)) {
2961
volatile U_32* flagsPtr = &(((J9ObjectCompressed*)objectPtr)->clazz);
2962
U_32 oldFlags = 0;
2963
U_32 newFlags = 0;
2964
do {
2965
oldFlags = *flagsPtr;
2966
if((oldFlags & J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST) >= J9_OBJECT_HEADER_REMEMBERED_BITS_TO_SET) {
2967
/* Remembered state in age was set by somebody else */
2968
result = false;
2969
break;
2970
}
2971
newFlags = (oldFlags & ~J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_CLEAR) | J9_OBJECT_HEADER_REMEMBERED_BITS_TO_SET;
2972
} while (oldFlags != VM_AtomicSupport::lockCompareExchangeU32(flagsPtr, oldFlags, newFlags));
2973
} else {
2974
volatile UDATA* flagsPtr = &(((J9ObjectFull*)objectPtr)->clazz);
2975
UDATA oldFlags = 0;
2976
UDATA newFlags = 0;
2977
do {
2978
oldFlags = *flagsPtr;
2979
if((oldFlags & J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_TEST) >= J9_OBJECT_HEADER_REMEMBERED_BITS_TO_SET) {
2980
/* Remembered state in age was set by somebody else */
2981
result = false;
2982
break;
2983
}
2984
newFlags = (oldFlags & ~J9_OBJECT_HEADER_REMEMBERED_MASK_FOR_CLEAR) | J9_OBJECT_HEADER_REMEMBERED_BITS_TO_SET;
2985
} while (oldFlags != VM_AtomicSupport::lockCompareExchange(flagsPtr, oldFlags, newFlags));
2986
}
2987
2988
return result;
2989
}
2990
#endif /* J9VM_GC_GENERATIONAL */
2991
2992
2993
};
2994
2995
#endif /* OBJECTACCESSBARRIERAPI_HPP_ */
2996
2997