Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/gcchk/gcchk.cpp
5986 views
1
2
/*******************************************************************************
3
* Copyright (c) 1991, 2018 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
/**
25
* @file
26
* @ingroup GCChk
27
*/
28
29
#include "j9.h"
30
#include "jni.h"
31
#include "j9port.h"
32
#include "jvminit.h"
33
#include "modronopt.h"
34
#include "gcchk.h"
35
36
#include <string.h>
37
38
#include "CheckBase.hpp"
39
#include "CheckEngine.hpp"
40
#include "CheckError.hpp"
41
#include "CheckReporterTTY.hpp"
42
#include "GCExtensions.hpp"
43
#include "ModronTypes.hpp"
44
#include "ObjectModel.hpp"
45
#include "CycleState.hpp"
46
47
extern "C" {
48
49
void hookGcCycleStart(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData);
50
void hookGcCycleEnd(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData);
51
52
#if (defined(J9VM_GC_MODRON_SCAVENGER)) /* priv. proto (autogen) */
53
void hookScavengerBackOut(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData);
54
#endif /* J9VM_GC_MODRON_SCAVENGER (autogen) */
55
56
#if defined(J9VM_GC_GENERATIONAL)
57
void hookRememberedSetOverflow(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData);
58
#endif /* J9VM_GC_GENERATIONAL */
59
60
void hookInvokeGCCheck(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData);
61
62
63
static IDATA OnLoad(J9JavaVM * javaVM, const char *options);
64
static IDATA OnUnload(J9JavaVM * javaVM);
65
66
IDATA
67
J9VMDllMain(J9JavaVM* vm, IDATA stage, void* reserved)
68
{
69
if (stage == ALL_VM_ARGS_CONSUMED) {
70
const char* options = "";
71
IDATA xcheckGCIndex = FIND_AND_CONSUME_ARG( OPTIONAL_LIST_MATCH, "-Xcheck:gc", NULL );
72
73
if (xcheckGCIndex >= 0) {
74
GET_OPTION_VALUE(xcheckGCIndex, ':', &options);
75
options = strchr(options, ':');
76
if (options == NULL) {
77
options = "";
78
} else {
79
options++;
80
}
81
}
82
83
return OnLoad(vm, options);
84
} else if (stage == LIBRARIES_ONUNLOAD) {
85
return OnUnload(vm);
86
} else {
87
return J9VMDLLMAIN_OK;
88
}
89
}
90
91
/**
92
* Perform the actions required by GCCheck on JVM load.
93
*
94
* Initialize a GC_CheckEngine object, parse the J9 command line for the prefered
95
* options and install the appropriate hooks.
96
*/
97
static IDATA
98
OnLoad(J9JavaVM *javaVM, const char *options)
99
{
100
GCCHK_Extensions *extensions;
101
GC_CheckReporter *reporter;
102
J9HookInterface** mmPrivateHooks = J9_HOOK_INTERFACE((MM_GCExtensions::getExtensions(javaVM))->privateHookInterface);
103
J9HookInterface** mmOmrHooks = J9_HOOK_INTERFACE((MM_GCExtensions::getExtensions(javaVM))->omrHookInterface);
104
PORT_ACCESS_FROM_JAVAVM(javaVM);
105
MM_Forge *forge = MM_GCExtensions::getExtensions(javaVM)->getForge();
106
107
/* catch just outputting the help text */
108
if(!strcmp(options, "help")) {
109
GC_CheckCycle::printHelp(PORTLIB);
110
return J9VMDLLMAIN_SILENT_EXIT_VM;
111
}
112
113
extensions = (GCCHK_Extensions *)forge->allocate(sizeof(GCCHK_Extensions), MM_AllocationCategory::DIAGNOSTIC, J9_GET_CALLSITE());
114
if (!extensions) {
115
goto error_no_memory;
116
}
117
memset(extensions, 0, sizeof(GCCHK_Extensions));
118
(MM_GCExtensions::getExtensions(javaVM))->gcchkExtensions = extensions;
119
120
/* Instantiate the reporter, check, and command-line cycle objects */
121
reporter = GC_CheckReporterTTY::newInstance(javaVM);
122
if (!reporter) {
123
goto error_no_memory;
124
}
125
extensions->checkEngine = (void *)GC_CheckEngine::newInstance(javaVM, reporter);
126
if (!extensions->checkEngine) {
127
goto error_no_memory;
128
}
129
130
extensions->checkCycle = (void *)GC_CheckCycle::newInstance(javaVM, (GC_CheckEngine *)extensions->checkEngine, options);
131
if(!extensions->checkCycle) {
132
goto error_no_memory;
133
}
134
135
if(!(((GC_CheckCycle *)extensions->checkCycle)->getMiscFlags() & J9MODRON_GCCHK_MANUAL)) {
136
/* Install the hooks */
137
(*mmOmrHooks)->J9HookRegisterWithCallSite(mmOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_START, hookGcCycleStart, OMR_GET_CALLSITE(), NULL);
138
(*mmOmrHooks)->J9HookRegisterWithCallSite(mmOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_END, hookGcCycleEnd, OMR_GET_CALLSITE(), NULL);
139
140
#if defined(J9VM_GC_MODRON_SCAVENGER)
141
/* Install scavengerBackOut hooks */
142
(*mmPrivateHooks)->J9HookRegisterWithCallSite(mmPrivateHooks, J9HOOK_MM_PRIVATE_SCAVENGER_BACK_OUT, hookScavengerBackOut, OMR_GET_CALLSITE(), NULL);
143
#endif /* J9VM_GC_MODRON_SCAVENGER */
144
145
#if defined(J9VM_GC_GENERATIONAL)
146
(*mmPrivateHooks)->J9HookRegisterWithCallSite(mmPrivateHooks, J9HOOK_MM_PRIVATE_REMEMBEREDSET_OVERFLOW, hookRememberedSetOverflow, OMR_GET_CALLSITE(), NULL);
147
#endif /* J9VM_GC_GENERATIONAL */
148
}
149
150
/* Install handler to run GCCheck from anywhere in GC code. */
151
(*mmPrivateHooks)->J9HookRegisterWithCallSite(mmPrivateHooks, J9HOOK_MM_PRIVATE_INVOKE_GC_CHECK, hookInvokeGCCheck, OMR_GET_CALLSITE(), NULL);
152
153
/* Set the ALLOW_USER_HEAP_WALK bit in the requiredDebugAttributes flag so GC Check can walk the heap */
154
javaVM->requiredDebugAttributes |= J9VM_DEBUG_ATTRIBUTE_ALLOW_USER_HEAP_WALK;
155
156
if (((GC_CheckCycle *)extensions->checkCycle)->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
157
j9tty_printf(PORTLIB, "<gc check installed>\n");
158
}
159
160
return J9VMDLLMAIN_OK;
161
162
error_no_memory:
163
if (extensions) {
164
if (extensions->checkEngine) {
165
((GC_CheckEngine *)extensions->checkEngine)->kill();
166
} else if (reporter) {
167
/* CheckEngine will kill the reporter if the CheckEngine was created */
168
reporter->kill();
169
}
170
171
if(extensions->checkCycle) {
172
((GC_CheckCycle *)extensions->checkCycle)->kill();
173
}
174
175
forge->free(extensions);
176
((MM_GCExtensions *)javaVM->gcExtensions)->gcchkExtensions = NULL;
177
}
178
return J9VMDLLMAIN_FAILED;
179
}
180
181
/**
182
* Perform the actions required by GCCheck on JVM Unload.
183
* Free any OS resources created by OnLoad.
184
*/
185
static IDATA
186
OnUnload(J9JavaVM *javaVM )
187
{
188
GCCHK_Extensions *extensions = (GCCHK_Extensions *)(MM_GCExtensions::getExtensions(javaVM))->gcchkExtensions;
189
MM_Forge *forge = MM_GCExtensions::getExtensions(javaVM)->getForge();
190
191
if(extensions) {
192
((GC_CheckEngine *)extensions->checkEngine)->kill();
193
((GC_CheckCycle *)extensions->checkCycle)->kill();
194
forge->free(extensions);
195
((MM_GCExtensions *)javaVM->gcExtensions)->gcchkExtensions = NULL;
196
}
197
198
return J9VMDLLMAIN_OK;
199
}
200
201
#if (defined(J9VM_GC_MODRON_SCAVENGER)) /* priv. proto (autogen) */
202
/**
203
* Determine whether the next local GC should be excluded from checking.
204
*
205
* @return false if we SHOULD perform a check before the next local
206
* GC, i.e. the next local GC should NOT be excluded
207
* @return true if we should NOT perform a check
208
*/
209
bool
210
excludeLocalGc(J9JavaVM *javaVM)
211
{
212
MM_GCExtensions *gcExtensions = MM_GCExtensions::getExtensions(javaVM);
213
GCCHK_Extensions *extensions = (GCCHK_Extensions *)gcExtensions->gcchkExtensions;
214
GC_CheckEngine *gcCheck = (GC_CheckEngine *)extensions->checkEngine;
215
GC_CheckCycle *cycle = (GC_CheckCycle *)extensions->checkCycle;
216
bool ret = false;
217
218
/* User either requested that localGC be suppressed, or inform them only on remembered set overflow.
219
* Either way, local information is not provided.
220
*/
221
if ((cycle->getMiscFlags() & J9MODRON_GCCHK_SUPPRESS_LOCAL) ||
222
((cycle->getMiscFlags() & J9MODRON_GCCHK_REMEMBEREDSET_OVERFLOW) && (!gcCheck->_rsOverflowState))) {
223
return true;
224
}
225
226
/* Don't check after Concurrent Scavenge aborted (even if J9MODRON_GCCHK_SCAVENGER_BACKOUT requested). Nursery is not walkable
227
* between aborted CS and following percolated global GC. The check will be done after percolate GC is complete (which will do most of heap fixup).
228
* Since gcCheck->_scavengerBackout is only set if J9MODRON_GCCHK_SCAVENGER_BACKOUT is requested, relying on gcExtensions->isScavengerBackOutFlagRaised() instead.
229
*/
230
if (gcExtensions->isConcurrentScavengerEnabled() && gcExtensions->isScavengerBackOutFlagRaised()) {
231
return true;
232
}
233
234
/* If the request was for scavenger backout and there wasn't one, no check */
235
if ((cycle->getMiscFlags() & J9MODRON_GCCHK_SCAVENGER_BACKOUT) && (!gcCheck->_scavengerBackout)) {
236
return true;
237
}
238
239
if (cycle->getMiscFlags() & J9MODRON_GCCHK_LOCAL_INTERVAL) {
240
if ((extensions->localGcCount % extensions->localGcInterval) == 0) {
241
return false;
242
} else {
243
ret = true;
244
}
245
}
246
247
if (cycle->getMiscFlags() & J9MODRON_GCCHK_INTERVAL) {
248
return ( ((extensions->globalGcCount + extensions->localGcCount) % extensions->gcInterval) != 0 );
249
}
250
251
if (cycle->getMiscFlags() & J9MODRON_GCCHK_START_INDEX) {
252
return ((extensions->globalGcCount + extensions->localGcCount) < extensions->gcStartIndex);
253
}
254
255
return ret;
256
}
257
258
/**
259
* GCCheck function for hookScavengerBackOut.
260
* The scavenger is backing out. Set our flag so we know to report the localEnd hook information.
261
*/
262
void
263
hookScavengerBackOut(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
264
{
265
MM_ScavengerBackOutEvent* event = (MM_ScavengerBackOutEvent*)eventData;
266
bool value = (event->value == TRUE);
267
GCCHK_Extensions *extensions = (GCCHK_Extensions *)(MM_GCExtensions::getExtensions(event->omrVM))->gcchkExtensions;
268
GC_CheckEngine *checkEngine = (GC_CheckEngine *)extensions->checkEngine;
269
GC_CheckCycle *cycle = (GC_CheckCycle *)extensions->checkCycle;
270
271
if (cycle->getMiscFlags() & J9MODRON_GCCHK_SCAVENGER_BACKOUT) {
272
checkEngine->_scavengerBackout = value;
273
}
274
}
275
#endif /* J9VM_GC_MODRON_SCAVENGER (autogen) */
276
277
/**
278
* Determine whether the next global GC should be excluded from checking.
279
*
280
* @return false if we SHOULD perform a check before the next global
281
* GC, i.e. the next global GC should NOT be excluded
282
* @return true if we should NOT perform a check
283
*/
284
bool
285
excludeGlobalGc(J9VMThread* vmThread)
286
{
287
J9JavaVM *javaVM = vmThread->javaVM;
288
MM_GCExtensions *gcExtensions = MM_GCExtensions::getExtensions(javaVM);
289
GCCHK_Extensions *extensions = (GCCHK_Extensions *)gcExtensions->gcchkExtensions;
290
GC_CheckCycle *cycle = (GC_CheckCycle *)extensions->checkCycle;
291
GC_CheckEngine *gcCheck = (GC_CheckEngine *)extensions->checkEngine;
292
bool ret = false;
293
UDATA gcCount;
294
295
/* If Concurrent Scavenger aborted, do not check before global GC (regardless if J9MODRON_GCCHK_SCAVENGER_BACKOUT is requested or not).
296
* Since checkEngine->_scavengerBackout is set only if J9MODRON_GCCHK_SCAVENGER_BACKOUT requested, gcExtensions->isScavengerBackOutFlagRaised() is checked instead. */
297
if (gcExtensions->isConcurrentScavengerEnabled() && gcExtensions->isScavengerBackOutFlagRaised() && (OMRVMSTATE_GC_CHECK_BEFORE_GC == vmThread->omrVMThread->vmState)) {
298
return true;
299
}
300
301
/* User either requested that globalGC be suppressed, or inform them only on
302
* scavenger backout or remembered set overflow.
303
* Either way, global information is not provided.
304
*/
305
if ((cycle->getMiscFlags() & J9MODRON_GCCHK_SUPPRESS_GLOBAL) ||
306
(cycle->getMiscFlags() & J9MODRON_GCCHK_REMEMBEREDSET_OVERFLOW)) {
307
return true;
308
}
309
310
if (cycle->getMiscFlags() & J9MODRON_GCCHK_SCAVENGER_BACKOUT) {
311
/* if J9MODRON_GCCHK_SCAVENGER_BACKOUT is requested, the check will be done at the end of percolate global GC (not at the end of the aborted scavenge).
312
* Recovery from the aborted CS is mostly done in the global GC and Nursery is not walkable between aborted CS and percolate global.
313
* Since GC check is done in global GC cycle end hook, gcExtensions->isScavengerBackOutFlagRaised just has been reset, so we have to rely
314
* on gcCheck->_scavengerBackout, which is yet to be cleared in the initialization of this check cycle */
315
if (!(gcExtensions->isConcurrentScavengerEnabled() && gcCheck->_scavengerBackout)) {
316
return true;
317
}
318
}
319
320
if (cycle->getMiscFlags() & J9MODRON_GCCHK_GLOBAL_INTERVAL) {
321
if ( (extensions->globalGcCount % extensions->globalGcInterval) == 0 ) {
322
return false;
323
} else {
324
ret = true;
325
}
326
}
327
328
gcCount = extensions->globalGcCount;
329
#if defined(J9VM_GC_MODRON_SCAVENGER)
330
gcCount += extensions->localGcCount;
331
#endif /* J9VM_GC_MODRON_SCAVENGER */
332
if (cycle->getMiscFlags() & J9MODRON_GCCHK_INTERVAL) {
333
return ((gcCount % extensions->gcInterval) != 0 );
334
}
335
336
if (cycle->getMiscFlags() & J9MODRON_GCCHK_START_INDEX) {
337
return (gcCount < extensions->gcStartIndex);
338
}
339
340
return ret;
341
}
342
343
/**
344
* GCCheck function for hookGcCycleStart.
345
* Check memory management structures prior to garbage collection.
346
*/
347
void
348
hookGcCycleStart(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
349
{
350
MM_GCCycleStartEvent* event = (MM_GCCycleStartEvent*)eventData;
351
J9VMThread* vmThread = (J9VMThread*)MM_EnvironmentBase::getEnvironment(event->omrVMThread)->getLanguageVMThread();
352
J9JavaVM *javaVM = vmThread->javaVM;
353
GCCHK_Extensions *extensions = (GCCHK_Extensions *)(MM_GCExtensions::getExtensions(javaVM))->gcchkExtensions;
354
GC_CheckCycle *cycle = (GC_CheckCycle *)extensions->checkCycle;
355
PORT_ACCESS_FROM_JAVAVM(javaVM);
356
357
UDATA oldVMState = vmThread->omrVMThread->vmState;
358
vmThread->omrVMThread->vmState = OMRVMSTATE_GC_CHECK_BEFORE_GC;
359
360
if (OMR_GC_CYCLE_TYPE_GLOBAL == event->cycleType) {
361
++extensions->globalGcCount;
362
if (!excludeGlobalGc(vmThread)) {
363
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
364
j9tty_printf(PORTLIB, "<gc check: start verifying slots before global gc (%zu)>\n", extensions->globalGcCount);
365
}
366
367
cycle->run(invocation_global_start);
368
369
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
370
j9tty_printf(PORTLIB, "<gc check: finished verifying slots before global gc (%zu)>\n", extensions->globalGcCount);
371
}
372
}
373
}
374
#if defined(J9VM_GC_MODRON_SCAVENGER)
375
else if (OMR_GC_CYCLE_TYPE_SCAVENGE == event->cycleType) {
376
++extensions->localGcCount;
377
if (!excludeLocalGc(javaVM)) {
378
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
379
j9tty_printf(PORTLIB, "<gc check: start verifying slots before local gc (%zu)>\n", extensions->localGcCount);
380
}
381
382
cycle->run(invocation_local_start);
383
384
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
385
j9tty_printf(PORTLIB, "<gc check: finished verifying slots before local gc (%zu)>\n", extensions->localGcCount);
386
}
387
}
388
}
389
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */
390
else {
391
++extensions->globalGcCount;
392
if (!excludeGlobalGc(vmThread)) {
393
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
394
j9tty_printf(PORTLIB, "<gc check: start verifying slots before default gc (%zu)>\n", extensions->globalGcCount);
395
}
396
397
cycle->run(invocation_global_start);
398
399
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
400
j9tty_printf(PORTLIB, "<gc check: finished verifying slots before default gc (%zu)>\n", extensions->globalGcCount);
401
}
402
}
403
}
404
vmThread->omrVMThread->vmState = oldVMState;
405
}
406
407
/**
408
* GCCheck function for hookGcCycleEnd.
409
* Check memory management structures after garbage collection.
410
*/
411
void
412
hookGcCycleEnd(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
413
{
414
MM_GCCycleEndEvent* event = (MM_GCCycleEndEvent*)eventData;
415
J9VMThread* vmThread = (J9VMThread*)MM_EnvironmentBase::getEnvironment(event->omrVMThread)->getLanguageVMThread();
416
J9JavaVM *javaVM = vmThread->javaVM;
417
GCCHK_Extensions *extensions = (GCCHK_Extensions *)(MM_GCExtensions::getExtensions(javaVM))->gcchkExtensions;
418
GC_CheckCycle *cycle = (GC_CheckCycle *)extensions->checkCycle;
419
PORT_ACCESS_FROM_JAVAVM(javaVM);
420
421
UDATA oldVMState = vmThread->omrVMThread->vmState;
422
vmThread->omrVMThread->vmState = OMRVMSTATE_GC_CHECK_AFTER_GC;
423
424
if (OMR_GC_CYCLE_TYPE_GLOBAL == event->cycleType) {
425
if (!excludeGlobalGc(vmThread)) {
426
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
427
j9tty_printf(PORTLIB, "<gc check: start verifying slots after global gc (%zu)>\n", extensions->globalGcCount);
428
}
429
430
cycle->run(invocation_global_end);
431
432
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
433
j9tty_printf(PORTLIB, "<gc check: finished verifying slots after global gc (%zu)>\n", extensions->globalGcCount);
434
}
435
}
436
}
437
#if defined(J9VM_GC_MODRON_SCAVENGER)
438
else if (OMR_GC_CYCLE_TYPE_SCAVENGE == event->cycleType) {
439
if (!excludeLocalGc(javaVM)) {
440
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
441
j9tty_printf(PORTLIB, "<gc check: start verifying slots after local gc (%zu)>\n", extensions->localGcCount);
442
}
443
444
cycle->run(invocation_local_end);
445
446
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
447
j9tty_printf(PORTLIB, "<gc check: finished verifying slots after local gc (%zu)>\n", extensions->localGcCount);
448
}
449
}
450
}
451
#endif /* defined(J9VM_GC_MODRON_SCAVENGER) */
452
else {
453
if (!excludeGlobalGc(vmThread)) {
454
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
455
j9tty_printf(PORTLIB, "<gc check: start verifying slots after default gc (%zu)>\n", extensions->globalGcCount);
456
}
457
458
cycle->run(invocation_global_end);
459
460
if (cycle->getMiscFlags() & J9MODRON_GCCHK_VERBOSE) {
461
j9tty_printf(PORTLIB, "<gc check: finished verifying slots after default gc (%zu)>\n", extensions->globalGcCount);
462
}
463
}
464
}
465
vmThread->omrVMThread->vmState = oldVMState;
466
}
467
468
#if defined(J9VM_GC_GENERATIONAL)
469
/**
470
* GCCheck function for hookRememberedSetOverflow.
471
*/
472
void
473
hookRememberedSetOverflow(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
474
{
475
MM_RememberedSetOverflowEvent* event = (MM_RememberedSetOverflowEvent*)eventData;
476
GCCHK_Extensions *extensions = (GCCHK_Extensions *)(MM_GCExtensions::getExtensions(event->currentThread))->gcchkExtensions;
477
GC_CheckEngine *checkEngine = (GC_CheckEngine *)extensions->checkEngine;
478
GC_CheckCycle *cycle = (GC_CheckCycle *)extensions->checkCycle;
479
480
if (cycle->getMiscFlags() & J9MODRON_GCCHK_REMEMBEREDSET_OVERFLOW) {
481
checkEngine->_rsOverflowState = MM_GCExtensions::getExtensions(event->currentThread)->isRememberedSetInOverflowState();
482
}
483
}
484
#endif /* J9VM_GC_GENERATIONAL */
485
486
/**
487
* Manually initiate a GCCheck run (as opposed to having one triggered by a GC).
488
* Users wishing to manually start GCCheck should add code like the following
489
* <pre>
490
#include "mmhook_internal.h"
491
492
PORT_ACCESS_FROM_JAVAVM(javaVM);
493
494
TRIGGER_J9HOOK_MM_PRIVATE_INVOKE_GC_CHECK(_extensions->hookInterface, _javaVM, PORTLIB, "all:all:verbose", 0);
495
}
496
* </pre>
497
* GCCheck must be installed for via the command line. Specifying -Xrunj9gcchk23:none:none:quiet,nocheck will ensure
498
* GCCheck does not run for any GC event. Thus all output is controlled by the user placed invocations. Users
499
* can specify other options on the command line if they wish. These options are not passed to user invoked
500
* invocations.
501
*
502
* @param javaVM the javaVM
503
* @param portLibrary where to output results
504
* @param options what events to invoke GCCheck on
505
* @param invocationNumber uniquely identifies which manual invocation has triggered the GCCheck
506
*
507
* @return void
508
*/
509
void
510
hookInvokeGCCheck(J9HookInterface** hook, UDATA eventNum, void* eventData, void* userData)
511
{
512
MM_InvokeGCCheckEvent* event = (MM_InvokeGCCheckEvent*)eventData;
513
J9JavaVM *javaVM = static_cast<J9JavaVM*>(event->omrVM->_language_vm);
514
GCCHK_Extensions *extensions = (GCCHK_Extensions *)((MM_GCExtensions *)javaVM->gcExtensions)->gcchkExtensions;
515
GC_CheckEngine *checkEngine = (GC_CheckEngine *)extensions->checkEngine;
516
GC_CheckCycle *cycle;
517
518
if (checkEngine) {
519
cycle = GC_CheckCycle::newInstance(javaVM, checkEngine, event->options, event->invocationNumber);
520
if(cycle) {
521
cycle->run(invocation_manual);
522
cycle->kill();
523
}
524
}
525
}
526
527
} /* extern "C" */
528
529