Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gc_trace_vlhgc/TgcInterRegionRememberedSet.cpp
5986 views
1
2
/*******************************************************************************
3
* Copyright (c) 1991, 2017 IBM Corp. and others
4
*
5
* This program and the accompanying materials are made available under
6
* the terms of the Eclipse Public License 2.0 which accompanies this
7
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
8
* or the Apache License, Version 2.0 which accompanies this distribution and
9
* is available at https://www.apache.org/licenses/LICENSE-2.0.
10
*
11
* This Source Code may also be made available under the following
12
* Secondary Licenses when the conditions for such availability set
13
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
14
* General Public License, version 2 with the GNU Classpath
15
* Exception [1] and GNU General Public License, version 2 with the
16
* OpenJDK Assembly Exception [2].
17
*
18
* [1] https://www.gnu.org/software/classpath/license.html
19
* [2] http://openjdk.java.net/legal/assembly-exception.html
20
*
21
* 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
22
*******************************************************************************/
23
24
#include "j9.h"
25
#include "j9cfg.h"
26
#include "j9port.h"
27
#include "Tgc.hpp"
28
#include "mmhook.h"
29
30
#include "GCExtensions.hpp"
31
#include "TgcExtensions.hpp"
32
33
#include "CycleState.hpp"
34
#include "EnvironmentVLHGC.hpp"
35
#include "HeapRegionDescriptorVLHGC.hpp"
36
#include "HeapRegionManager.hpp"
37
#include "IncrementalGenerationalGC.hpp"
38
#include "InterRegionRememberedSet.hpp"
39
#include "RememberedSetCardListCardIterator.hpp"
40
41
42
/* Histogram buckets */
43
#define MAX_BUCKETS 18
44
struct Bucket {
45
UDATA regionCount;
46
UDATA duplicates;
47
UDATA cardCount;
48
};
49
50
enum {
51
DISTINCT_FLAG_ARRAY_SHIFT = 4 /* for duplicate/distinct card list count we used a hash table, this is a factor which tells how hash table is big relative to RSCL */
52
};
53
54
static UDATA
55
getUpperBoundDuplicatesCount(MM_EnvironmentVLHGC *env, MM_RememberedSetCardList *rscl)
56
{
57
UDATA duplicateCount = 0;
58
59
if (MM_GCExtensions::getExtensions(env)->tarokTgcEnableRememberedSetDuplicateDetection) {
60
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(MM_GCExtensions::getExtensions(env));
61
62
/* If lazy initialize of _rsclDistinctFlagArray failed, we'll skip calculating duplicates */
63
if (NULL != tgcExtensions->_rsclDistinctFlagArray) {
64
UDATA cardListSize = rscl->getSize(env);
65
UDATA distinctFlagArraySize = cardListSize << DISTINCT_FLAG_ARRAY_SHIFT;
66
for (UDATA i = 0; i < distinctFlagArraySize; i++) {
67
tgcExtensions->_rsclDistinctFlagArray[i] = 0;
68
}
69
70
GC_RememberedSetCardListCardIterator rsclCardIterator(rscl);
71
void *cardAddress = NULL;
72
while(NULL != (cardAddress = rsclCardIterator.nextReferencingCardHeapAddress(env))) {
73
/* card addresses are CARD_SIZE bytes aligned, thus stripping low bits that are 0s (use the shift value corresponding to the size) */
74
/* prime 100000007 should be larger than distinctFlagArraySize * 8bits */
75
UDATA hash = ((UDATA)cardAddress >> CARD_SIZE_SHIFT) % 100000007;
76
UDATA bit = hash & 0x7;
77
UDATA index = (hash >> 3) % distinctFlagArraySize;
78
tgcExtensions->_rsclDistinctFlagArray[index] |= (1 << bit);
79
}
80
81
UDATA distinctCount = 0;
82
83
for (UDATA i = 0; i < distinctFlagArraySize; i++) {
84
U_8 flag = tgcExtensions->_rsclDistinctFlagArray[i];
85
if (0 != flag) {
86
for (UDATA bitShift = 0; bitShift < 8; bitShift++) {
87
U_8 bit = 1 << bitShift;
88
if (bit == (tgcExtensions->_rsclDistinctFlagArray[i] & bit)) {
89
distinctCount += 1;
90
}
91
}
92
}
93
}
94
95
duplicateCount = cardListSize - distinctCount;
96
}
97
}
98
99
return duplicateCount;
100
101
}
102
103
/**
104
* Print a histogram of the objects using classList
105
*/
106
static void
107
calculateAndPrintHistogram(J9VMThread *vmThread, MM_HeapRegionManager *regionManager, const char *eventString, UDATA totalReferences, UDATA maxReferences)
108
{
109
J9JavaVM *javaVM = vmThread->javaVM;
110
MM_EnvironmentVLHGC *env = MM_EnvironmentVLHGC::getEnvironment(vmThread);
111
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
112
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
113
maxReferences = extensions->tarokRememberedSetCardListMaxSize;
114
UDATA regionCount = regionManager->getTableRegionCount();
115
double totalPercent = ((double)totalReferences / ((double)regionCount * (double)extensions->tarokRememberedSetCardListSize)) * 100.0;
116
UDATA totalDuplicates = 0;
117
118
tgcExtensions->printf("{RSCL: %zu (%.2f%%) total reference cards to regions; max %zu per region}\n", totalReferences, totalPercent, maxReferences);
119
if (maxReferences > 0) {
120
Bucket buckets[MAX_BUCKETS];
121
UDATA maxForBucket[MAX_BUCKETS - 1];
122
UDATA increment = (maxReferences + MAX_BUCKETS - 3) / (MAX_BUCKETS - 2);
123
UDATA i = 0;
124
for (i = 0; i < MAX_BUCKETS; i++) {
125
buckets[i].regionCount = 0;
126
buckets[i].duplicates = 0;
127
buckets[i].cardCount = 0;
128
}
129
for (i = 0; i < MAX_BUCKETS - 1; i++) {
130
maxForBucket[i] = i * increment;
131
}
132
133
tgcExtensions->printf("{RSCL: Histogram of reference cards TO regions after %s. Duplicates percentage in brackets left to the region count. }\n{RSCL: Refs ", eventString);
134
UDATA minForBucket = 0;
135
for (i = 0; i < MAX_BUCKETS - 1; i++) {
136
if (minForBucket < maxForBucket[i]) {
137
if (100000 <= maxForBucket[i]) {
138
tgcExtensions->printf(" <=%3zuK", maxForBucket[i]/1024);
139
} else {
140
tgcExtensions->printf(" <=%5zu", maxForBucket[i]);
141
}
142
} else {
143
tgcExtensions->printf(" =%5zu", maxForBucket[i]);
144
}
145
minForBucket = maxForBucket[i] + 1;
146
}
147
tgcExtensions->printf(" OF");
148
149
for (UDATA age = 0; age <= extensions->tarokRegionMaxAge; age++) {
150
for (i = 0; i < regionCount; i++) {
151
MM_HeapRegionDescriptorVLHGC *region = (MM_HeapRegionDescriptorVLHGC *)regionManager->physicalTableDescriptorForIndex(i);
152
if (age == region->getLogicalAge()) {
153
UDATA cardCount = region->getRememberedSetCardList()->getSize(env);
154
UDATA duplicates = getUpperBoundDuplicatesCount(env, region->getRememberedSetCardList());
155
UDATA bucketIndex;
156
if (region->getRememberedSetCardList()->isOverflowed()) {
157
bucketIndex = MAX_BUCKETS - 1;
158
} else {
159
bucketIndex = (cardCount + increment - 1) / increment;
160
}
161
buckets[bucketIndex].regionCount += 1;
162
buckets[bucketIndex].cardCount += cardCount;
163
buckets[bucketIndex].duplicates += duplicates;
164
totalDuplicates += duplicates;
165
}
166
}
167
168
tgcExtensions->printf(" }\n{RSCL: age %2zu ", age);
169
for (i = 0; i < MAX_BUCKETS; i++) {
170
UDATA duplicatePercentage = 0;
171
if (0 != buckets[i].cardCount) {
172
duplicatePercentage = 100 * buckets[i].duplicates / buckets[i].cardCount;
173
}
174
if (0 != duplicatePercentage) {
175
tgcExtensions->printf(" (%2zu)%3zu", duplicatePercentage, buckets[i].regionCount);
176
} else {
177
tgcExtensions->printf(" %7zu", buckets[i].regionCount);
178
}
179
buckets[i].regionCount = 0;
180
buckets[i].duplicates = 0;
181
buckets[i].cardCount = 0;
182
}
183
}
184
185
tgcExtensions->printf(" }\n");
186
tgcExtensions->printf("{RSCL: Total duplicates: %zu%% }\n", totalReferences ? (totalDuplicates * 100 / totalReferences): (UDATA)0);
187
}
188
}
189
190
191
/**
192
* Report RSCL histogram prior to a collection
193
*/
194
static void
195
tgcHookReportInterRegionRememberedSetHistogram(J9HookInterface** hookInterface, UDATA eventNum, void* eventData, void* userData)
196
{
197
J9VMThread* vmThread = NULL;
198
const char *eventString = NULL;
199
J9JavaVM *javaVM = (J9JavaVM *) userData;
200
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
201
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
202
MM_EnvironmentVLHGC env(javaVM);
203
J9HookInterface** externalHookInterface = extensions->getHookInterface();
204
J9HookInterface** privateHookInterface = extensions->getPrivateHookInterface();
205
206
if ((J9HOOK_MM_PRIVATE_MARK_END == eventNum) && ( privateHookInterface == hookInterface)) {
207
MM_MarkEndEvent* event = (MM_MarkEndEvent*)eventData;
208
vmThread = static_cast<J9VMThread *>(event->currentThread->_language_vmthread);
209
eventString = "Mark";
210
} else if ((J9HOOK_MM_OMR_COMPACT_END == eventNum) && ( externalHookInterface == hookInterface)) {
211
MM_CompactEndEvent* event = (MM_CompactEndEvent*)eventData;
212
vmThread = (J9VMThread *)event->omrVMThread->_language_vmthread;
213
eventString = "Compact";
214
} else if (J9HOOK_MM_PRIVATE_COPY_FORWARD_END == eventNum && ( privateHookInterface == hookInterface)) {
215
MM_CopyForwardEndEvent* event = (MM_CopyForwardEndEvent*)eventData;
216
vmThread = static_cast<J9VMThread *>(event->currentThread->_language_vmthread);
217
eventString = "CopyForward";
218
} else {
219
Assert_MM_unreachable();
220
}
221
222
/* Lazy allocate for _rsclDistinctFlagArray
223
* (count not be done in Initialize, since tarokRememberedSetCardListMaxSize might have not be set yet
224
*/
225
if (NULL == tgcExtensions->_rsclDistinctFlagArray) {
226
tgcExtensions->_rsclDistinctFlagArray = (U_8 *)extensions->getForge()->allocate(extensions->tarokRememberedSetCardListMaxSize << DISTINCT_FLAG_ARRAY_SHIFT, MM_AllocationCategory::FIXED, J9_GET_CALLSITE());
227
}
228
229
MM_HeapRegionManager *regionManager = extensions->heap->getHeapRegionManager();
230
UDATA regionCount = regionManager->getTableRegionCount();
231
232
UDATA maxCardsToRegion = 0;
233
UDATA totalCardsToRegions = 0;
234
235
for (UDATA i = 0; i < regionCount; i++) {
236
MM_HeapRegionDescriptorVLHGC *region = (MM_HeapRegionDescriptorVLHGC *)regionManager->physicalTableDescriptorForIndex(i);
237
maxCardsToRegion = OMR_MAX(maxCardsToRegion, region->getRememberedSetCardList()->getSize(&env));
238
totalCardsToRegions += region->getRememberedSetCardList()->getSize(&env);
239
}
240
241
calculateAndPrintHistogram(vmThread, regionManager, eventString, totalCardsToRegions, maxCardsToRegion);
242
}
243
244
245
/**
246
* Initialize inter region remembered set tgc tracing.
247
* Initializes the TgcInterRegionRememberedSetExtensions object associated with irrs tgc tracing. Attaches hooks
248
* to the appropriate functions handling events used by irrs tgc tracing.
249
*/
250
bool
251
tgcInterRegionRememberedSetInitialize(J9JavaVM *javaVM)
252
{
253
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
254
bool result = true;
255
256
J9HookInterface** privateHooks = J9_HOOK_INTERFACE(extensions->privateHookInterface);
257
J9HookInterface** omrHooks = J9_HOOK_INTERFACE(extensions->omrHookInterface);
258
(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_MARK_END, tgcHookReportInterRegionRememberedSetHistogram, OMR_GET_CALLSITE(), javaVM);
259
(*omrHooks)->J9HookRegisterWithCallSite(omrHooks, J9HOOK_MM_OMR_COMPACT_END, tgcHookReportInterRegionRememberedSetHistogram, OMR_GET_CALLSITE(), javaVM);
260
(*privateHooks)->J9HookRegisterWithCallSite(privateHooks, J9HOOK_MM_PRIVATE_COPY_FORWARD_END, tgcHookReportInterRegionRememberedSetHistogram, OMR_GET_CALLSITE(), javaVM);
261
262
return result;
263
}
264
265
void
266
tgcInterRegionRememberedSetTearDown(J9JavaVM *javaVM)
267
{
268
MM_GCExtensions *extensions = MM_GCExtensions::getExtensions(javaVM);
269
MM_TgcExtensions *tgcExtensions = MM_TgcExtensions::getExtensions(extensions);
270
271
if (NULL != tgcExtensions->_rsclDistinctFlagArray) {
272
extensions->getForge()->free(tgcExtensions->_rsclDistinctFlagArray);
273
}
274
}
275
276