Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_glue_java/ObjectModelDelegate.hpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 2017, 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
#ifndef OBJECTMODELDELEGATE_HPP_
24
#define OBJECTMODELDELEGATE_HPP_
25
26
#include "j9nonbuilder.h"
27
#include "omr.h"
28
#include "objectdescription.h"
29
#include "util_api.h"
30
31
#include "ArrayObjectModel.hpp"
32
#include "ForwardedHeader.hpp"
33
#include "MixedObjectModel.hpp"
34
35
class MM_AllocateInitialization;
36
class MM_EnvironmentBase;
37
38
#define CLI_THREAD_TYPE J9VMThread
39
40
struct CLI_THREAD_TYPE;
41
42
/**
43
* GC_ObjectModelBase is inaccessible from this class. Some factors are redefined here.
44
*/
45
class GC_ObjectModelDelegate
46
{
47
/*
48
* Member data and types
49
*/
50
private:
51
static const uintptr_t _objectHeaderSlotOffset = 0;
52
static const uintptr_t _objectHeaderSlotFlagsShift = 0;
53
54
const uintptr_t _delegateHeaderSlotFlagsMask;
55
56
GC_ArrayObjectModel *_arrayObjectModel;
57
GC_MixedObjectModel *_mixedObjectModel;
58
59
protected:
60
#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)
61
bool _compressObjectReferences;
62
#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */
63
public:
64
65
/*
66
* Member functions
67
*/
68
private:
69
protected:
70
public:
71
/**
72
* Return back true if object references are compressed
73
* @return true, if object references are compressed
74
*/
75
MMINLINE bool
76
compressObjectReferences()
77
{
78
return OMR_COMPRESS_OBJECT_REFERENCES(_compressObjectReferences);
79
}
80
81
#if defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS)
82
/**
83
* Set the compress object references flag.
84
*/
85
MMINLINE void
86
setCompressObjectReferences(bool compress)
87
{
88
_compressObjectReferences = compress;
89
}
90
#endif /* defined(OMR_GC_COMPRESSED_POINTERS) && defined(OMR_GC_FULL_POINTERS) */
91
92
/**
93
* Set the array object model.
94
*/
95
MMINLINE void
96
setArrayObjectModel(GC_ArrayObjectModel *arrayObjectModel)
97
{
98
_arrayObjectModel = arrayObjectModel;
99
}
100
101
/**
102
* Get the array object model.
103
*/
104
MMINLINE GC_ArrayObjectModel*
105
getArrayObjectModel()
106
{
107
return _arrayObjectModel;
108
}
109
110
/**
111
* Set the array object model.
112
*/
113
MMINLINE void
114
setMixedObjectModel(GC_MixedObjectModel *mixedObjectModel)
115
{
116
_mixedObjectModel = mixedObjectModel;
117
}
118
119
/**
120
* Get the array object model.
121
*/
122
MMINLINE GC_MixedObjectModel*
123
getMixedObjectModel()
124
{
125
return _mixedObjectModel;
126
}
127
128
/**
129
* This method is called for each heap object during heap walks. If the received object holds
130
* an indirect object reference (ie a reference to an object that might not otherwise be walked),
131
* a pointer to the indirect object should be returned here.
132
*
133
* @param objectPtr the object to obtain indirect reference from
134
* @return a pointer to the indirect object, or NULL if none
135
*/
136
MMINLINE omrobjectptr_t
137
getIndirectObject(omrobjectptr_t objectPtr)
138
{
139
J9Class *clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, this);
140
return J9VM_J9CLASS_TO_HEAPCLASS(clazz);
141
}
142
143
/**
144
* Get the byte offset from object address to object hash code slot.
145
*/
146
MMINLINE uintptr_t
147
getHashcodeOffset(omrobjectptr_t objectPtr) {
148
UDATA offset = 0;
149
150
if (isIndexable(objectPtr)) {
151
offset = _arrayObjectModel->getHashcodeOffset((J9IndexableObject *)objectPtr);
152
} else {
153
offset = _mixedObjectModel->getHashcodeOffset(objectPtr);
154
}
155
156
return offset;
157
}
158
159
/**
160
* Get the offset of the slot containing the object header.
161
*/
162
MMINLINE uintptr_t
163
getObjectHeaderSlotOffset()
164
{
165
return _objectHeaderSlotOffset;
166
}
167
168
/**
169
* Get the bit offset to the flags byte in object headers.
170
*/
171
MMINLINE uintptr_t
172
getObjectHeaderSlotFlagsShift()
173
{
174
return _objectHeaderSlotFlagsShift;
175
}
176
177
/**
178
* Get the exact size of the object header, in bytes.
179
*/
180
MMINLINE uintptr_t
181
getObjectHeaderSizeInBytes(omrobjectptr_t objectPtr)
182
{
183
uintptr_t headerSize = 0;
184
185
if (isIndexable(objectPtr)) {
186
headerSize = _arrayObjectModel->getHeaderSize((J9IndexableObject *)objectPtr);
187
} else {
188
headerSize = _mixedObjectModel->getHeaderSize(objectPtr);
189
}
190
191
return headerSize;
192
}
193
194
/**
195
* Get the exact size of the object data, in bytes. This excludes the size of the object header,
196
* hash code and any bytes added for object alignment. If the object has a discontiguous representation,
197
* this method should return the size of the root object that the discontiguous parts depend from.
198
*
199
* @param[in] objectPtr points to the object to determine size for
200
* @return the exact size of an object, in bytes, excluding padding bytes and header bytes
201
*/
202
MMINLINE uintptr_t
203
getObjectSizeInBytesWithoutHeader(omrobjectptr_t objectPtr)
204
{
205
uintptr_t dataSize = 0;
206
207
if (isIndexable(objectPtr)) {
208
dataSize = _arrayObjectModel->getSizeInBytesWithoutHeader((J9IndexableObject *)objectPtr);
209
} else {
210
dataSize = _mixedObjectModel->getSizeInBytesWithoutHeader(objectPtr);
211
}
212
213
return dataSize;
214
}
215
216
/**
217
* Get the exact total size of the object data, in bytes. This includes the size of the object
218
* header and hash code but excludes bytes added for object alignment. If the object has a
219
* discontiguous representation, this method should return the size of the root object that the
220
* discontiguous parts depend from.
221
*
222
* @param[in] objectPtr points to the object to determine size for
223
* @return the exact size of an object, in bytes, excluding padding bytes and header bytes
224
*/
225
MMINLINE uintptr_t
226
getObjectSizeInBytesWithHeader(omrobjectptr_t objectPtr, bool includeHashCode)
227
{
228
uintptr_t dataSize = 0;
229
230
/* get header + data size */
231
if (isIndexable(objectPtr)) {
232
dataSize = _arrayObjectModel->getSizeInBytesWithoutHeader((J9IndexableObject *)objectPtr);
233
dataSize += _arrayObjectModel->getHeaderSize((J9IndexableObject *)objectPtr);
234
} else {
235
dataSize = _mixedObjectModel->getSizeInBytesWithoutHeader(objectPtr);
236
dataSize += _mixedObjectModel->getHeaderSize(objectPtr);
237
}
238
239
/* include space for hash code reservation */
240
if (includeHashCode) {
241
if (getHashcodeOffset(objectPtr) == dataSize) {
242
dataSize += sizeof(uintptr_t);
243
}
244
}
245
246
return dataSize;
247
}
248
249
/**
250
* Get the total footprint of an object, in bytes, including the object header and all data.
251
* If the object has a discontiguous representation, this method should return the size of
252
* the root object plus the total of all the discontiguous parts of the object.
253
*
254
* @param[in] objectPtr points to the object to determine size for
255
* @return the total size of an object, in bytes, including discontiguous parts
256
*/
257
MMINLINE uintptr_t
258
getTotalFootprintInBytes(omrobjectptr_t objectPtr)
259
{
260
uintptr_t dataSize = getObjectSizeInBytesWithHeader(objectPtr);
261
262
if (isIndexable(objectPtr)) {
263
// add size of arraylet leaves (if any)
264
dataSize += _arrayObjectModel->externalArrayletsSize((J9IndexableObject *)objectPtr);
265
}
266
267
return dataSize;
268
}
269
270
/**
271
* Get the exact size of the object data, in bytes. This includes the size of the object header and
272
* hash slot (if allocated) and excludes any bytes added for object alignment. If the object has a
273
* discontiguous representation, this method should return the size of the root object that the
274
* discontiguous parts depend from.
275
*
276
* @param[in] objectPtr points to the object to determine size for
277
* @return the exact size of an object, in bytes, excluding padding bytes and header bytes
278
*/
279
MMINLINE uintptr_t
280
getObjectSizeInBytesWithHeader(omrobjectptr_t objectPtr)
281
{
282
uintptr_t flags = 0;
283
if (compressObjectReferences()) {
284
flags = *(uint32_t*)objectPtr;
285
} else {
286
flags = *(uintptr_t*)objectPtr;
287
}
288
bool hasBeenMoved = J9_ARE_ANY_BITS_SET((flags >> getObjectHeaderSlotFlagsShift()) & _delegateHeaderSlotFlagsMask, OBJECT_HEADER_HAS_BEEN_MOVED_IN_CLASS);
289
return getObjectSizeInBytesWithHeader(objectPtr, hasBeenMoved);
290
}
291
292
/**
293
* If object initialization fails for any reason, this method must return NULL. In that case, the heap
294
* memory allocated for the object will become floating garbage in the heap and will be recovered in
295
* the next GC cycle.
296
*
297
* @param[in] env points to the environment for the calling thread
298
* @param[in] allocatedBytes points to the heap memory allocated for the object
299
* @param[in] allocateInitialization points to the MM_AllocateInitialization instance used to allocate the heap memory
300
* @return pointer to the initialized object, or NULL if initialization fails
301
*/
302
omrobjectptr_t initializeAllocation(MM_EnvironmentBase *env, void *allocatedBytes, MM_AllocateInitialization *allocateInitialization);
303
304
/**
305
* Returns TRUE if an object is indexable, FALSE otherwise. Languages that support indexable objects
306
* (eg, arrays) must provide an implementation that distinguished indexable from scalar objects.
307
*
308
* @param objectPtr pointer to the object
309
* @return TRUE if object is indexable, FALSE otherwise
310
*/
311
MMINLINE bool
312
isIndexable(omrobjectptr_t objectPtr)
313
{
314
J9Class* clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, this);
315
return J9GC_CLASS_IS_ARRAY(clazz);
316
}
317
318
/**
319
* The following methods (defined(OMR_GC_MODRON_SCAVENGER)) are required if generational GC is
320
* configured for the build (--enable-OMR_GC_MODRON_SCAVENGER in configure_includes/configure_*.mk).
321
* They typically involve a MM_ForwardedHeader object, and allow information about the forwarded
322
* object to be obtained.
323
*/
324
#if defined(OMR_GC_MODRON_SCAVENGER)
325
/**
326
* Returns TRUE if the object referred to by the forwarded header is indexable.
327
*
328
* @param forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
329
* @return TRUE if object is indexable, FALSE otherwise
330
*/
331
MMINLINE bool
332
isIndexable(MM_ForwardedHeader *forwardedHeader)
333
{
334
J9Class* clazz = (J9Class *)((uintptr_t)(forwardedHeader->getPreservedSlot()) & ~(UDATA)_delegateHeaderSlotFlagsMask);
335
return J9GC_CLASS_IS_ARRAY(clazz);
336
}
337
338
/**
339
* Get the instance size (total) in bytes of a forwarded object from the forwarding pointer.
340
*
341
* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
342
* @return The instance size (total) in bytes of the forwarded object
343
*/
344
MMINLINE uintptr_t
345
getForwardedObjectSizeInBytes(MM_ForwardedHeader *forwardedHeader)
346
{
347
uintptr_t size = 0;
348
uintptr_t preservedSlot = (uintptr_t)(forwardedHeader->getPreservedSlot());
349
J9Class* clazz = (J9Class *)(preservedSlot & ~(UDATA)_delegateHeaderSlotFlagsMask);
350
351
if (J9GC_CLASS_IS_ARRAY(clazz)) {
352
uintptr_t elements = 0;
353
#if defined (OMR_GC_COMPRESSED_POINTERS)
354
if (compressObjectReferences()) {
355
elements = forwardedHeader->getPreservedOverlap();
356
} else
357
#endif /* defined (OMR_GC_COMPRESSED_POINTERS) */
358
{
359
elements = ((J9IndexableObjectContiguousFull *)forwardedHeader->getObject())->size;
360
}
361
362
if (0 == elements) {
363
/* Discontiguous */
364
if (compressObjectReferences()) {
365
elements = ((J9IndexableObjectDiscontiguousCompressed *)forwardedHeader->getObject())->size;
366
} else {
367
elements = ((J9IndexableObjectDiscontiguousFull *)forwardedHeader->getObject())->size;
368
}
369
}
370
371
uintptr_t dataSize = _arrayObjectModel->getDataSizeInBytes(clazz, elements);
372
GC_ArrayletObjectModel::ArrayLayout layout = _arrayObjectModel->getArrayletLayout(clazz, dataSize);
373
size = _arrayObjectModel->getSizeInBytesWithHeader(clazz, layout, elements);
374
} else {
375
size = _mixedObjectModel->getSizeInBytesWithoutHeader(clazz) + J9GC_OBJECT_HEADER_SIZE(this);
376
}
377
378
return size;
379
}
380
381
/**
382
* Returns the field offset of the hottest field of the object referred to by the forwarded header.
383
* Valid if scavenger dynamicBreadthFirstScanOrdering is enabled.
384
*
385
* @param forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
386
* @return the offset of the hottest field of the given object referred to by the forwarded header, return U_8_MAX if a hot field does not exist
387
*/
388
MMINLINE uint8_t
389
getHotFieldOffset(MM_ForwardedHeader *forwardedHeader)
390
{
391
J9Class* hotClass = ((J9Class *)(((uintptr_t)(forwardedHeader->getPreservedSlot())) & ~(UDATA)_delegateHeaderSlotFlagsMask));
392
if (hotClass->hotFieldsInfo != NULL) {
393
return hotClass->hotFieldsInfo->hotFieldOffset1;
394
}
395
396
return U_8_MAX;
397
}
398
399
/**
400
* Returns the field offset of the second hottest field of the object referred to by the forwarded header.
401
* Valid if scavenger dynamicBreadthFirstScanOrdering is enabled
402
*
403
* @param forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
404
* @return the offset of the second hottest field of the given object referred to by the forwarded header, return U_8_MAX if the hot field does not exist
405
*/
406
MMINLINE uint8_t
407
getHotFieldOffset2(MM_ForwardedHeader *forwardedHeader)
408
{
409
J9Class* hotClass = ((J9Class *)(((uintptr_t)(forwardedHeader->getPreservedSlot())) & ~(UDATA)_delegateHeaderSlotFlagsMask));
410
if (hotClass->hotFieldsInfo != NULL) {
411
return hotClass->hotFieldsInfo->hotFieldOffset2;
412
}
413
414
return U_8_MAX;
415
}
416
417
/**
418
* Returns the field offset of the third hottest field of the object referred to by the forwarded header.
419
* Valid if scavenger dynamicBreadthFirstScanOrdering is enabled
420
*
421
* @param forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
422
* @return the offset of the third hottest field of the given object referred to by the forwarded header, return U_8_MAX if the hot field does not exist
423
*/
424
MMINLINE uint8_t
425
getHotFieldOffset3(MM_ForwardedHeader *forwardedHeader)
426
{
427
J9Class* hotClass = ((J9Class *)(((uintptr_t)(forwardedHeader->getPreservedSlot())) & ~(UDATA)_delegateHeaderSlotFlagsMask));
428
if (hotClass->hotFieldsInfo != NULL) {
429
return hotClass->hotFieldsInfo->hotFieldOffset3;
430
}
431
432
return U_8_MAX;
433
}
434
435
/**
436
* Return true if the object holds references to heap objects not reachable from reference graph. For
437
* example, an object may be associated with a class and the class may have associated meta-objects
438
* that are in the heap but not directly reachable from the root set. This method is called to
439
* determine whether or not any such objects exist.
440
*
441
* @param env points to environment for the thread
442
* @param objectPtr points to an object
443
* @return true if object holds indirect references to heap objects
444
*/
445
MMINLINE bool
446
hasIndirectObjectReferents(CLI_THREAD_TYPE *thread, omrobjectptr_t objectPtr)
447
{
448
return J9GC_IS_INITIALIZED_HEAPCLASS(thread, objectPtr);
449
}
450
451
/**
452
* Calculate the actual object size and the size adjusted to object alignment. The calculated object size
453
* includes any expansion bytes allocated if the object will grow when moved.
454
*
455
* @param[in] env points to the environment for the calling thread
456
* @param[in] forwardedHeader pointer to the MM_ForwardedHeader instance encapsulating the object
457
* @param[out] objectCopySizeInBytes actual object size
458
* @param[out] objectReserveSizeInBytes size adjusted to object alignment
459
* @param[out] hotFieldAlignmentDescriptor pointer to hot field alignment descriptor for class (or NULL)
460
*/
461
void calculateObjectDetailsForCopy(MM_EnvironmentBase *env, MM_ForwardedHeader *forwardedHeader, uintptr_t *objectCopySizeInBytes, uintptr_t *objectReserveSizeInBytes, uintptr_t *hotFieldAlignmentDescriptor);
462
#endif /* defined(OMR_GC_MODRON_SCAVENGER) */
463
464
/**
465
* Constructor receives a copy of OMR's object flags mask, normalized to low order byte. Delegate
466
* realigns it for internal use.
467
*/
468
GC_ObjectModelDelegate(uintptr_t omrHeaderSlotFlagsMask)
469
: _delegateHeaderSlotFlagsMask(omrHeaderSlotFlagsMask << _objectHeaderSlotFlagsShift)
470
{}
471
472
};
473
474
#endif /* OBJECTMODELDELEGATE_HPP_ */
475
476