Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_glue_java/ObjectModel.hpp
5985 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
/**
24
* @file
25
* @ingroup GC_Base
26
*/
27
28
#if !defined(OBJECTMODEL_HPP_)
29
#define OBJECTMODEL_HPP_
30
31
/* @ddr_namespace: default */
32
#include <assert.h>
33
34
#include "j9.h"
35
#include "j9cfg.h"
36
#include "j9consts.h"
37
#include "j9nonbuilder.h"
38
#include "modron.h"
39
#include "j9modron.h"
40
#include "objectdescription.h"
41
#include "util_api.h"
42
43
#include "ArrayObjectModel.hpp"
44
#include "ArrayletObjectModel.hpp"
45
#include "AtomicOperations.hpp"
46
#include "ForwardedHeader.hpp"
47
#include "HeapLinkedFreeHeader.hpp"
48
#include "MixedObjectModel.hpp"
49
#include "ObjectModelBase.hpp"
50
#include "ObjectModelDelegate.hpp"
51
52
#if defined(OMR_GC_REALTIME)
53
/* this bit is set in the object header slot if an overflow condition is raised */
54
#define GC_OVERFLOW 0x4
55
#endif /* defined(OMR_GC_REALTIME) */
56
57
/*
58
* #defines representing the scope depth stored in each object header
59
* use two low bits of Collector Bits for Depth
60
*/
61
#define OBJECT_HEADER_DEPTH_ZERO 0
62
#define OBJECT_HEADER_DEPTH_MAX 3
63
#define OBJECT_HEADER_DEPTH_SHIFT OMR_OBJECT_METADATA_AGE_SHIFT
64
#define OBJECT_HEADER_DEPTH_MASK (OBJECT_HEADER_DEPTH_MAX << OBJECT_HEADER_DEPTH_SHIFT)
65
66
/* check that we have enough collector bits to be used for Depth */
67
#if (0 != (OBJECT_HEADER_DEPTH_MASK & ~(OMR_OBJECT_METADATA_AGE_MASK)))
68
#error "Some OBJECT_HEADER_DEPTH_MASK bits are out of range of OMR_OBJECT_METADATA_AGE_MASK."
69
#endif /* (0 != (OBJECT_HEADER_DEPTH_MASK & ~(OMR_OBJECT_METADATA_AGE_MASK))) */
70
71
/*
72
* #defines representing the 2 bits stored in immortal object header used as mark and overflow bits by ReferenceChainWalker.
73
* Both bits occupy the arraylet layout bits which have been deprecated
74
*/
75
#define OBJECT_HEADER_REFERENCE_CHAIN_WALKER_IMMORTAL_MARKED 0x40
76
#define OBJECT_HEADER_REFERENCE_CHAIN_WALKER_IMMORTAL_OVERFLOW 0xC0
77
78
/* Object header flag bits used for lazy hashcode insertion on copy/move */
79
#define OMR_GC_DEFERRED_HASHCODE_INSERTION
80
81
class MM_AllocateInitialization;
82
class MM_EnvironmentBase;
83
class MM_GCExtensionsBase;
84
85
/**
86
* Provides information for a given object.
87
* @ingroup GC_Base
88
*/
89
class GC_ObjectModel : public GC_ObjectModelBase
90
{
91
/*
92
* Member data and types
93
*/
94
private:
95
J9JavaVM* _javaVM; /***< pointer to the Java VM */
96
GC_MixedObjectModel *_mixedObjectModel; /**< pointer to the mixed object model in extensions (so that we can delegate to it) */
97
GC_ArrayObjectModel *_indexableObjectModel; /**< pointer to the indexable object model in extensions (so that we can delegate to it) */
98
J9Class *_classClass; /**< java.lang.Class class pointer for detecting special objects */
99
J9Class *_classLoaderClass; /**< java.lang.ClassLoader class pointer for detecting special objects */
100
J9Class *_atomicMarkableReferenceClass; /**< java.util.concurrent.atomic.AtomicMarkableReference class pointer for detecting special objects */
101
102
protected:
103
public:
104
/**
105
* Return values for getScanType().
106
*/
107
enum ScanType {
108
SCAN_INVALID_OBJECT = 0,
109
SCAN_MIXED_OBJECT = 1,
110
SCAN_POINTER_ARRAY_OBJECT = 2,
111
SCAN_PRIMITIVE_ARRAY_OBJECT = 3,
112
SCAN_REFERENCE_MIXED_OBJECT = 4,
113
SCAN_CLASS_OBJECT = 5,
114
SCAN_CLASSLOADER_OBJECT = 6,
115
SCAN_ATOMIC_MARKABLE_REFERENCE_OBJECT = 7,
116
SCAN_OWNABLESYNCHRONIZER_OBJECT = 8,
117
SCAN_MIXED_OBJECT_LINKED = 9,
118
SCAN_FLATTENED_ARRAY_OBJECT = 10
119
};
120
121
/**
122
* Values for the 'state' field in java.lang.ref.Reference.
123
* Note that these values are mirrored in the Java code. Do not change them.
124
*/
125
enum ReferenceState {
126
REF_STATE_INITIAL = 0, /**< indicates the initial (normal) state for a Reference object. Referent is weak. */
127
REF_STATE_CLEARED = 1, /**< indicates that the Reference object has been cleared, either by the GC or by the Java clear() API. Referent is null or strong. */
128
REF_STATE_ENQUEUED = 2, /**< indicates that the Reference object has been cleared and enqueued on its ReferenceQueue. Referent is null or strong. */
129
REF_STATE_REMEMBERED = 3, /**< indicates that the Reference object was discovered by a global cycle and that the current local GC cycle must return it to that list and restore the state to INITIAL. */
130
};
131
132
/*
133
* Member functions
134
*/
135
private:
136
/**
137
* Determine the scan type for an instant of the specified class.
138
* The class has the J9AccClassGCSpecial bit set.
139
* @param[in] objectClazz the class of the object to identify
140
* @return one of the ScanType constants
141
*/
142
ScanType getSpecialClassScanType(J9Class *objectClazz);
143
144
/**
145
* Examine all classes as they are loaded to determine if they require the J9AccClassGCSpecial bit.
146
* These classes are handled specially by GC_ObjectModel::getScanType()
147
*/
148
static void internalClassLoadHook(J9HookInterface** hook, uintptr_t eventNum, void* eventData, void* userData);
149
150
/**
151
* Update all of the GC special class pointers to their most current version after a class
152
* redefinition has occurred.
153
*/
154
static void classesRedefinedHook(J9HookInterface** hook, uintptr_t eventNum, void* eventData, void* userData);
155
156
/**
157
* Returns the shape of an class.
158
* @param objectPtr Pointer to object whose shape is required.
159
* @return The shape of the object
160
*/
161
MMINLINE uintptr_t
162
getClassShape(J9Object *objectPtr)
163
{
164
J9Class* clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, this);
165
return J9GC_CLASS_SHAPE(clazz);
166
}
167
168
public:
169
/**
170
* Determine the ScanType code for objects of the specified class. This code determines how instances should be scanned.
171
* @param clazz[in] the class of the object to be scanned
172
* @return a ScanType code, SCAN_INVALID_OBJECT if the code cannot be determined due to an error
173
*/
174
MMINLINE ScanType
175
getScanType(J9Class *clazz)
176
{
177
ScanType result = SCAN_INVALID_OBJECT;
178
179
switch(J9GC_CLASS_SHAPE(clazz)) {
180
case OBJECT_HEADER_SHAPE_MIXED:
181
{
182
uintptr_t classFlags = J9CLASS_FLAGS(clazz) & (J9AccClassReferenceMask | J9AccClassGCSpecial | J9AccClassOwnableSynchronizer);
183
if (0 == classFlags) {
184
if (0 != clazz->selfReferencingField1) {
185
result = SCAN_MIXED_OBJECT_LINKED;
186
} else {
187
result = SCAN_MIXED_OBJECT;
188
}
189
} else {
190
if (0 != (classFlags & J9AccClassReferenceMask)) {
191
result = SCAN_REFERENCE_MIXED_OBJECT;
192
} else if (0 != (classFlags & J9AccClassGCSpecial)) {
193
result = getSpecialClassScanType(clazz);
194
} else if (0 != (classFlags & J9AccClassOwnableSynchronizer)) {
195
result = SCAN_OWNABLESYNCHRONIZER_OBJECT;
196
} else {
197
/* Assert_MM_unreachable(); */
198
assert(false);
199
}
200
}
201
break;
202
}
203
case OBJECT_HEADER_SHAPE_POINTERS:
204
if (J9_IS_J9CLASS_FLATTENED(clazz)) {
205
if (J9CLASS_HAS_REFERENCES(((J9ArrayClass *)clazz)->leafComponentType)) {
206
result = SCAN_FLATTENED_ARRAY_OBJECT;
207
} else {
208
result = SCAN_PRIMITIVE_ARRAY_OBJECT;
209
}
210
} else {
211
result = SCAN_POINTER_ARRAY_OBJECT;
212
}
213
break;
214
case OBJECT_HEADER_SHAPE_DOUBLES:
215
case OBJECT_HEADER_SHAPE_BYTES:
216
case OBJECT_HEADER_SHAPE_WORDS:
217
case OBJECT_HEADER_SHAPE_LONGS:
218
/* Must be a primitive array*/
219
result = SCAN_PRIMITIVE_ARRAY_OBJECT;
220
break;
221
default:
222
result = SCAN_INVALID_OBJECT;
223
}
224
225
return result;
226
}
227
228
MMINLINE ScanType
229
getScanType(J9Object *objectPtr)
230
{
231
J9Class *clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, this);
232
return getScanType(clazz);
233
}
234
235
/**
236
* Returns the depth of an object.
237
* @param objectPtr Pointer to object whose depth is required.
238
* @return The depth of the object
239
*/
240
MMINLINE uintptr_t
241
getObjectDepth(J9Object *objectPtr)
242
{
243
return (getRememberedBits(objectPtr) & OBJECT_HEADER_DEPTH_MASK);
244
}
245
246
/**
247
* Returns TRUE if a class is indexable, FALSE otherwise.
248
* @param clazz Pointer to the class
249
* @return TRUE if a class is indexable, FALSE otherwise
250
*/
251
MMINLINE bool
252
isIndexable(J9Class* clazz)
253
{
254
return J9GC_CLASS_IS_ARRAY(clazz);
255
}
256
257
using GC_ObjectModelBase::isIndexable;
258
259
/**
260
* Returns TRUE if an object has a OBJECT_HEADER_SHAPE_POINTERS shape, FALSE otherwise.
261
* @param objectPtr Pointer to an object
262
* @return TRUE if an object has a OBJECT_HEADER_SHAPE_POINTERS shape, FALSE otherwise
263
*/
264
MMINLINE bool
265
isObjectArray(J9Object *objectPtr)
266
{
267
J9Class* clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, this);
268
return (OBJECT_HEADER_SHAPE_POINTERS == J9GC_CLASS_SHAPE(clazz));
269
}
270
271
/**
272
* @see isObjectArray(J9Object *objectPtr)
273
*/
274
MMINLINE bool
275
isObjectArray(J9IndexableObject *objectPtr)
276
{
277
return isObjectArray((J9Object*)objectPtr);
278
}
279
280
/**
281
* Returns TRUE if an object is primitive array, FALSE otherwise.
282
* @param objectPtr Pointer to an object
283
* @return TRUE if an object is primitive array, FALSE otherwise
284
*/
285
MMINLINE bool
286
isPrimitiveArray(J9Object *objectPtr)
287
{
288
bool isPrimitiveArray = false;
289
290
switch(getClassShape(objectPtr)) {
291
case OBJECT_HEADER_SHAPE_BYTES:
292
case OBJECT_HEADER_SHAPE_WORDS:
293
case OBJECT_HEADER_SHAPE_LONGS:
294
case OBJECT_HEADER_SHAPE_DOUBLES:
295
isPrimitiveArray = true;
296
break;
297
default:
298
isPrimitiveArray = false;
299
break;
300
}
301
302
return isPrimitiveArray;
303
}
304
305
/**
306
* @see isPrimitiveArray(J9Object *objectPtr)
307
*/
308
MMINLINE bool
309
isPrimitiveArray(J9IndexableObject *objectPtr)
310
{
311
return isPrimitiveArray((J9Object*)objectPtr);
312
}
313
314
/**
315
* Determine whether or not the given object is a double array
316
*
317
* @return true if objectPtr is a double array
318
* @return false otherwise
319
*/
320
MMINLINE bool
321
isDoubleArray(J9Object* objectPtr)
322
{
323
return (OBJECT_HEADER_SHAPE_DOUBLES == getClassShape(objectPtr));
324
}
325
326
/**
327
* @see isDoubleArray(J9Object* objectPtr)
328
*/
329
MMINLINE bool
330
isDoubleArray(J9IndexableObject *objectPtr)
331
{
332
return isDoubleArray((J9Object*)objectPtr);
333
}
334
335
/**
336
* Check is indexable bit set properly:
337
* must be set for arrays and primitive arrays
338
* must not be set for all others
339
* @param objectPtr Pointer to an object
340
* @return TRUE if indexable bit is set properly
341
*/
342
MMINLINE bool
343
checkIndexableFlag(J9Object *objectPtr)
344
{
345
bool result = false;
346
347
if (isObjectArray(objectPtr) || isPrimitiveArray(objectPtr)) {
348
if (isIndexable(objectPtr)) {
349
result = true;
350
}
351
} else {
352
if (!isIndexable(objectPtr)) {
353
result = true;
354
}
355
}
356
return result;
357
}
358
359
/**
360
* Determine the basic hash code for the specified object. This may modify the object. For example, it may
361
* set the HAS_BEEN_HASHED bit in the object's header. Object must not be NULL.
362
*
363
* @param object[in] the object to be hashed
364
* @return the persistent, basic hash code for the object
365
*/
366
MMINLINE int32_t
367
getObjectHashCode(J9JavaVM *vm, J9Object *object)
368
{
369
int32_t result = 0;
370
#if defined (OMR_GC_MODRON_COMPACTION) || defined (J9VM_GC_GENERATIONAL)
371
if (hasBeenMoved(object)) {
372
uintptr_t hashOffset = getHashcodeOffset(object);
373
result = *(int32_t*)((uint8_t*)object + hashOffset);
374
} else {
375
atomicSetObjectFlags(object, 0, OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS);
376
result = convertValueToHash(vm, (uintptr_t)object);
377
}
378
#else /* defined (OMR_GC_MODRON_COMPACTION) || defined (J9VM_GC_GENERATIONAL) */
379
result = computeObjectAddressToHash(vm, object);
380
#endif /* defined (OMR_GC_MODRON_COMPACTION) || defined (J9VM_GC_GENERATIONAL) */
381
return result;
382
}
383
384
/**
385
* Initialize the basic hash code for the specified object.
386
* Space for the hash slot must already exist.
387
*
388
* @note Sets OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS | OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS flags
389
* @param object[in] the object to be initialized.
390
*/
391
MMINLINE void
392
initializeHashSlot(J9JavaVM* vm, J9Object *objectPtr)
393
{
394
#if defined (OMR_GC_MODRON_COMPACTION) || defined (J9VM_GC_GENERATIONAL)
395
uintptr_t hashOffset = getHashcodeOffset(objectPtr);
396
uint32_t *hashCodePointer = (uint32_t*)((uint8_t*)objectPtr + hashOffset);
397
398
*hashCodePointer = convertValueToHash(vm, (uintptr_t)objectPtr);
399
setObjectHasBeenMoved(objectPtr);
400
#endif /* defined (OMR_GC_MODRON_COMPACTION) || defined (J9VM_GC_GENERATIONAL) */
401
}
402
403
/**
404
* Returns TRUE if an object has been hashed or moved, FALSE otherwise.
405
* @param objectPtr Object to test
406
* @return TRUE if an object has been hashed or moved, FALSE otherwise
407
*/
408
MMINLINE bool
409
hasBeenHashed(J9Object *objectPtr)
410
{
411
return hasBeenHashed(getObjectFlags(objectPtr));
412
}
413
414
MMINLINE bool
415
hasBeenHashed(uintptr_t objectFlags)
416
{
417
return 0 != (objectFlags & (OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS | OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS));
418
}
419
420
/**
421
* Returns TRUE if an object has been hashed but not moved, FALSE otherwise.
422
* @param objectPtr Object to test
423
* @return TRUE if an object has been hashed but not moved, FALSE otherwise
424
*/
425
MMINLINE bool
426
hasJustBeenHashed(J9Object *objectPtr)
427
{
428
return hasJustBeenHashed(getObjectFlags(objectPtr));
429
}
430
431
MMINLINE bool
432
hasJustBeenHashed(uintptr_t objectFlags)
433
{
434
return OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS == (objectFlags & OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS);
435
}
436
437
/**
438
* Returns TRUE if an object has been moved, regardless of state of hashed bit, FALSE otherwise.
439
* @param objectPtr Object to test
440
* @return TRUE if an object has been moved, regardless of state of hashed bit, FALSE otherwise
441
*/
442
MMINLINE bool
443
hasBeenMoved(J9Object *objectPtr)
444
{
445
return hasBeenMoved(getObjectFlags(objectPtr));
446
}
447
448
MMINLINE bool
449
hasBeenMoved(uintptr_t objectFlags)
450
{
451
return OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS == (objectFlags & OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS);
452
}
453
454
/**
455
* Returns TRUE if an object has been moved and hashed bit cleared, FALSE otherwise.
456
* @param objectPtr Object to test
457
* @return TRUE if an object has been moved and hashed bit cleared, FALSE otherwise
458
*/
459
MMINLINE bool
460
hasRecentlyBeenMoved(J9Object *objectPtr)
461
{
462
return hasRecentlyBeenMoved(getObjectFlags(objectPtr));
463
}
464
465
MMINLINE bool
466
hasRecentlyBeenMoved(uintptr_t objectFlags)
467
{
468
return OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS == (objectFlags & (OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS | OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS));
469
}
470
471
/**
472
* Set OBJECT_HEADER_HAS_BEEN_MOVED and OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS flags
473
* @param objectPtr Pointer to an object
474
*/
475
MMINLINE void
476
setObjectHasBeenMoved(omrobjectptr_t objectPtr)
477
{
478
setObjectFlags(objectPtr, 0, OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS | OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS);
479
}
480
481
/**
482
* Set OBJECT_HEADER_HAS_BEEN_MOVED flag / clear OBJECT_HEADER_HAS_BEEN_HASHED bit
483
* @param objectPtr Pointer to an object
484
*/
485
MMINLINE void
486
setObjectJustHasBeenMoved(omrobjectptr_t objectPtr)
487
{
488
setObjectFlags(objectPtr, OBJECT_HEADER_HAS_BEEN_HASHED_IN_CLASS, OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS);
489
}
490
491
MMINLINE int32_t
492
computeObjectHash(MM_ForwardedHeader *forwardedHeader)
493
{
494
return convertValueToHash(_javaVM, (uintptr_t)forwardedHeader->getObject());
495
}
496
497
MMINLINE uintptr_t
498
getHashcodeOffset(omrobjectptr_t objectPtr) {
499
return getObjectModelDelegate()->getHashcodeOffset(objectPtr);
500
}
501
502
/**
503
* Same as getConsumedSizeInBytesWithHeader, except that it returns the size
504
* the object will consume if it is moved. i.e. it includes space for the
505
* hash code slot.
506
* @param objectPtr Pointer to an object
507
* @return The consumed heap size of an object, in bytes, including the header
508
*/
509
MMINLINE uintptr_t
510
getConsumedSizeInBytesWithHeaderForMove(J9Object *objectPtr)
511
{
512
return adjustSizeInBytes(getObjectModelDelegate()->getObjectSizeInBytesWithHeader(objectPtr, hasBeenHashed(objectPtr)));
513
}
514
515
/**
516
* Same as getConsumedSizeInBytesWithHeader, except that it returns the size
517
* the object will consume if it is moved. i.e. it includes space for the
518
* hash code slot.
519
* @param objectPtr Pointer to an object
520
* @return The consumed heap size of an object, in bytes, including the header
521
*/
522
MMINLINE uintptr_t
523
getConsumedSizeInBytesWithHeaderBeforeMove(J9Object *objectPtr)
524
{
525
return adjustSizeInBytes(getObjectModelDelegate()->getObjectSizeInBytesWithHeader(objectPtr, hasBeenMoved(objectPtr) && !hasRecentlyBeenMoved(objectPtr)));
526
}
527
528
#if defined(J9VM_GC_MODRON_SCAVENGER)
529
/**
530
* Extract the class pointer from an unforwarded object.
531
*
532
* This method will assert if the object has been marked as forwarded.
533
*
534
* @param[in] pointer to forwardedHeader the MM_ForwardedHeader instance encapsulating the object
535
* @return pointer to the J9Class from the object encapsulated by forwardedHeader
536
* @see MM_ForwardingHeader::isForwardedObject()
537
*/
538
MMINLINE J9Class *
539
getPreservedClass(MM_ForwardedHeader *forwardedHeader)
540
{
541
return (J9Class *)((uintptr_t)(forwardedHeader->getPreservedSlot()) & J9GC_J9OBJECT_CLAZZ_ADDRESS_MASK);
542
}
543
544
/**
545
* Update the new version of this object after it has been copied. This undoes any damaged
546
* caused by installing the forwarding pointer into the original prior to the copy, and sets
547
* the object age.
548
*
549
* This will install the correct (i.e. unforwarded) class pointer, update the hashed/moved
550
* flags and install the hash code if the object has been hashed but not previously moved.
551
*
552
* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
553
* @param[in] destinationObjectPtr pointer to the copied object to be fixed up
554
* @param[in] objectAge the age to set in the copied object
555
*/
556
MMINLINE void
557
fixupForwardedObject(MM_ForwardedHeader *forwardedHeader, omrobjectptr_t destinationObjectPtr, uintptr_t objectAge)
558
{
559
GC_ObjectModelBase::fixupForwardedObject(forwardedHeader, destinationObjectPtr, objectAge);
560
561
if (isIndexable(forwardedHeader)) {
562
/* Updates internal field of indexable objects. Every indexable object have an extra field
563
* that can be used to store any extra information about the indexable object. One use case is
564
* OpenJ9 where we use this field to point to array data. In this case it will always point to
565
* the address right after the header, in case of contiguous data it will point to the data
566
* itself, and in case of discontiguous arraylet it will point to the first arrayiod. How to
567
* updated dataAddr is up to the target language that must override fixupDataAddr */
568
_indexableObjectModel->fixupDataAddr(forwardedHeader, destinationObjectPtr);
569
}
570
571
fixupHashFlagsAndSlot(forwardedHeader, destinationObjectPtr);
572
}
573
574
/**
575
* This will install the correct (i.e. unforwarded) class pointer, update the hashed/moved
576
* flags and install the hash code if the object has been hashed but not previously moved.
577
*
578
* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
579
* @param[in] destinationObjectPtr pointer to the copied object to be fixed up
580
*/
581
MMINLINE void
582
fixupHashFlagsAndSlot(MM_ForwardedHeader *forwardedHeader, omrobjectptr_t destinationObjectPtr)
583
{
584
/* To have ability to backout last scavenge we need to recognize objects just moved (moved first time) in current scavenge
585
*
586
* Bits State
587
* --------------------------------
588
* m h moved / hashed bits
589
* 0 0 not moved / not hashed
590
* 0 1 not moved / hashed
591
* 1 0 just moved / hashed
592
* 1 1 moved / hashed
593
* --------------------------------
594
*/
595
if (hasBeenMoved(getPreservedFlags(forwardedHeader))) {
596
if (hasRecentlyBeenMoved(getPreservedFlags(forwardedHeader))) {
597
/* Moved bit set / hashed bit not set means "moved previous scavenge" so set moved/hashed */
598
setObjectHasBeenMoved(destinationObjectPtr);
599
}
600
} else if (hasBeenHashed(getPreservedFlags(forwardedHeader))) {
601
/* The object has been hashed and has not been moved so we must store the previous address into the hashcode slot at hashcode offset. */
602
uintptr_t hashOffset;
603
J9Class *clazz = getPreservedClass(forwardedHeader);
604
if (isIndexable(clazz)) {
605
hashOffset = _indexableObjectModel->getPreservedHashcodeOffset(forwardedHeader);
606
} else {
607
hashOffset = _mixedObjectModel->getHashcodeOffset(clazz);
608
}
609
610
uint32_t *hashCodePointer = (uint32_t*)((uint8_t*) destinationObjectPtr + hashOffset);
611
*hashCodePointer = convertValueToHash(_javaVM, (uintptr_t)forwardedHeader->getObject());
612
setObjectJustHasBeenMoved(destinationObjectPtr);
613
}
614
}
615
616
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */
617
618
#if defined(OMR_GC_REALTIME)
619
/**
620
* Set GC_OVERFLOW bit atomically
621
* @param objectPtr Pointer to an object
622
* @return true, if GC_OVERFLOW bit has been set this call
623
*/
624
MMINLINE bool
625
atomicSetOverflowBit(J9Object *objectPtr)
626
{
627
return atomicSetObjectFlags(objectPtr, 0, GC_OVERFLOW);
628
}
629
630
/**
631
* Clear GC_OVERFLOW bit atomically
632
* @param objectPtr Pointer to an object
633
* @return true, if GC_OVERFLOW bit has been cleared this call
634
*/
635
MMINLINE bool
636
atomicClearOverflowBit(J9Object *objectPtr)
637
{
638
return atomicSetObjectFlags(objectPtr, GC_OVERFLOW, 0);
639
}
640
641
/**
642
* Return back true if GC_OVERFLOW bit is set
643
* @param objectPtr Pointer to an object
644
* @return true, if GC_OVERFLOW bit is set
645
*/
646
MMINLINE bool
647
isOverflowBitSet(J9Object *objectPtr)
648
{
649
return (GC_OVERFLOW == (J9GC_J9OBJECT_FLAGS_FROM_CLAZZ(objectPtr, this) & GC_OVERFLOW));
650
}
651
#endif /* defined(OMR_GC_REALTIME) */
652
653
/**
654
* Set class in clazz slot in object header, with header flags.
655
* @param objectPtr Pointer to an object
656
* @param clazz class pointer to set
657
* @param flags flag bits to set
658
*/
659
MMINLINE void
660
setObjectClassAndFlags(J9Object *objectPtr, J9Class* clazz, uintptr_t flags)
661
{
662
uintptr_t classBits = (uintptr_t)clazz;
663
uintptr_t flagsBits = flags & (uintptr_t)OMR_OBJECT_METADATA_FLAGS_MASK;
664
if (compressObjectReferences()) {
665
*((uint32_t*)getObjectHeaderSlotAddress(objectPtr)) = (uint32_t)(classBits | flagsBits);
666
} else {
667
*((uintptr_t*)getObjectHeaderSlotAddress(objectPtr)) = (classBits | flagsBits);
668
}
669
}
670
671
/**
672
* Set class in clazz slot in object header, preserving header flags
673
* @param objectPtr Pointer to an object
674
* @param clazz class pointer to set
675
*/
676
MMINLINE void
677
setObjectClass(J9Object *objectPtr, J9Class* clazz)
678
{
679
setObjectClassAndFlags(objectPtr, clazz, getObjectFlags(objectPtr));
680
}
681
682
/**
683
* Initialize the receiver, a new instance of GC_ObjectModel
684
*
685
* @return true on success, false on failure
686
*/
687
virtual bool initialize(MM_GCExtensionsBase *extensions);
688
689
/**
690
* Tear down the receiver
691
*/
692
virtual void tearDown(MM_GCExtensionsBase *extensions);
693
694
/**
695
* Constructor.
696
*/
697
GC_ObjectModel()
698
: GC_ObjectModelBase()
699
{}
700
};
701
702
#endif /* OBJECTMODEL_HPP_ */
703
704