Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/env/J9VMEnv.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 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
#define J9_EXTERNAL_TO_VM
24
25
#include "compile/Compilation.hpp"
26
#include "control/Options.hpp"
27
#include "control/CompilationRuntime.hpp"
28
#include "control/CompilationThread.hpp"
29
#include "env/VMEnv.hpp"
30
#include "env/CompilerEnv.hpp"
31
#include "env/VMJ9.h"
32
#include "exceptions/JITShutDown.hpp"
33
#include "infra/Assert.hpp"
34
#include "infra/Monitor.hpp"
35
#include "infra/MonitorTable.hpp"
36
#include "runtime/J9VMAccess.hpp"
37
#include "j9.h"
38
#include "j9cfg.h"
39
#include "jilconsts.h"
40
#include "vmaccess.h"
41
#if defined(J9VM_OPT_JITSERVER)
42
#include "runtime/JITClientSession.hpp"
43
#endif /* defined(J9VM_OPT_JITSERVER) */
44
45
int64_t
46
J9::VMEnv::maxHeapSizeInBytes()
47
{
48
#if defined(J9VM_OPT_JITSERVER)
49
if (auto stream = TR::CompilationInfo::getStream())
50
{
51
auto *vmInfo = TR::compInfoPT->getClientData()->getOrCacheVMInfo(stream);
52
return vmInfo->_maxHeapSizeInBytes;
53
}
54
#endif /* defined(J9VM_OPT_JITSERVER) */
55
J9JavaVM *jvm = TR::Compiler->javaVM;
56
57
if (!jvm)
58
return -1;
59
60
J9MemoryManagerFunctions * mmf = jvm->memoryManagerFunctions;
61
return (int64_t) mmf->j9gc_get_maximum_heap_size(jvm);
62
}
63
64
bool
65
J9::VMEnv::hasAccess(OMR_VMThread *omrVMThread)
66
{
67
return TR::Compiler->vm.hasAccess(self()->J9VMThreadFromOMRVMThread(omrVMThread));
68
}
69
70
71
bool
72
J9::VMEnv::hasAccess(J9VMThread *j9VMThread)
73
{
74
return (j9VMThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS) ? true : false;
75
}
76
77
78
bool
79
J9::VMEnv::hasAccess(TR::Compilation *comp)
80
{
81
return comp->fej9()->haveAccess(comp);
82
}
83
84
85
// Points to address: what if vmThread is not the compilation thread?
86
// What if the compilation thread does not have the classUnloadMonitor?
87
// What if jitConfig does not exist?
88
// What if we already have the compilationShouldBeInterrupted flag set?
89
// How do we set the error code when we throw an exception?
90
91
// IMPORTANT: acquireVMAccessIfNeeded could throw an exception,
92
// hence it is important to call this within a try block.
93
//
94
static bool
95
acquireVMaccessIfNeededInner(J9VMThread *vmThread, TR_YesNoMaybe isCompThread)
96
{
97
bool haveAcquiredVMAccess = false;
98
99
if (TR::Options::getCmdLineOptions() == 0 || // if options haven't been created yet, there is no danger
100
TR::Options::getCmdLineOptions()->getOption(TR_DisableNoVMAccess))
101
{
102
return false; // don't need to acquire VM access
103
}
104
105
// we need to test if the thread has VM access
106
TR_ASSERT(vmThread, "vmThread must be not null");
107
108
// We need to acquire VMaccess only for the compilation thread
109
if (isCompThread == TR_no)
110
{
111
TR_ASSERT((vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS), "Must have vm access if this is not a compilation thread");
112
return false;
113
}
114
115
// scan all compilation threads
116
J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;
117
TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);
118
TR::CompilationInfoPerThread *compInfoPT = compInfo->getCompInfoForThread(vmThread);
119
120
// We need to acquire VMaccess only for the compilation thread
121
if (isCompThread == TR_maybe)
122
{
123
if (!compInfoPT)
124
{
125
TR_ASSERT((vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS), "Must have vm access if this is not a compilation thread");
126
return false;
127
}
128
}
129
130
// At this point we know we deal with a compilation thread
131
//
132
TR_ASSERT(compInfoPT, "A compilation thread must have an associated compilationInfo");
133
134
if (!(vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS)) // I don't already have VM access
135
{
136
if (0 == vmThread->javaVM->internalVMFunctions->internalTryAcquireVMAccessWithMask(vmThread, J9_PUBLIC_FLAGS_HALT_THREAD_ANY_NO_JAVA_SUSPEND))
137
{
138
haveAcquiredVMAccess = true;
139
}
140
else // the GC is having exclusive VM access
141
{
142
// compilationShouldBeInterrupted flag is reset by the compilation
143
// thread when a new compilation starts.
144
145
// must test if we have the class unload monitor
146
//vmThread->osThread == classUnloadMonitor->owner()
147
148
bool hadClassUnloadMonitor = false;
149
#if !defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
150
if (TR::Options::getCmdLineOptions()->getOption(TR_EnableHCR) || TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug))
151
#endif
152
hadClassUnloadMonitor = TR::MonitorTable::get()->readReleaseClassUnloadMonitor(compInfoPT->getCompThreadId()) >= 0;
153
154
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
155
// We must have had classUnloadMonitor by the way we architected the application
156
TR_ASSERT(hadClassUnloadMonitor, "Comp thread must hold classUnloadMonitor when compiling without VMaccess");
157
#endif
158
159
//--- GC CAN INTERVENE HERE ---
160
161
// fprintf(stderr, "Have released class unload monitor temporarily\n"); fflush(stderr);
162
163
// At this point we must not hold any JIT monitors that can also be accessed by the GC
164
// As we don't know how the GC code will be modified in the future we will
165
// scan the entire list of known monitors
166
#if defined(DEBUG) || defined(PROD_WITH_ASSUMES)
167
TR::Monitor * heldMonitor = TR::MonitorTable::get()->monitorHeldByCurrentThread();
168
TR_ASSERT(!heldMonitor, "Current thread must not hold TR::Monitor %p called %s when trying to acquire VM access\n",
169
heldMonitor, TR_J9VMBase::get(jitConfig, NULL)->getJ9MonitorName((J9ThreadMonitor*)heldMonitor->getVMMonitor()));
170
#endif // #if defined(DEBUG) || defined(PROD_WITH_ASSUMES)
171
172
TR::Compilation *comp = compInfoPT->getCompilation();
173
if ((comp && comp->getOptions()->realTimeGC()) ||
174
TR::Options::getCmdLineOptions()->realTimeGC())
175
compInfoPT->waitForGCCycleMonitor(false); // used only for real-time
176
177
acquireVMAccessNoSuspend(vmThread); // blocking. Will wait for the entire GC
178
179
if (hadClassUnloadMonitor)
180
{
181
TR::MonitorTable::get()->readAcquireClassUnloadMonitor(compInfoPT->getCompThreadId());
182
//fprintf(stderr, "Have acquired class unload monitor again\n"); fflush(stderr);
183
}
184
185
// Now we can check if the GC has done some unloading or redefinition happened
186
if (compInfoPT->compilationShouldBeInterrupted())
187
{
188
// bail out
189
// fprintf(stderr, "Released classUnloadMonitor and will throw an exception because GC unloaded classes\n"); fflush(stderr);
190
//TR::MonitorTable::get()->readReleaseClassUnloadMonitor(0); // Main code should do it.
191
// releaseVMAccess(vmThread);
192
193
if (comp)
194
{
195
comp->failCompilation<TR::CompilationInterrupted>("Compilation interrupted by GC unloading classes");
196
}
197
else // I am not sure we are in a compilation; better release the monitor
198
{
199
if (hadClassUnloadMonitor)
200
TR::MonitorTable::get()->readReleaseClassUnloadMonitor(compInfoPT->getCompThreadId()); // Main code should do it.
201
throw TR::CompilationInterrupted();
202
}
203
}
204
else // GC did not do any unloading
205
{
206
haveAcquiredVMAccess = true;
207
}
208
}
209
}
210
211
/*
212
* At shutdown time the compilation thread executes Java code and it may receive a sample (see D174900)
213
* Only abort the compilation if we're explicitly prepared to handle it.
214
*/
215
if (compInfoPT->compilationShouldBeInterrupted())
216
{
217
TR_ASSERT(compInfoPT->compilationShouldBeInterrupted() != GC_COMP_INTERRUPT, "GC should not have cut in _compInfoPT=%p\n", compInfoPT);
218
219
// in prod builds take some corrective action
220
throw J9::JITShutdown();
221
}
222
223
return haveAcquiredVMAccess;
224
}
225
226
227
bool
228
J9::VMEnv::acquireVMAccessIfNeeded(OMR_VMThread *omrVMThread)
229
{
230
TR_ASSERT(0, "not implemented"); return false;
231
}
232
233
234
bool
235
J9::VMEnv::acquireVMAccessIfNeeded(TR_J9VMBase *fej9)
236
{
237
// This interface should be deprecated when the FrontEnd is redesigned and
238
// eliminated. The trouble with the CompilerEnv interface is that it doesn't
239
// yet understand compilation contexts (i.e., a 'regular' compile, an AOT
240
// compile, etc.). While this can be sorted out, the safest thing to do until
241
// that happens is to simply call the equivalent J9 FrontEnd virtual function to
242
// ensure the correct call is being made.
243
//
244
// return acquireVMaccessIfNeededInner(fej9->vmThread(), fej9->vmThreadIsCompilationThread());
245
246
return fej9->acquireVMAccessIfNeeded();
247
}
248
249
250
bool
251
J9::VMEnv::acquireVMAccessIfNeeded(TR::Compilation *comp)
252
{
253
return TR::Compiler->vm.acquireVMAccessIfNeeded(comp->fej9());
254
}
255
256
257
bool
258
J9::VMEnv::tryToAcquireAccess(TR::Compilation *comp, bool *haveAcquiredVMAccess)
259
{
260
return comp->fej9()->tryToAcquireAccess(comp, haveAcquiredVMAccess);
261
}
262
263
264
bool
265
J9::VMEnv::tryToAcquireAccess(OMR_VMThread *omrVMThread, bool *haveAcquiredVMAccess)
266
{
267
TR_ASSERT(0, "not implemented"); return false;
268
}
269
270
271
static void
272
releaseVMaccessIfNeededInner(J9VMThread *vmThread, bool haveAcquiredVMAccess)
273
{
274
if (haveAcquiredVMAccess)
275
{
276
TR_ASSERT((vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS), "Must have VM access");
277
releaseVMAccess(vmThread);
278
}
279
}
280
281
282
void
283
J9::VMEnv::releaseVMAccessIfNeeded(TR::Compilation *comp, bool haveAcquiredVMAccess)
284
{
285
comp->fej9()->releaseVMAccessIfNeeded(haveAcquiredVMAccess);
286
}
287
288
289
void
290
J9::VMEnv::releaseVMAccessIfNeeded(OMR_VMThread *omrVMThread, bool haveAcquiredVMAccess)
291
{
292
releaseVMaccessIfNeededInner(self()->J9VMThreadFromOMRVMThread(omrVMThread), haveAcquiredVMAccess);
293
}
294
295
296
void
297
J9::VMEnv::releaseVMAccessIfNeeded(TR_J9VMBase *fej9, bool haveAcquiredVMAccess)
298
{
299
fej9->releaseVMAccessIfNeeded(haveAcquiredVMAccess);
300
}
301
302
303
void
304
J9::VMEnv::releaseAccess(TR::Compilation *comp)
305
{
306
comp->fej9()->releaseAccess(comp);
307
}
308
309
310
void
311
J9::VMEnv::releaseAccess(OMR_VMThread *omrVMThread)
312
{
313
TR_ASSERT(0, "not implemented");
314
}
315
316
317
void
318
J9::VMEnv::releaseAccess(TR_J9VMBase *fej9)
319
{
320
if (fej9->vmThread()->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS)
321
{
322
releaseVMAccess(fej9->vmThread());
323
}
324
}
325
326
uintptr_t
327
J9::VMEnv::thisThreadGetPendingExceptionOffset()
328
{
329
return offsetof(J9VMThread, jitException);
330
}
331
332
bool
333
J9::VMEnv::hasResumableTrapHandler(TR::Compilation *comp)
334
{
335
return comp->fej9()->hasResumableTrapHandler();
336
}
337
338
bool
339
J9::VMEnv::hasResumableTrapHandler(OMR_VMThread *omrVMThread)
340
{
341
TR_ASSERT(0, "not implemented"); return false;
342
}
343
344
uint64_t
345
J9::VMEnv::getUSecClock(TR::Compilation *comp)
346
{
347
return comp->fej9()->getUSecClock();
348
}
349
350
uint64_t
351
J9::VMEnv::getUSecClock(OMR_VMThread *omrVMThread)
352
{
353
TR_ASSERT(0, "not implemented"); return 0;
354
}
355
356
uint64_t
357
J9::VMEnv::getHighResClock(TR::Compilation *comp)
358
{
359
return comp->fej9()->getHighResClock();
360
}
361
362
uint64_t
363
J9::VMEnv::getHighResClock(OMR_VMThread *omrVMThread)
364
{
365
TR_ASSERT(0, "not implemented"); return 0;
366
}
367
368
uint64_t
369
J9::VMEnv::getHighResClockResolution(TR::Compilation *comp)
370
{
371
return comp->fej9()->getHighResClockResolution();
372
}
373
374
uint64_t
375
J9::VMEnv::getHighResClockResolution(OMR_VMThread *omrVMThread)
376
{
377
TR_ASSERT(0, "not implemented"); return 0;
378
}
379
380
uint64_t
381
J9::VMEnv::getHighResClockResolution(TR_FrontEnd *fej9)
382
{
383
return ((TR_J9VMBase*)fej9)->getHighResClockResolution();
384
}
385
386
uint64_t
387
J9::VMEnv::getHighResClockResolution()
388
{
389
PORT_ACCESS_FROM_PORT(TR::Compiler->portLib);
390
return j9time_hires_frequency();
391
}
392
393
bool
394
J9::VMEnv::canMethodEnterEventBeHooked(TR::Compilation *comp)
395
{
396
return comp->fej9()->canMethodEnterEventBeHooked();
397
}
398
399
bool
400
J9::VMEnv::canMethodExitEventBeHooked(TR::Compilation *comp)
401
{
402
return comp->fej9()->canMethodExitEventBeHooked();
403
}
404
405
uintptr_t
406
J9::VMEnv::getOverflowSafeAllocSize(TR::Compilation *comp)
407
{
408
return comp->fej9()->getOverflowSafeAllocSize();
409
}
410
411
412
int64_t
413
J9::VMEnv::cpuTimeSpentInCompilationThread(TR::Compilation *comp)
414
{
415
return comp->fej9()->getCpuTimeSpentInCompThread(comp);
416
}
417
418
419
uintptr_t
420
J9::VMEnv::OSRFrameHeaderSizeInBytes(TR::Compilation *comp)
421
{
422
return comp->fej9()->getOSRFrameHeaderSizeInBytes();
423
}
424
425
426
uintptr_t
427
J9::VMEnv::OSRFrameSizeInBytes(TR::Compilation *comp, TR_OpaqueMethodBlock* method)
428
{
429
return comp->fej9()->getOSRFrameSizeInBytes(method);
430
}
431
432
433
bool
434
J9::VMEnv::ensureOSRBufferSize(TR::Compilation *comp, uintptr_t osrFrameSizeInBytes, uintptr_t osrScratchBufferSizeInBytes, uintptr_t osrStackFrameSizeInBytes)
435
{
436
return comp->fej9()->ensureOSRBufferSize(comp, osrFrameSizeInBytes, osrScratchBufferSizeInBytes, osrStackFrameSizeInBytes);
437
}
438
439
uintptr_t
440
J9::VMEnv::thisThreadGetOSRReturnAddressOffset(TR::Compilation *comp)
441
{
442
return comp->fej9()->thisThreadGetOSRReturnAddressOffset();
443
}
444
445
uintptr_t
446
J9::VMEnv::thisThreadGetGSIntermediateResultOffset(TR::Compilation *comp)
447
{
448
return comp->fej9()->thisThreadGetGSIntermediateResultOffset();
449
}
450
451
uintptr_t
452
J9::VMEnv::thisThreadGetConcurrentScavengeActiveByteAddressOffset(TR::Compilation *comp)
453
{
454
return comp->fej9()->thisThreadGetConcurrentScavengeActiveByteAddressOffset();
455
}
456
457
uintptr_t
458
J9::VMEnv::thisThreadGetEvacuateBaseAddressOffset(TR::Compilation *comp)
459
{
460
return comp->fej9()->thisThreadGetEvacuateBaseAddressOffset();
461
}
462
463
uintptr_t
464
J9::VMEnv::thisThreadGetEvacuateTopAddressOffset(TR::Compilation *comp)
465
{
466
return comp->fej9()->thisThreadGetEvacuateTopAddressOffset();
467
}
468
469
uintptr_t
470
J9::VMEnv::thisThreadGetGSOperandAddressOffset(TR::Compilation *comp)
471
{
472
return comp->fej9()->thisThreadGetGSOperandAddressOffset();
473
}
474
475
uintptr_t
476
J9::VMEnv::thisThreadGetGSHandlerAddressOffset(TR::Compilation *comp)
477
{
478
return comp->fej9()->thisThreadGetGSHandlerAddressOffset();
479
}
480
481
/*
482
* Method enter/exit hooks are only enabled for some specific methods
483
*/
484
bool
485
J9::VMEnv::isSelectiveMethodEnterExitEnabled(TR::Compilation *comp)
486
{
487
return comp->fej9()->isSelectiveMethodEnterExitEnabled();
488
}
489
490
size_t
491
J9::VMEnv::getInterpreterVTableOffset()
492
{
493
#if defined(J9VM_OPT_JITSERVER)
494
if (auto stream = TR::CompilationInfo::getStream())
495
{
496
auto *vmInfo = TR::compInfoPT->getClientData()->getOrCacheVMInfo(stream);
497
return vmInfo->_interpreterVTableOffset;
498
}
499
#endif /* defined(J9VM_OPT_JITSERVER) */
500
return sizeof(J9Class);
501
}
502
503
bool
504
J9::VMEnv::isVMInStartupPhase(J9JITConfig *jitConfig)
505
{
506
#if defined(J9VM_OPT_JITSERVER)
507
if (auto stream = TR::CompilationInfo::getStream())
508
{
509
return TR::compInfoPT->getClientData()->isInStartupPhase();
510
}
511
#endif /* defined(J9VM_OPT_JITSERVER) */
512
return jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP;
513
}
514
515