Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_api/HeapIteratorAPI.cpp
5985 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2019 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
#include "j9.h"
24
#include "j9cfg.h"
25
#include "j9port.h"
26
#include "modron.h"
27
#include "HeapIteratorAPI.h"
28
#include "ModronAssertions.h"
29
30
#include "ArrayletLeafIterator.hpp"
31
#include "GCExtensionsBase.hpp"
32
#include "HeapIteratorAPIRootIterator.hpp"
33
#include "HeapIteratorAPIBufferedIterator.hpp"
34
#include "HeapRegionDescriptor.hpp"
35
#if defined(OMR_GC_SEGREGATED_HEAP)
36
#include "HeapRegionDescriptorSegregated.hpp"
37
#endif /* defined(OMR_GC_SEGREGATED_HEAP) */
38
#include "HeapRegionIterator.hpp"
39
#include "HeapRegionManager.hpp"
40
#include "MemorySpace.hpp"
41
#include "MemorySubSpace.hpp"
42
#include "MixedObjectIterator.hpp"
43
#include "ObjectAccessBarrier.hpp"
44
#include "OwnableSynchronizerObjectList.hpp"
45
#include "PointerArrayIterator.hpp"
46
#include "SlotObject.hpp"
47
#include "VMInterface.hpp"
48
49
static void
50
initializeRegionDescriptor(
51
J9MM_IterateRegionDescriptor *descriptor,
52
const char* name,
53
UDATA id,
54
UDATA objectAlignment,
55
UDATA objectMinimumSize,
56
void* start,
57
UDATA size);
58
59
static void
60
initializeRegionDescriptor(
61
MM_GCExtensionsBase* extensions,
62
J9MM_IterateRegionDescriptor *descriptor,
63
MM_HeapRegionDescriptor *region);
64
static void
65
initializeObjectDescriptor(
66
J9JavaVM *javaVM,
67
J9MM_IterateObjectDescriptor *descriptor,
68
J9MM_IterateRegionDescriptor *regionDesc,
69
j9object_t object);
70
71
static jvmtiIterationControl
72
iterateRegions(
73
J9JavaVM* vm,
74
J9MM_IterateSpaceDescriptor *space,
75
UDATA flags,
76
jvmtiIterationControl (*func)(J9JavaVM* vm, J9MM_IterateRegionDescriptor *regionDesc, void *userData),
77
void *userData);
78
79
static jvmtiIterationControl
80
iterateRegionObjects(
81
J9JavaVM *vm,
82
J9MM_IterateRegionDescriptor *region,
83
UDATA flags,
84
jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateObjectDescriptor *objectDesc, void *userData),
85
void *userData);
86
87
extern "C" {
88
89
/* used by j9mm_iterate_all_objects */
90
static jvmtiIterationControl internalIterateHeaps(J9JavaVM *vm, J9MM_IterateHeapDescriptor *heap, void *userData);
91
static jvmtiIterationControl internalIterateSpaces(J9JavaVM *vm, J9MM_IterateSpaceDescriptor *space, void *userData);
92
static jvmtiIterationControl internalIterateRegions(J9JavaVM *vm, J9MM_IterateRegionDescriptor *region, void *userData);
93
94
typedef struct J9MM_CallbackDataHolderPrivate{
95
jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateObjectDescriptor *object, void *userData);
96
void *userData;
97
J9PortLibrary *portLibrary;
98
UDATA flags;
99
} J9MM_CallbackDataHolderPrivate;
100
101
102
typedef enum J9MM_RegionType{
103
j9mm_region_type_region = 0
104
} J9MM_RegionType;
105
106
typedef struct J9MM_IterateRegionDescriptorPrivate {
107
J9MM_IterateRegionDescriptor descriptor; /**< Public region descriptor */
108
J9MM_RegionType type; /**< Internal - type of region */
109
} J9MM_IterateRegionDescriptorPrivate;
110
111
#define HEAPITERATORAPI_REGION_NAME_FREE "Free Region"
112
#define HEAPITERATORAPI_REGION_NAME_RESERVED "Reserved Region"
113
#define HEAPITERATORAPI_REGION_NAME_ARRAYLET "Arraylet Region"
114
#define HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_TENURED "Tenured Region"
115
#define HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_NURSERY "Nursery Region"
116
#define HEAPITERATORAPI_REGION_NAME_SEGREGATED_SMALL "Small Region"
117
#define HEAPITERATORAPI_REGION_NAME_SEGREGATED_LARGE "Large Region"
118
#define HEAPITERATORAPI_REGION_NAME_SHARED "Shared Region"
119
#define HEAPITERATORAPI_REGION_NAME "Region"
120
121
/**
122
* Walk all heaps, call user provided function.
123
*
124
* @param flags The flags describing the walk (unused currently)
125
* @param func The function to call on each heap descriptor.
126
* @param userData Pointer to storage for userData.
127
*/
128
jvmtiIterationControl
129
j9mm_iterate_heaps(
130
J9JavaVM *vm,
131
J9PortLibrary *portLibrary,
132
UDATA flags,
133
jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateHeapDescriptor *heapDesc, void *userData),
134
void *userData)
135
{
136
/* There is only one heap currently. Since we can not see the MM_Heap struct in
137
* OOP we will just use an id of 0x1.
138
*/
139
J9MM_IterateHeapDescriptor heapDescriptor;
140
heapDescriptor.name = "Heap";
141
heapDescriptor.id = 0x1;
142
143
return func(vm, &heapDescriptor, userData);
144
}
145
146
/**
147
* Walk all space for the given heap, call user provided function.
148
*
149
* @param heap The descriptor for the heap that should be walked
150
* @param flags The flags describing the walk (unused currently)
151
* @param func The function to call on each region descriptor.
152
* @param userData Pointer to storage for userData.
153
*/
154
jvmtiIterationControl
155
j9mm_iterate_spaces(
156
J9JavaVM *vm,
157
J9PortLibrary *portLibrary,
158
J9MM_IterateHeapDescriptor *heap,
159
UDATA flags,
160
jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateSpaceDescriptor *spaceDesc, void *userData),
161
void *userData)
162
{
163
jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;
164
165
if (NULL == heap) {
166
return JVMTI_ITERATION_CONTINUE;
167
}
168
169
void *defaultMemorySpace = vm->defaultMemorySpace;
170
if (NULL != defaultMemorySpace) {
171
UDATA const referenceSize = J9JAVAVM_REFERENCE_SIZE(vm);
172
J9MM_IterateSpaceDescriptor spaceDesc;
173
spaceDesc.name = MM_MemorySpace::getMemorySpace(defaultMemorySpace)->getName();
174
spaceDesc.id = (UDATA)defaultMemorySpace;
175
spaceDesc.classPointerOffset = TMP_OFFSETOF_J9OBJECT_CLAZZ;
176
spaceDesc.classPointerSize = referenceSize;
177
spaceDesc.fobjectPointerDisplacement = 0;
178
#if defined(OMR_GC_COMPRESSED_POINTERS)
179
if (J9JAVAVM_COMPRESS_OBJECT_REFERENCES(vm)) {
180
spaceDesc.fobjectPointerScale = (UDATA)1 << vm->compressedPointersShift;
181
} else
182
#endif /* OMR_GC_COMPRESSED_POINTERS */
183
{
184
spaceDesc.fobjectPointerScale = 1;
185
}
186
spaceDesc.fobjectSize = referenceSize;
187
spaceDesc.memorySpace = defaultMemorySpace;
188
189
returnCode = func(vm, &spaceDesc, userData);
190
}
191
192
return returnCode;
193
}
194
195
/**
196
* Walk all roots in a heap, call user provided function.
197
*
198
* @param flags The flags describing the walk (unused currently)
199
* @param func The function to call on each heap descriptor.
200
* @param userData Pointer to storage for userData.
201
*/
202
jvmtiIterationControl
203
j9mm_iterate_roots(
204
J9JavaVM *javaVM,
205
J9PortLibrary *portLibrary,
206
UDATA flags,
207
rootIteratorCallBackFunc callBackFunc,
208
void *userData)
209
{
210
211
HeapIteratorAPI_RootIterator rootIterator(javaVM, callBackFunc, flags, userData);
212
213
rootIterator.scanAllSlots();
214
215
return JVMTI_ITERATION_ABORT;
216
}
217
218
/**
219
* Walk all regions for the given heap, call user provided function.
220
* A region may be a J9MemorySegment or a HeapIteratorAPI_Page.
221
*
222
* @param heap The descriptor for the heap that should be walked
223
* @param flags The flags describing the walk: read only (region data only) or prepare heap for walk
224
* @param func The function to call on each region descriptor.
225
* @param userData Pointer to storage for userData.
226
*/
227
jvmtiIterationControl
228
j9mm_iterate_regions(
229
J9JavaVM *vm,
230
J9PortLibrary *portLibrary,
231
J9MM_IterateSpaceDescriptor *space,
232
UDATA flags,
233
jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateRegionDescriptor *regionDesc, void *userData),
234
void *userData)
235
{
236
if (NULL == space) {
237
return JVMTI_ITERATION_CONTINUE;
238
}
239
240
if (j9mm_iterator_flag_regions_read_only != (flags & j9mm_iterator_flag_regions_read_only)) {
241
/* It is not a read-only request - make sure the heap is walkable (flush TLH's, secure heap integrity) */
242
vm->memoryManagerFunctions->j9gc_flush_caches_for_walk(vm);
243
}
244
245
return iterateRegions(vm, space, flags, func, userData);
246
247
}
248
249
/**
250
* Walk all objects for the given region, call user provided function.
251
*
252
* @param heap The descriptor for the region that should be walked
253
* @param flags The flags describing the walk (0 or j9mm_iterator_objects_flag_fix_dead_objects)
254
* @param func The function to call on each object descriptor.
255
* @param userData Pointer to storage for userData.
256
*/
257
jvmtiIterationControl
258
j9mm_iterate_region_objects(
259
J9JavaVM *vm,
260
J9PortLibrary *portLibrary,
261
J9MM_IterateRegionDescriptor *region,
262
UDATA flags,
263
jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateObjectDescriptor *objectDesc, void *userData),
264
void *userData)
265
{
266
J9MM_IterateRegionDescriptorPrivate *privateRegion = (J9MM_IterateRegionDescriptorPrivate *)region;
267
jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;
268
269
if (NULL == privateRegion) {
270
return JVMTI_ITERATION_CONTINUE;
271
}
272
273
switch (privateRegion->type) {
274
case j9mm_region_type_region:
275
returnCode = iterateRegionObjects(vm, region, flags, func, userData);
276
break;
277
default:
278
Assert_MM_unreachable();
279
break;
280
}
281
282
return returnCode;
283
}
284
285
jvmtiIterationControl static
286
iterateObjectSlotDo(
287
J9JavaVM *javaVM,
288
GC_SlotObject *slotObject,
289
J9MM_IterateObjectDescriptor *object,
290
J9MM_IteratorObjectRefType type,
291
UDATA flags,
292
jvmtiIterationControl (*func)(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *objectDesc, J9MM_IterateObjectRefDescriptor *refDesc, void *userData),
293
void *userData)
294
{
295
jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;
296
J9Object *actualObject = slotObject->readReferenceFromSlot();
297
if ( (NULL != actualObject) || (0 == (flags & j9mm_iterator_flag_exclude_null_refs)) ) {
298
J9MM_IterateObjectRefDescriptor refDescriptor;
299
refDescriptor.object = actualObject;
300
refDescriptor.id = (UDATA)actualObject;
301
refDescriptor.fieldAddress = slotObject->readAddressFromSlot();
302
refDescriptor.type = type;
303
returnCode = func(javaVM, object, &refDescriptor, userData);
304
slotObject->writeReferenceToSlot(refDescriptor.object);
305
}
306
return returnCode;
307
}
308
309
jvmtiIterationControl static
310
iterateMixedObjectSlots(
311
J9JavaVM *javaVM,
312
J9Object *objectPtr,
313
J9MM_IterateObjectDescriptor *object,
314
UDATA flags,
315
jvmtiIterationControl (*func)(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *objectDesc, J9MM_IterateObjectRefDescriptor *refDesc, void *userData),
316
void *userData)
317
{
318
GC_MixedObjectIterator mixedObjectIterator(javaVM->omrVM, objectPtr);
319
GC_SlotObject *slotObject;
320
jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;
321
322
while ((slotObject = mixedObjectIterator.nextSlot()) != NULL) {
323
returnCode = iterateObjectSlotDo(javaVM, slotObject, object, j9mm_iterator_object_ref_type_object, flags, func, userData);
324
if (JVMTI_ITERATION_ABORT == returnCode) {
325
break;
326
}
327
}
328
return returnCode;
329
}
330
331
jvmtiIterationControl static
332
iterateArrayObjectSlots(
333
J9JavaVM *javaVM,
334
J9Object *objectPtr,
335
J9MM_IterateObjectDescriptor *object,
336
UDATA flags,
337
jvmtiIterationControl (*func)(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *objectDesc, J9MM_IterateObjectRefDescriptor *refDesc, void *userData),
338
void *userData)
339
{
340
GC_PointerArrayIterator pointerArrayIterator(javaVM, objectPtr);
341
GC_SlotObject *slotObject;
342
jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;
343
344
while ((slotObject = pointerArrayIterator.nextSlot()) != NULL) {
345
returnCode = iterateObjectSlotDo(javaVM, slotObject, object, j9mm_iterator_object_ref_type_object, flags, func, userData);
346
if (JVMTI_ITERATION_ABORT == returnCode) {
347
break;
348
}
349
}
350
return returnCode;
351
}
352
353
jvmtiIterationControl static
354
iterateArrayletSlots(
355
J9JavaVM *javaVM,
356
J9Object *objectPtr,
357
J9MM_IterateObjectDescriptor *object,
358
UDATA flags,
359
jvmtiIterationControl (*func)(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *objectDesc, J9MM_IterateObjectRefDescriptor *refDesc, void *userData),
360
void *userData)
361
{
362
jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;
363
if (j9mm_iterator_flag_include_arraylet_leaves == (flags & j9mm_iterator_flag_include_arraylet_leaves) ) {
364
if (MM_GCExtensions::getExtensions(javaVM->omrVM)->indexableObjectModel.hasArrayletLeafPointers((J9IndexableObject *)objectPtr)) {
365
GC_ArrayletLeafIterator arrayletLeafIterator(javaVM, (J9IndexableObject*)objectPtr);
366
GC_SlotObject *slotObject = NULL;
367
368
while (NULL != (slotObject = arrayletLeafIterator.nextLeafPointer())) {
369
returnCode = iterateObjectSlotDo(javaVM, slotObject, object, j9mm_iterator_object_ref_type_arraylet_leaf, flags, func, userData);
370
if (JVMTI_ITERATION_ABORT == returnCode) {
371
break;
372
}
373
}
374
}
375
}
376
return returnCode;
377
}
378
379
/**
380
* Walk all object slots for the given object, call user provided function.
381
*
382
* @param object The descriptor for the object that should be walked
383
* @param flags The flags describing the walk (unused currently)
384
* @param func The function to call on each object descriptor.
385
* @param userData Pointer to storage for userData.
386
*/
387
jvmtiIterationControl
388
j9mm_iterate_object_slots(
389
J9JavaVM *javaVM,
390
J9PortLibrary *portLibrary,
391
J9MM_IterateObjectDescriptor *object,
392
UDATA flags,
393
jvmtiIterationControl (*func)(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *objectDesc, J9MM_IterateObjectRefDescriptor *refDesc, void *userData),
394
void *userData)
395
{
396
jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;
397
J9Object *objectPtr = (J9Object *)(object->id);
398
MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(javaVM->omrVM);
399
400
switch(extensions->objectModel.getScanType(objectPtr)) {
401
case GC_ObjectModel::SCAN_MIXED_OBJECT_LINKED:
402
case GC_ObjectModel::SCAN_ATOMIC_MARKABLE_REFERENCE_OBJECT:
403
case GC_ObjectModel::SCAN_MIXED_OBJECT:
404
case GC_ObjectModel::SCAN_OWNABLESYNCHRONIZER_OBJECT:
405
case GC_ObjectModel::SCAN_CLASS_OBJECT:
406
case GC_ObjectModel::SCAN_CLASSLOADER_OBJECT:
407
case GC_ObjectModel::SCAN_REFERENCE_MIXED_OBJECT:
408
returnCode = iterateMixedObjectSlots(javaVM, objectPtr, object, flags, func, userData);
409
break;
410
411
case GC_ObjectModel::SCAN_POINTER_ARRAY_OBJECT:
412
returnCode = iterateArrayObjectSlots(javaVM, objectPtr, object, flags, func, userData);
413
if (JVMTI_ITERATION_CONTINUE == returnCode) {
414
returnCode = iterateArrayletSlots(javaVM, objectPtr, object, flags, func, userData);
415
}
416
break;
417
418
case GC_ObjectModel::SCAN_PRIMITIVE_ARRAY_OBJECT:
419
returnCode = iterateArrayletSlots(javaVM, objectPtr, object, flags, func, userData);
420
break;
421
422
default:
423
Assert_MM_unreachable();
424
}
425
426
return returnCode;
427
}
428
429
/**
430
* Initialize a descriptor for the specified object.
431
* This descriptor may subsequently be used with j9mm_iterate_object_slots or other iterator APIs.
432
*
433
* @return descriptor The descriptor to be initialized
434
* @param object The object to store into the descriptor
435
*/
436
void
437
j9mm_initialize_object_descriptor(J9JavaVM *javaVM, J9MM_IterateObjectDescriptor *descriptor, j9object_t object)
438
{
439
MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(javaVM->omrVM);
440
441
descriptor->id = (UDATA)object;
442
descriptor->object = object;
443
descriptor->size = extensions->objectModel.getConsumedSizeInBytesWithHeader(object);
444
descriptor->isObject = TRUE;
445
}
446
447
/**
448
* Walk all objects reachable under the given VM, call user provided function.
449
* @param flags The flags describing the walk (unused currently)
450
* @param func The function to call on each object descriptor.
451
* @param userData Pointer to storage for userData.
452
*/
453
jvmtiIterationControl
454
j9mm_iterate_all_objects(J9JavaVM *vm, J9PortLibrary *portLibrary, UDATA flags, jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateObjectDescriptor *object, void *userData), void *userData)
455
{
456
J9MM_CallbackDataHolderPrivate data;
457
data.func = func;
458
data.userData = userData;
459
data.portLibrary = portLibrary;
460
data.flags = flags;
461
return j9mm_iterate_heaps(vm, portLibrary, flags, &internalIterateHeaps, &data);
462
}
463
464
/* used by j9mm_iterate_all_objects */
465
static jvmtiIterationControl
466
internalIterateHeaps(J9JavaVM *vm, J9MM_IterateHeapDescriptor *heap, void *userData)
467
{
468
J9MM_CallbackDataHolderPrivate *data = (J9MM_CallbackDataHolderPrivate *)userData;
469
return j9mm_iterate_spaces(vm, data->portLibrary, heap, data->flags, &internalIterateSpaces, userData);
470
}
471
472
static jvmtiIterationControl
473
internalIterateSpaces(J9JavaVM *vm, J9MM_IterateSpaceDescriptor *space, void *userData)
474
{
475
J9MM_CallbackDataHolderPrivate *data = (J9MM_CallbackDataHolderPrivate *)userData;
476
return j9mm_iterate_regions(vm, data->portLibrary, space, data->flags, internalIterateRegions, userData);
477
}
478
479
static jvmtiIterationControl
480
internalIterateRegions(J9JavaVM *vm, J9MM_IterateRegionDescriptor *region, void *userData)
481
{
482
J9MM_CallbackDataHolderPrivate *data = (J9MM_CallbackDataHolderPrivate *)userData;
483
return j9mm_iterate_region_objects(vm, data->portLibrary, region, data->flags, data->func, data->userData);
484
}
485
486
/**
487
* Walk all ownable synchronizer object, call user provided function.
488
* @param flags The flags describing the walk (unused currently)
489
* @param func The function to call on each object descriptor.
490
* @param userData Pointer to storage for userData.
491
* @return return 0 on successfully iterating entire list, return user provided function call if it did not return JVMTI_ITERATION_CONTINUE
492
*/
493
jvmtiIterationControl
494
j9mm_iterate_all_ownable_synchronizer_objects(J9VMThread *vmThread, J9PortLibrary *portLibrary, UDATA flags, jvmtiIterationControl (*func)(J9VMThread *vmThread, J9MM_IterateObjectDescriptor *object, void *userData), void *userData)
495
{
496
J9JavaVM *javaVM = vmThread->javaVM;
497
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM->omrVM);
498
MM_ObjectAccessBarrier *barrier = extensions->accessBarrier;
499
MM_OwnableSynchronizerObjectList *ownableSynchronizerObjectList = extensions->getOwnableSynchronizerObjectListsExternal(vmThread);
500
501
Assert_MM_true(NULL != ownableSynchronizerObjectList);
502
503
J9MM_IterateObjectDescriptor objectDescriptor;
504
J9MM_IterateRegionDescriptor regionDesc;
505
jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;
506
507
while (NULL != ownableSynchronizerObjectList) {
508
J9Object *objectPtr = ownableSynchronizerObjectList->getHeadOfList();
509
while (NULL != objectPtr) {
510
UDATA regionFound = j9mm_find_region_for_pointer(javaVM, objectPtr, &regionDesc);
511
if (0 != regionFound) {
512
initializeObjectDescriptor(javaVM, &objectDescriptor, &regionDesc, objectPtr);
513
returnCode = func(vmThread, &objectDescriptor, userData);
514
if (JVMTI_ITERATION_ABORT == returnCode) {
515
return returnCode;
516
}
517
} else {
518
Assert_MM_unreachable();
519
}
520
objectPtr = barrier->getOwnableSynchronizerLink(objectPtr);
521
}
522
ownableSynchronizerObjectList = ownableSynchronizerObjectList->getNextList();
523
}
524
return returnCode;
525
}
526
527
} /* extern "C" */
528
529
/**
530
* Initialize the specified descriptor with the specified values.
531
* Invariant fields are initialized to the appropriate values for the JVM.
532
*
533
* @param[in] extensions - a pointer to the GC extensions
534
* @param[out] descriptor - the descriptor to initialize
535
* @param[in] region - The region to use for descriptor initialization
536
*/
537
static void
538
initializeRegionDescriptor(MM_GCExtensionsBase* extensions, J9MM_IterateRegionDescriptor *descriptor, MM_HeapRegionDescriptor *region)
539
{
540
UDATA objectAlignment = extensions->getObjectAlignmentInBytes();
541
UDATA objectMinimumSize = 0;
542
const char *regionName = NULL;
543
#if defined(J9VM_GC_MINIMUM_OBJECT_SIZE)
544
objectMinimumSize = J9_GC_MINIMUM_OBJECT_SIZE;
545
#else /* J9VM_GC_MINIMUM_OBJECT_SIZE */
546
objectMinimumSize = J9GC_OBJECT_HEADER_SIZE(extensions)
547
#endif /* J9VM_GC_MINIMUM_OBJECT_SIZE */
548
549
switch(region->getRegionType()) {
550
case MM_HeapRegionDescriptor::RESERVED:
551
regionName = HEAPITERATORAPI_REGION_NAME_RESERVED;
552
objectAlignment = 0;
553
objectMinimumSize = 0;
554
break;
555
case MM_HeapRegionDescriptor::FREE:
556
case MM_HeapRegionDescriptor::ADDRESS_ORDERED_IDLE:
557
case MM_HeapRegionDescriptor::BUMP_ALLOCATED_IDLE:
558
/* (for all intents and purposes, an IDLE region is the same as a FREE region) */
559
regionName = HEAPITERATORAPI_REGION_NAME_FREE;
560
objectAlignment = 0;
561
objectMinimumSize = 0;
562
break;
563
case MM_HeapRegionDescriptor::ARRAYLET_LEAF:
564
regionName = HEAPITERATORAPI_REGION_NAME_ARRAYLET;
565
objectAlignment = 0;
566
objectMinimumSize = 0;
567
break;
568
#if defined(J9VM_GC_SEGREGATED_HEAP)
569
case MM_HeapRegionDescriptor::SEGREGATED_SMALL:
570
regionName = HEAPITERATORAPI_REGION_NAME_SEGREGATED_SMALL;
571
objectMinimumSize = ((MM_HeapRegionDescriptorSegregated *)region)->getCellSize();
572
break;
573
case MM_HeapRegionDescriptor::SEGREGATED_LARGE:
574
regionName = HEAPITERATORAPI_REGION_NAME_SEGREGATED_LARGE;
575
objectMinimumSize = region->getSize();
576
break;
577
#endif /* J9VM_GC_SEGREGATED_HEAP */
578
case MM_HeapRegionDescriptor::ADDRESS_ORDERED:
579
case MM_HeapRegionDescriptor::BUMP_ALLOCATED:
580
if (extensions->isVLHGC()) {
581
#if defined(J9VM_GC_VLHGC)
582
regionName = HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_NURSERY;
583
#endif /* J9VM_GC_VLHGC */
584
} else {
585
if (MEMORY_TYPE_NEW == (region->getTypeFlags() & MEMORY_TYPE_NEW)) {
586
regionName = HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_NURSERY;
587
} else if (MEMORY_TYPE_OLD == (region->getTypeFlags() & MEMORY_TYPE_OLD)) {
588
regionName = HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_TENURED;
589
} else {
590
regionName = HEAPITERATORAPI_REGION_NAME;
591
}
592
}
593
break;
594
#if defined(J9VM_GC_VLHGC)
595
case MM_HeapRegionDescriptor::ADDRESS_ORDERED_MARKED:
596
case MM_HeapRegionDescriptor::BUMP_ALLOCATED_MARKED:
597
regionName = HEAPITERATORAPI_REGION_NAME_ADDRESS_ORDERED_TENURED;
598
break;
599
#endif /* J9VM_GC_VLHGC */
600
default:
601
Assert_MM_unreachable();
602
}
603
604
initializeRegionDescriptor(descriptor, regionName, (UDATA)region, objectAlignment, objectMinimumSize, region->getLowAddress(), region->getSize());
605
}
606
607
/**
608
* Initialize the specified descriptor with the specified values.
609
* Invariant fields are initialized to the appropriate values for the JVM.
610
*
611
* @param[out] descriptor - the descriptor to initialize
612
* @param[in] name - name of the region
613
* @param[in] id - id of the region
614
* @param[in] start - start address of the region
615
* @param[in] size - size (in bytes) of the region
616
*/
617
static void
618
initializeRegionDescriptor(J9MM_IterateRegionDescriptor *descriptor, const char* name, UDATA id, UDATA objectAlignment, UDATA objectMinimumSize, void* start, UDATA size)
619
{
620
descriptor->name = name;
621
descriptor->id = id;
622
descriptor->objectAlignment = objectAlignment;
623
descriptor->objectMinimumSize = objectMinimumSize;
624
descriptor->regionStart = start;
625
descriptor->regionSize = size;
626
}
627
628
/**
629
* Initialize a descriptor for the specified object.
630
* This descriptor may subsequently be used with j9mm_iterate_object_slots or other iterator APIs.
631
*
632
* @return descriptor The descriptor to be initialized
633
* @param regionDesc the region to use to round object to minimum object size
634
* @param object The object to store into the descriptor
635
*/
636
static void
637
initializeObjectDescriptor(
638
J9JavaVM *javaVM,
639
J9MM_IterateObjectDescriptor *descriptor,
640
J9MM_IterateRegionDescriptor *regionDesc,
641
j9object_t object)
642
{
643
j9mm_initialize_object_descriptor(javaVM, descriptor, object);
644
645
#if defined(J9VM_GC_SEGREGATED_HEAP)
646
MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(javaVM->omrVM);
647
648
if (extensions->isSegregatedHeap()) {
649
/* TODO remove this once the objectModel properly handles Segregated Heaps */
650
if (descriptor->size < regionDesc->objectMinimumSize) {
651
descriptor->size = regionDesc->objectMinimumSize;
652
}
653
}
654
#endif /* J9VM_GC_SEGREGATED_HEAP */
655
}
656
657
static jvmtiIterationControl
658
iterateRegions(
659
J9JavaVM *vm,
660
J9MM_IterateSpaceDescriptor *space,
661
UDATA flags,
662
jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateRegionDescriptor *regionDesc, void *userData),
663
void *userData)
664
{
665
jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;
666
667
MM_MemorySpace *memorySpace = MM_MemorySpace::getMemorySpace((void *)space->id);
668
MM_HeapRegionManager *manager = memorySpace->getHeap()->getHeapRegionManager();
669
manager->lock();
670
671
GC_HeapRegionIterator regionIterator(manager, memorySpace);
672
MM_HeapRegionDescriptor *region = NULL;
673
MM_GCExtensionsBase* extensions = MM_GCExtensionsBase::getExtensions(vm->omrVM);
674
while(NULL != (region = regionIterator.nextRegion())) {
675
J9MM_IterateRegionDescriptorPrivate regionDescription;
676
regionDescription.type = j9mm_region_type_region;
677
initializeRegionDescriptor(extensions, &regionDescription.descriptor, region);
678
returnCode = func(vm, &(regionDescription.descriptor), userData);
679
if (JVMTI_ITERATION_ABORT == returnCode) {
680
break;
681
}
682
}
683
manager->unlock();
684
685
return returnCode;
686
}
687
688
static jvmtiIterationControl
689
iterateRegionObjects(
690
J9JavaVM *vm,
691
J9MM_IterateRegionDescriptor *region,
692
UDATA flags,
693
jvmtiIterationControl (*func)(J9JavaVM *vm, J9MM_IterateObjectDescriptor *objectDesc, void *userData),
694
void *userData)
695
{
696
PORT_ACCESS_FROM_JAVAVM(vm);
697
jvmtiIterationControl returnCode = JVMTI_ITERATION_CONTINUE;
698
/* Iterate over live and dead objects */
699
MM_HeapRegionDescriptor* heapRegion = (MM_HeapRegionDescriptor*)region->id;
700
MM_GCExtensionsBase *extensions = MM_GCExtensionsBase::getExtensions(vm->omrVM);
701
HeapIteratorAPI_BufferedIterator objectHeapIterator(vm, PORTLIB, heapRegion, true);
702
J9Object* object = NULL;
703
while(NULL != (object = objectHeapIterator.nextObject())) {
704
J9MM_IterateObjectDescriptor objectDescriptor;
705
if ((extensions->objectModel.isDeadObject(object)) || (0 != (J9CLASS_FLAGS(J9GC_J9OBJECT_CLAZZ_VM(object, vm)) & J9AccClassDying))) {
706
if (0 != (flags & j9mm_iterator_flag_include_holes)) {
707
if (extensions->objectModel.isDeadObject(object)) {
708
objectDescriptor.id = (UDATA)object;
709
objectDescriptor.object = object;
710
objectDescriptor.size = extensions->objectModel.getSizeInBytesDeadObject(object);
711
} else {
712
/* this object is not marked as a hole, but its class has been partially unloaded so it's treated like a hole here */
713
j9mm_initialize_object_descriptor(vm, &objectDescriptor, object);
714
}
715
objectDescriptor.isObject = FALSE;
716
returnCode = func(vm, &objectDescriptor, userData);
717
if (JVMTI_ITERATION_ABORT == returnCode) {
718
break;
719
}
720
}
721
} else {
722
initializeObjectDescriptor(vm, &objectDescriptor, region, object);
723
returnCode = func(vm, &objectDescriptor, userData);
724
if (JVMTI_ITERATION_ABORT == returnCode) {
725
break;
726
}
727
}
728
}
729
730
return returnCode;
731
}
732
733
/**
734
* Find the Region that the pointer belongs too.
735
* Returns true if region found.
736
*/
737
UDATA
738
j9mm_find_region_for_pointer(J9JavaVM* javaVM, void *pointer, J9MM_IterateRegionDescriptor *regionDesc)
739
{
740
MM_GCExtensions* extensions = MM_GCExtensions::getExtensions(javaVM->omrVM);
741
bool found = false;
742
MM_HeapRegionManager *regionManager = extensions->heap->getHeapRegionManager();
743
/* See if the pointer is being managed by the RegionManager */
744
MM_HeapRegionDescriptor *region = regionManager->regionDescriptorForAddress(pointer);
745
746
if (NULL != region) {
747
initializeRegionDescriptor(extensions, regionDesc, region);
748
found = true;
749
}
750
751
return (UDATA) found; /* TODO: fix this, we really return bool */
752
}
753
754
/**
755
* Convert the memory that is currently represented as an object to dark matter.
756
* This routine is typically used by GC tools such as gccheck and tgc to ensure that only valid (i.e. reachable)
757
* objects remain on the heap after a sweep. An 'dead' object may contain dangling references to heap addresses
758
* which no longer contain walkable objects. The problem is solved by converting the invalid objects to dark matter.
759
*
760
* @param[in] javaVM the JavaVM
761
* @param[in] region the region in which the object exists
762
* @param[in] objectDesc the object to be abandoned
763
* @return 0 on success, non-0 on failure.
764
*/
765
UDATA
766
j9mm_abandon_object(
767
J9JavaVM *javaVM,
768
J9MM_IterateRegionDescriptor *region,
769
J9MM_IterateObjectDescriptor *objectDesc)
770
{
771
UDATA rc = 0;
772
J9MM_IterateRegionDescriptorPrivate *privateRegion = (J9MM_IterateRegionDescriptorPrivate *)region;
773
774
if (j9mm_region_type_region == privateRegion->type) {
775
MM_HeapRegionDescriptor* heapRegion = (MM_HeapRegionDescriptor*)region->id;
776
MM_MemorySubSpace* memorySubSpace = heapRegion->getSubSpace();
777
778
UDATA deadObjectByteSize = MM_GCExtensions::getExtensions(javaVM)->objectModel.getConsumedSizeInBytesWithHeader(objectDesc->object);
779
memorySubSpace->abandonHeapChunk(objectDesc->object, ((U_8*)objectDesc->object) + deadObjectByteSize);
780
781
} else {
782
rc = 1;
783
}
784
785
return rc;
786
}
787
788