Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_trace_vlhgc/TgcInterRegionRememberedSetDemographics.cpp
5986 views
1
/*******************************************************************************
2
* Copyright (c) 1991, 2020 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 "Tgc.hpp"
27
#include "mmhook.h"
28
29
#include <string.h>
30
31
#include "GCExtensions.hpp"
32
#include "TgcExtensions.hpp"
33
34
#include "EnvironmentBase.hpp"
35
#include "HashTableIterator.hpp"
36
#include "HeapMapIterator.hpp"
37
#include "HeapRegionDescriptorVLHGC.hpp"
38
#include "HeapRegionIteratorVLHGC.hpp"
39
#include "HeapRegionManager.hpp"
40
#include "ParallelDispatcher.hpp"
41
#include "ParallelTask.hpp"
42
43
struct ClassTableEntry {
44
J9Class *clazz; /**< The class represented by this entry */
45
UDATA rememberedInstances; /**< The number of instances of the class with references out of their own region */
46
UDATA totalInstances; /**< The total number of instances of the class encountered */
47
48
static UDATA hash(void *key, void *userData) { return (UDATA)((ClassTableEntry*)key)->clazz; }
49
static UDATA equal(void *leftKey, void *rightKey, void *userData) { return ((ClassTableEntry*)leftKey)->clazz == ((ClassTableEntry*)rightKey)->clazz; }
50
};
51
52
static void reportInterRegionRememberedSetDemographics(MM_EnvironmentBase *env);
53
static void tgcHookIncrementStart(J9HookInterface** hookInterface, UDATA eventNum, void* eventData, void* userData);
54
static void insertIntoSortedList(ClassTableEntry* entry, ClassTableEntry* list, UDATA listCount);
55
56
class TgcParallelHeapWalkTask : public MM_ParallelTask
57
{
58
/* Data Members */
59
private:
60
protected:
61
public:
62
63
/* Member Functions */
64
private:
65
protected:
66
public:
67
virtual UDATA getVMStateID(void) { return OMRVMSTATE_GC_TGC; }
68
virtual void run(MM_EnvironmentBase *env);
69
70
TgcParallelHeapWalkTask(MM_EnvironmentBase *env, MM_ParallelDispatcher *dispatcher)
71
: MM_ParallelTask(env, dispatcher)
72
{
73
_typeId = __FUNCTION__;
74
}
75
};
76
77
void
78
TgcParallelHeapWalkTask::run(MM_EnvironmentBase *env)
79
{
80
UDATA errorCount = 0;
81
UDATA totalRememberedObjects = 0;
82
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
83
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
84
MM_HeapMap *markMap = extensions->previousMarkMap;
85
J9HashTable *hashTable = hashTableNew(env->getPortLibrary(), J9_GET_CALLSITE(), 8*1024, sizeof(ClassTableEntry), sizeof(char *), 0, OMRMEM_CATEGORY_MM, ClassTableEntry::hash, ClassTableEntry::equal, NULL, NULL);
86
87
if (NULL == hashTable) {
88
errorCount += 1;
89
} else {
90
GC_HeapRegionIteratorVLHGC regionIterator(extensions->heapRegionManager);
91
MM_HeapRegionDescriptorVLHGC *region = NULL;
92
while(NULL != (region = regionIterator.nextRegion())) {
93
if (region->hasValidMarkMap()) {
94
if (J9MODRON_HANDLE_NEXT_WORK_UNIT(env)) {
95
MM_HeapMapIterator mapIterator(extensions, markMap, (UDATA *)region->getLowAddress(), (UDATA *)region->getHighAddress(), false);
96
J9Object *objectPtr = NULL;
97
while(NULL != (objectPtr = mapIterator.nextObject())) {
98
ClassTableEntry exemplar;
99
exemplar.clazz = J9GC_J9OBJECT_CLAZZ(objectPtr, env);
100
exemplar.rememberedInstances = 0;
101
exemplar.totalInstances = 0;
102
ClassTableEntry *entry = (ClassTableEntry *)hashTableAdd(hashTable, &exemplar);
103
104
if (NULL == entry) {
105
errorCount += 1;
106
} else {
107
entry->totalInstances += 1;
108
if (extensions->objectModel.isRemembered(objectPtr)) {
109
entry->rememberedInstances += 1;
110
totalRememberedObjects += 1;
111
}
112
}
113
}
114
}
115
}
116
}
117
}
118
119
/*
120
* Merge data
121
*/
122
omrthread_monitor_enter(tgcExtensions->_interRegionRememberedSetDemographics.mutex);
123
if (NULL != hashTable) {
124
J9HashTable *sharedHashTable = tgcExtensions->_interRegionRememberedSetDemographics.classHashTable;
125
GC_HashTableIterator hashTableIterator(hashTable);
126
ClassTableEntry *entry = NULL;
127
while(NULL != (entry = (ClassTableEntry*)hashTableIterator.nextSlot())) {
128
if (entry->rememberedInstances > 0) {
129
ClassTableEntry exemplar;
130
exemplar.clazz = entry->clazz;
131
exemplar.rememberedInstances = 0;
132
exemplar.totalInstances = 0;
133
ClassTableEntry *sharedEntry = (ClassTableEntry *)hashTableAdd(sharedHashTable, &exemplar);
134
if (NULL == sharedEntry) {
135
errorCount += 1;
136
} else {
137
sharedEntry->rememberedInstances += entry->rememberedInstances;
138
sharedEntry->totalInstances += entry->totalInstances;
139
}
140
}
141
}
142
}
143
tgcExtensions->_interRegionRememberedSetDemographics.errorCount += errorCount;
144
tgcExtensions->_interRegionRememberedSetDemographics.totalRememberedObjects += totalRememberedObjects;
145
omrthread_monitor_exit(tgcExtensions->_interRegionRememberedSetDemographics.mutex);
146
147
if (NULL != hashTable) {
148
hashTableFree(hashTable);
149
}
150
}
151
152
153
/**
154
* Report RSCL histogram prior to a collection
155
*/
156
static void
157
reportInterRegionRememberedSetDemographics(MM_EnvironmentBase *env)
158
{
159
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(env);
160
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
161
J9HashTable *hashTable = tgcExtensions->_interRegionRememberedSetDemographics.classHashTable;
162
163
tgcExtensions->_interRegionRememberedSetDemographics.incrementCount += 1;
164
tgcExtensions->_interRegionRememberedSetDemographics.errorCount = 0;
165
tgcExtensions->_interRegionRememberedSetDemographics.totalRememberedObjects = 0;
166
167
tgcExtensions->printf("<rememberedSetDemographics increment=\"%zu\">\n", tgcExtensions->_interRegionRememberedSetDemographics.incrementCount);
168
169
MM_ParallelDispatcher *dispatcher = extensions->dispatcher;
170
TgcParallelHeapWalkTask heapWalkTask(env, dispatcher);
171
dispatcher->run(env, &heapWalkTask);
172
173
/* at this point, the helper threads have completed populating the shared hash table with the all classes with remembered instances */
174
175
const UDATA listCount = 10;
176
ClassTableEntry sortedResults[listCount];
177
memset(sortedResults, 0, sizeof(sortedResults));
178
179
GC_HashTableIterator hashTableIterator(hashTable);
180
ClassTableEntry *entry = NULL;
181
while(NULL != (entry = (ClassTableEntry*)hashTableIterator.nextSlot())) {
182
Assert_MM_true(0 != entry->rememberedInstances);
183
insertIntoSortedList(entry, sortedResults, listCount);
184
hashTableIterator.removeSlot();
185
}
186
187
UDATA errorCount = tgcExtensions->_interRegionRememberedSetDemographics.errorCount;
188
UDATA totalRememberedObjects = tgcExtensions->_interRegionRememberedSetDemographics.totalRememberedObjects;
189
for (UDATA index = 0; index < listCount; index++) {
190
entry = &sortedResults[index];
191
J9Class *clazz = entry->clazz;
192
if (NULL != clazz) {
193
double fractionRemembered = (double)entry->rememberedInstances / (double)entry->totalInstances;
194
double fractionOfAllRemembered = (double)entry->rememberedInstances / (double)totalRememberedObjects;
195
tgcExtensions->printf("%8zu %.2f %.2f %p ", entry->rememberedInstances, fractionRemembered, fractionOfAllRemembered, clazz);
196
if (J9GC_CLASS_IS_ARRAY(clazz)) {
197
J9Class *leafComponentType = ((J9ArrayClass*)clazz)->leafComponentType;
198
J9UTF8 *name = J9ROMCLASS_CLASSNAME(leafComponentType->romClass);
199
UDATA arity = ((J9ArrayClass*)clazz)->arity;
200
char brackets[256];
201
Assert_MM_true(arity <= sizeof(brackets));
202
memset(brackets, '[', sizeof(brackets));
203
if (OBJECT_HEADER_SHAPE_MIXED == J9GC_CLASS_SHAPE(leafComponentType)) {
204
tgcExtensions->printf("%.*sL%.*s;\n", arity, brackets, J9UTF8_LENGTH(name), J9UTF8_DATA(name));
205
} else {
206
tgcExtensions->printf("%.*s%.*s\n", arity, brackets, J9UTF8_LENGTH(name), J9UTF8_DATA(name));
207
}
208
} else {
209
J9UTF8 *name = J9ROMCLASS_CLASSNAME(clazz->romClass);
210
tgcExtensions->printf("%.*s\n", J9UTF8_LENGTH(name), J9UTF8_DATA(name));
211
}
212
}
213
}
214
215
if (0 != errorCount) {
216
tgcExtensions->printf("WARNING: Failed to allocate records for %zu class(es).\n", errorCount);
217
}
218
219
tgcExtensions->printf("<rememberedSetDemographics/>\n");
220
}
221
222
static void
223
insertIntoSortedList(ClassTableEntry* entry, ClassTableEntry* list, UDATA listCount)
224
{
225
for (UDATA index = 0; index < listCount; index++) {
226
if (entry->rememberedInstances > list[index].rememberedInstances) {
227
memmove(&list[index + 1], &list[index], (listCount - index - 1) * sizeof(list[0]));
228
list[index] = *entry;
229
break;
230
}
231
}
232
}
233
234
static void
235
tgcHookIncrementStart(J9HookInterface** hookInterface, UDATA eventNum, void* eventData, void* userData)
236
{
237
OMR_VMThread *omrThread = ((MM_GCIncrementStartEvent*)eventData)->currentThread;
238
MM_EnvironmentBase *env = MM_EnvironmentBase::getEnvironment(omrThread);
239
reportInterRegionRememberedSetDemographics(env);
240
}
241
242
243
/**
244
* Initialize inter region remembered set tgc tracing.
245
* Initializes the TgcInterRegionRememberedSetExtensions object associated with irrs tgc tracing. Attaches hooks
246
* to the appropriate functions handling events used by irrs tgc tracing.
247
*/
248
bool
249
tgcInterRegionRememberedSetDemographicsInitialize(J9JavaVM *javaVM)
250
{
251
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
252
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
253
bool result = true;
254
255
J9HashTable *hashTable = hashTableNew(OMRPORT_FROM_J9PORT(javaVM->portLibrary), J9_GET_CALLSITE(), 8*1024, sizeof(ClassTableEntry), sizeof(char *), 0, OMRMEM_CATEGORY_MM, ClassTableEntry::hash, ClassTableEntry::equal, NULL, NULL);
256
tgcExtensions->_interRegionRememberedSetDemographics.classHashTable = hashTable;
257
258
if (NULL != hashTable) {
259
if (0 == omrthread_monitor_init_with_name(&tgcExtensions->_interRegionRememberedSetDemographics.mutex, 0, "InterRegionRememberedSetDemographics")) {
260
J9HookInterface** privateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface);
261
(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_GC_INCREMENT_START, tgcHookIncrementStart, OMR_GET_CALLSITE(), javaVM);
262
} else {
263
result = false;
264
}
265
} else {
266
result = false;
267
}
268
269
tgcExtensions->_interRegionRememberedSetDemographics.incrementCount = 0;
270
271
return result;
272
}
273
274
void
275
tgcInterRegionRememberedSetDemographicsTearDown(J9JavaVM *javaVM)
276
{
277
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
278
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
279
280
if (NULL != tgcExtensions->_interRegionRememberedSetDemographics.classHashTable) {
281
hashTableFree(tgcExtensions->_interRegionRememberedSetDemographics.classHashTable);
282
tgcExtensions->_interRegionRememberedSetDemographics.classHashTable = NULL;
283
}
284
285
if (NULL != tgcExtensions->_interRegionRememberedSetDemographics.mutex) {
286
omrthread_monitor_destroy(tgcExtensions->_interRegionRememberedSetDemographics.mutex);
287
tgcExtensions->_interRegionRememberedSetDemographics.mutex = NULL;
288
289
}
290
}
291
292