Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/control/HookedByTheJit.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2022 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 <algorithm>
24
#include <limits.h>
25
#include <stdarg.h>
26
#include "bcnames.h"
27
#include "jithash.h"
28
#include "jitprotos.h"
29
#include "j9.h"
30
#include "j9cfg.h"
31
#include "j9modron.h"
32
#include "j9nonbuilder.h"
33
#include "j9consts.h"
34
#include "mmhook.h"
35
#include "mmomrhook.h"
36
#include "vmaccess.h"
37
#include "codegen/CodeGenerator.hpp"
38
#include "compile/CompilationTypes.hpp"
39
#include "compile/Method.hpp"
40
#include "compile/ResolvedMethod.hpp"
41
#include "control/OptimizationPlan.hpp"
42
#include "control/OptionsUtil.hpp"
43
#include "control/Recompilation.hpp"
44
#include "control/RecompilationInfo.hpp"
45
#include "control/CompilationController.hpp"
46
#include "env/ClassLoaderTable.hpp"
47
#include "env/CompilerEnv.hpp"
48
#include "env/IO.hpp"
49
#include "env/J2IThunk.hpp"
50
#include "env/PersistentCHTable.hpp"
51
#include "env/PersistentInfo.hpp"
52
#include "env/jittypes.h"
53
#include "env/ClassTableCriticalSection.hpp"
54
#include "env/VMAccessCriticalSection.hpp"
55
#include "env/VMJ9.h"
56
#include "env/VerboseLog.hpp"
57
#include "il/DataTypes.hpp"
58
#include "ilgen/IlGeneratorMethodDetails_inlines.hpp"
59
#include "infra/Monitor.hpp"
60
#include "infra/MonitorTable.hpp"
61
#include "infra/CriticalSection.hpp"
62
#include "optimizer/DebuggingCounters.hpp"
63
#include "optimizer/JProfilingBlock.hpp"
64
#include "runtime/CodeCacheManager.hpp"
65
#include "runtime/HookHelpers.hpp"
66
#include "runtime/MethodMetaData.h"
67
#include "runtime/RelocationRuntime.hpp"
68
#include "runtime/asmprotos.h"
69
#include "runtime/codertinit.hpp"
70
#include "control/MethodToBeCompiled.hpp"
71
#include "control/CompilationRuntime.hpp"
72
#include "control/CompilationThread.hpp"
73
#include "env/VMJ9.h"
74
#include "env/j9method.h"
75
#include "env/ut_j9jit.h"
76
#include "ilgen/J9ByteCodeIlGenerator.hpp"
77
#include "ilgen/J9ByteCodeIterator.hpp"
78
#include "runtime/IProfiler.hpp"
79
#include "runtime/HWProfiler.hpp"
80
#include "env/SystemSegmentProvider.hpp"
81
#if defined(J9VM_OPT_JITSERVER)
82
#include "control/JITServerHelpers.hpp"
83
#include "runtime/JITServerAOTDeserializer.hpp"
84
#include "runtime/JITServerIProfiler.hpp"
85
#include "runtime/JITServerStatisticsThread.hpp"
86
#include "runtime/Listener.hpp"
87
#endif /* defined(J9VM_OPT_JITSERVER) */
88
89
extern "C" {
90
struct J9JavaVM;
91
}
92
93
#if defined(J9ZOS390) && defined(TR_TARGET_32BIT)
94
#include <stdlib.h>
95
96
#define PSAAOLD 0x224 ///< offset of current ASCB in prefixed save area (located at address 0x0)
97
#define ASCBLDA 0x30 ///< offset of LDA field in ASCB
98
#define LDASTRTA 0x3c ///< offset of user region start in LDA
99
#define LDASIZA 0x40 ///< offset of maximum user region size in LDA
100
#define LDAESTRA 0x4c ///< offset of extended user region start in LDA
101
#define LDAESIZA 0x50 ///< offset of maximum extended user region size in LDA
102
#define LDACRGTP 0x98 ///< offset of user region top in LDA
103
#define LDAERGTP 0x9c ///< offset of extended user region top in LDA
104
105
struct LDA {
106
uint32_t padding1[15]; ///< Padding
107
void * strta; ///< User Region Start
108
uint32_t siza; ///< Max size of the User Region
109
uint32_t padding2[2]; ///< Padding
110
void * estra; ///< Extended User Region Start
111
uint32_t esiza; ///< Max size of the Extended User Region
112
uint32_t padding3[17]; ///< Padding
113
void * crgtp; ///< User Region Top
114
void * ergtp; ///< Extended User Region Top
115
};
116
#endif
117
118
#ifdef J9VM_JIT_RUNTIME_INSTRUMENTATION
119
// extern until function is added to oti/jitprotos.h
120
extern "C" void shutdownJITRuntimeInstrumentation(J9JavaVM *vm);
121
#endif
122
123
/* 1) Regular hooks
124
* These fire when a normal condition occurs.
125
* Ie: In the case of the "jitHookInitializeSendTarget" hook,
126
* the VM triggers the event as its initializing the send targets for a class.
127
* This is part of the normal code flow.
128
*/
129
130
/* 2) Async hooks
131
* These fire when requested by an outside thread.
132
* The thread requesting the async event has each thread/requested thread stop at
133
* its next safepoint to acknowledge the event.
134
* The interrupted thread runs the handler and then continues its execution.
135
*/
136
137
void
138
cgOnClassUnloading(void *loaderPtr)
139
{
140
#if defined(TR_TARGET_POWER) && defined(TR_HOST_POWER) && defined(TR_TARGET_64BIT)
141
if (TR::Compiler->target.cpu.isPower())
142
TR::CodeGenerator::ppcCGOnClassUnloading(loaderPtr);
143
#endif
144
}
145
146
extern TR::Monitor *assumptionTableMutex;
147
148
extern volatile bool shutdownSamplerThread;
149
150
#if defined(AOTRT_DLL)
151
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
152
extern void rtHookClassUnload(J9HookInterface * *, UDATA , void *, void *);
153
extern void rtHookClassLoaderUnload(J9HookInterface * *, UDATA , void *, void *);
154
#endif
155
#endif
156
157
#ifdef FIXUP_UNALIGNED
158
#ifdef J9VM_ENV_LITTLE_ENDIAN
159
#define BC_OP_U16(bcPtr) (((*(((uint8_t*)(bcPtr))+1))<<8) + (*((uint8_t*)(bcPtr))))
160
#else
161
#define BC_OP_U16(bcPtr) (((*((uint8_t*)(bcPtr)))<<8) + (*(((uint8_t*)(bcPtr))+1)))
162
#endif
163
#else
164
#define BC_OP_U16(bcPtr) (*((uint16_t*)(bcPtr)))
165
#endif
166
167
168
TR::OptionSet *findOptionSet(J9Method *method, bool isAOT)
169
{
170
TR::OptionSet *optionSet = NULL;
171
J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
172
J9UTF8 *className;
173
J9UTF8 *name;
174
J9UTF8 *signature;
175
getClassNameSignatureFromMethod(method, className, name, signature);
176
char *methodSignature;
177
char arr[1024];
178
int32_t len = J9UTF8_LENGTH(className) + J9UTF8_LENGTH(name) + J9UTF8_LENGTH(signature) + 3;
179
if (len < 1024)
180
methodSignature = arr;
181
else
182
methodSignature = (char *) TR_Memory::jitPersistentAlloc(len);
183
184
if (methodSignature)
185
{
186
sprintf(methodSignature, "%.*s.%.*s%.*s", J9UTF8_LENGTH(className), utf8Data(className), J9UTF8_LENGTH(name), utf8Data(name), J9UTF8_LENGTH(signature), utf8Data(signature));
187
188
TR_FilterBST * filter = 0;
189
if (TR::Options::getDebug() && TR::Options::getDebug()->getCompilationFilters())
190
TR::Options::getDebug()->methodSigCanBeCompiled(methodSignature, filter, TR::Method::J9);
191
192
int32_t index = filter ? filter->getOptionSet() : 0;
193
int32_t lineNum = filter ? filter->getLineNumber() : 0;
194
195
bool hasBackwardBranches = (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? true : false);
196
197
optionSet = TR::Options::findOptionSet(index, lineNum, methodSignature, TR::Options::getInitialHotnessLevel(hasBackwardBranches), isAOT);
198
if (len >= 1024)
199
TR_Memory::jitPersistentFree(methodSignature);
200
}
201
202
return optionSet;
203
}
204
205
static void reportHook(J9VMThread *curThread, char *name, char *format=NULL, ...)
206
{
207
J9JITConfig * jitConfig = curThread->javaVM->jitConfig;
208
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
209
if ( TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks)
210
|| TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHookDetails))
211
{
212
TR_VerboseLog::CriticalSection vlogLock;
213
TR_VerboseLog::write(TR_Vlog_HK,"vmThread=%p hook %s ", curThread, name);
214
if (format)
215
{
216
va_list args;
217
va_start(args, format);
218
j9jit_vprintf(jitConfig, format, args);
219
va_end(args);
220
}
221
TR_VerboseLog::writeLine("");
222
}
223
}
224
225
static void reportHookFinished(J9VMThread *curThread, char *name, char *format=NULL, ...)
226
{
227
J9JITConfig * jitConfig = curThread->javaVM->jitConfig;
228
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
229
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHookDetails))
230
{
231
TR_VerboseLog::CriticalSection vlogLock;
232
TR_VerboseLog::writeLine(TR_Vlog_HD,"vmThread=%p hook %s finished ", curThread, name);
233
if (format)
234
{
235
va_list args;
236
va_start(args, format);
237
j9jit_vprintf(jitConfig, format, args);
238
va_end(args);
239
}
240
}
241
}
242
243
static void reportHookDetail(J9VMThread *curThread, char *name, char *format, ...)
244
{
245
J9JITConfig * jitConfig = curThread->javaVM->jitConfig;
246
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
247
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHookDetails))
248
{
249
TR_VerboseLog::CriticalSection vlogLock;
250
TR_VerboseLog::writeLine(TR_Vlog_HD,"vmThread=%p hook %s detail ", curThread, name);
251
va_list args;
252
va_start(args, format);
253
j9jit_vprintf(jitConfig, format, args);
254
va_end(args);
255
}
256
}
257
258
extern "C" {
259
260
extern void freeJITConfig(J9JITConfig *);
261
extern void stopSamplingThread(J9JITConfig *);
262
extern void getOutOfIdleStates(TR::CompilationInfo::TR_SamplerStates expectedState, TR::CompilationInfo *compInfo, const char* reason);
263
extern void getOutOfIdleStatesUnlocked(TR::CompilationInfo::TR_SamplerStates expectedState, TR::CompilationInfo *compInfo, const char* reason);
264
265
266
//***************************************************************************************
267
// Hooked by the JIT
268
//***************************************************************************************
269
270
int32_t encodeCount(int32_t count)
271
{
272
return (count == -1) ? 0 : (count << 1) + 1;
273
}
274
275
int32_t getCount(J9ROMMethod *romMethod, TR::Options *optionsJIT, TR::Options *optionsAOT)
276
{
277
int32_t count;
278
if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))
279
{
280
count = std::min(optionsJIT->getInitialBCount(), optionsAOT->getInitialBCount());
281
}
282
else
283
{
284
count = std::min(optionsJIT->getInitialCount(), optionsAOT->getInitialCount());
285
if (TR::Options::_smallMethodBytecodeSizeThreshold > 0)
286
{
287
uint32_t methodSize = TR::CompilationInfo::getMethodBytecodeSize(romMethod);
288
if ((int32_t)methodSize <= TR::Options::_smallMethodBytecodeSizeThreshold)
289
{
290
count = count << 3;
291
}
292
}
293
}
294
return count;
295
}
296
297
298
bool sharedCacheContainsProfilingInfoForMethod(J9VMThread *vmThread, TR::CompilationInfo *compInfo, J9ROMMethod * romMethod)
299
{
300
J9SharedClassConfig * scConfig = compInfo->getJITConfig()->javaVM->sharedClassConfig;
301
302
if(!scConfig)
303
return false;
304
305
unsigned char storeBuffer[1000];
306
uint32_t bufferLength=1000;
307
J9SharedDataDescriptor descriptor;
308
descriptor.address = storeBuffer;
309
descriptor.length = bufferLength;
310
descriptor.type = J9SHR_ATTACHED_DATA_TYPE_JITPROFILE;
311
descriptor.flags = J9SHR_ATTACHED_DATA_NO_FLAGS;
312
313
IDATA dataIsCorrupt;
314
TR_IPBCDataStorageHeader *store = (TR_IPBCDataStorageHeader *)scConfig->findAttachedData(vmThread, romMethod, &descriptor, &dataIsCorrupt);
315
316
if (!store)
317
return false;
318
319
if (store != (TR_IPBCDataStorageHeader *)descriptor.address) // a stronger check, as found can be error value
320
return false;
321
322
return true;
323
}
324
325
326
/// This is a helper function used by jitHookInitializeSendTarget().
327
/// This function calculates for the hash value for methods using method names.
328
/// The hash value will be eventually added to variable `count` in `jitHookInitializeSendTarget()` under some conditions.
329
/// The formula for the hash value is:
330
///
331
/// hashValue[0] = HASH_INIT_VALUE;
332
/// hashValue[i+1] = hashValue[i] * HASH_BASE_VALUE + name[i];
333
/// hashValue[length(name)] will be used as the hash value
334
static uint32_t initializeSendTargetHelperFuncHashValueForSpreading(J9Method* method)
335
{
336
// extract class name, method name, and signature
337
J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
338
J9UTF8 *className;
339
J9UTF8 *name;
340
J9UTF8 *signature;
341
getClassNameSignatureFromMethod(method, className, name, signature);
342
char *classNameChar = utf8Data(className);
343
char *nameChar = utf8Data(name);
344
char *signatureChar = utf8Data(signature);
345
346
// set the base and initial value for the hash value
347
// const uint32_t HASH_BASE_VALUE = 33;
348
const uint32_t HASH_INIT_VALUE = 5381;
349
350
// get options
351
TR::Options * optionsJIT = TR::Options::getJITCmdLineOptions();
352
TR::Options * optionsAOT = TR::Options::getAOTCmdLineOptions();
353
354
// extract the CAP of the hash value
355
uint32_t hashValueCap;
356
if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))
357
hashValueCap = std::max(optionsJIT->getMaxSpreadCountLoopy(), optionsAOT->getMaxSpreadCountLoopy());
358
else
359
hashValueCap = std::max(optionsJIT->getMaxSpreadCountLoopless(), optionsAOT->getMaxSpreadCountLoopless());
360
361
// compute the hash value
362
uint32_t hashValue = HASH_INIT_VALUE;
363
for (uint32_t i = 0; i < J9UTF8_LENGTH(className); i++)
364
hashValue = (hashValue << 5) + hashValue + classNameChar[i];
365
for (uint32_t i = 0; i < J9UTF8_LENGTH(name); i++)
366
hashValue = (hashValue << 5) + hashValue + nameChar[i];
367
for (uint32_t i = 0; i < J9UTF8_LENGTH(signature); i++)
368
hashValue = (hashValue << 5) + hashValue + signatureChar[i];
369
hashValue = hashValue % hashValueCap;
370
371
return hashValue;
372
}
373
374
static bool highCodeCacheOccupancyThresholdReached = false;
375
376
static void jitHookInitializeSendTarget(J9HookInterface * * hook, UDATA eventNum, void * eventData, void * userData)
377
{
378
J9VMInitializeSendTargetEvent * event = (J9VMInitializeSendTargetEvent *)eventData;
379
380
J9VMThread * vmThread = event->currentThread;
381
J9JITConfig* jitConfig = vmThread->javaVM->jitConfig;
382
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
383
384
if ((jitConfig->runtimeFlags & J9JIT_DEFER_JIT) != 0)
385
return; // No need to set counts in this mode
386
387
TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, vmThread);
388
389
J9Method * method = event->method;
390
J9ROMMethod * romMethod = fe->getROMMethodFromRAMMethod(method);
391
392
// Allow native and abstract methods to be initialized by the interpreter
393
if (romMethod->modifiers & (J9AccAbstract | J9AccNative))
394
{
395
TR::CompilationInfo::setInitialInvocationCountUnsynchronized(method,0);
396
return;
397
}
398
399
TR::Options * optionsJIT = TR::Options::getJITCmdLineOptions();
400
TR::Options * optionsAOT = TR::Options::getAOTCmdLineOptions();
401
402
method->methodRunAddress = jitGetCountingSendTarget(vmThread, method);
403
404
bool countInOptionSet = false;
405
406
if (TR::Options::getJITCmdLineOptions()->anOptionSetContainsACountValue())
407
{
408
TR::OptionSet * optionSet = findOptionSet(method, false);
409
if (optionSet)
410
{
411
optionsJIT = optionSet->getOptions();
412
countInOptionSet = true;
413
}
414
}
415
416
if (TR::Options::getAOTCmdLineOptions()->anOptionSetContainsACountValue())
417
{
418
TR::OptionSet * optionSet = findOptionSet(method, true);
419
if (optionSet)
420
{
421
optionsAOT = optionSet->getOptions();
422
countInOptionSet = true;
423
}
424
}
425
426
int32_t count = -1; // means we didn't set the value yet
427
428
{
429
J9ROMClass *declaringClazz = J9_CLASS_FROM_METHOD(method)->romClass;
430
J9UTF8 * className = J9ROMCLASS_CLASSNAME(declaringClazz);
431
J9UTF8 * name = J9ROMMETHOD_NAME(romMethod);
432
if (J9UTF8_LENGTH(className) == 36
433
&& J9UTF8_LENGTH(name) == 21
434
&& 0==memcmp(utf8Data(className), "com/ibm/rmi/io/FastPathForCollocated", 36)
435
&& 0==memcmp(utf8Data(J9ROMMETHOD_NAME(romMethod)), "isVMDeepCopySupported", 21)
436
)
437
{
438
count = 0;
439
}
440
else if (J9UTF8_LENGTH(className) == 39
441
&& J9UTF8_LENGTH(name) == 9
442
&& 0 == memcmp(utf8Data(className), "java/util/concurrent/ThreadPoolExecutor", 39)
443
&& 0 == memcmp(utf8Data(J9ROMMETHOD_NAME(romMethod)), "runWorker", 9)
444
)
445
{
446
count = 0;
447
}
448
else if (highCodeCacheOccupancyThresholdReached && !countInOptionSet && !TR::Options::getCountsAreProvidedByUser())
449
{
450
count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ?
451
TR::Options::getHighCodeCacheOccupancyBCount() :
452
TR::Options::getHighCodeCacheOccupancyCount();
453
}
454
else if (TR::Options::sharedClassCache())
455
{
456
// The default FE may not have TR_J9SharedCache object because the FE may have
457
// been created before options were processed.
458
TR_J9VMBase *fej9 = TR_J9VMBase::get(jitConfig, vmThread, TR_J9VMBase::AOT_VM);
459
TR_J9SharedCache *sc = fej9 ? fej9->sharedCache() : NULL;
460
#if defined(J9VM_INTERP_AOT_COMPILE_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))
461
if (sc && sc->isROMClassInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass))
462
{
463
PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);
464
I_64 sharedQueryTime = 0;
465
if (optionsAOT->getOption(TR_EnableSharedCacheTiming))
466
sharedQueryTime = j9time_hires_clock(); // may not be good for SMP
467
468
if (jitConfig->javaVM->sharedClassConfig->existsCachedCodeForROMMethod(vmThread, romMethod))
469
{
470
int32_t scount = optionsAOT->getInitialSCount();
471
uint16_t newScount = 0;
472
if (sc && sc->isHint(method, TR_HintFailedValidation, &newScount))
473
{
474
if ((scount == TR_QUICKSTART_INITIAL_SCOUNT) || (scount == TR_INITIAL_SCOUNT))
475
{ // If scount is not user specified (coarse way due to info being lost from options parsing)
476
// TODO: Is casting the best thing to do here?
477
scount= std::min(getCount(romMethod, optionsJIT, optionsAOT), static_cast<int32_t>(newScount) ); // Find what would've been normal count for this method and
478
// make sure new scount isn't larger than that
479
if (optionsAOT->getVerboseOption(TR_VerboseSCHints) || optionsJIT->getVerboseOption(TR_VerboseSCHints))
480
TR_VerboseLog::writeLineLocked(TR_Vlog_SCHINTS,"Found hint in sc, increase scount to: %d, wanted scount: %d", scount, newScount);
481
}
482
}
483
count = scount;
484
compInfo->incrementNumMethodsFoundInSharedCache();
485
}
486
// AOT Body not in SCC, so scount was not set
487
else if (!TR::Options::getCountsAreProvidedByUser() && !countInOptionSet)
488
{
489
bool useLowerCountsForAOTCold = false;
490
if (TR::Options::getCmdLineOptions()->getOption(TR_LowerCountsForAotCold) && compInfo->isWarmSCC() == TR_no)
491
{
492
// Because C-interpreter is slower we need to rely more on jitted code
493
// This means compiling more, but we have to be careful.
494
// Let's use some smaller than normal counts in the cold run (to avoid
495
// extra compilations in the warm runs), but only if
496
//
497
// 1) The Default SCC isn't used - because we don't want to increase footprint
498
//
499
// OR
500
//
501
// 1) Quickstart - because we don't risk losing iprofiling info
502
// 2) GracePeriod - because we want to limit the number of 'extra'
503
// compilations and short apps are affected more
504
// 3) Bootstrap - same as above, plus if these methods get into the
505
// SCC I would rather have non-app specific methods
506
//
507
// The danger is that very small applications that don't even get to AOT 200 methods
508
// may think that the runs are always cold
509
510
511
// J9SHR_RUNTIMEFLAG_ENABLE_CACHE_NON_BOOT_CLASSES is a good proxy for whether the
512
// Default SCC is set because, when -Xshareclasses option is used, by default non
513
// bootstrap loaded classes are put into the SCC. However, if the -Xshareclasses
514
// option isn't used, then the Default SCC only contains bootstrap loaded classes.
515
if (J9_SHARED_CACHE_DEFAULT_BOOT_SHARING(jitConfig->javaVM) &&
516
J9_ARE_ALL_BITS_SET(jitConfig->javaVM->sharedClassConfig->runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_CACHE_NON_BOOT_CLASSES))
517
{
518
useLowerCountsForAOTCold = true;
519
}
520
else if (compInfo->getPersistentInfo()->getElapsedTime() <= (uint64_t)compInfo->getPersistentInfo()->getClassLoadingPhaseGracePeriod() &&
521
TR::Options::isQuickstartDetected() &&
522
fe->isClassLibraryMethod((TR_OpaqueMethodBlock *)method))
523
{
524
useLowerCountsForAOTCold = true;
525
}
526
}
527
528
if (useLowerCountsForAOTCold)
529
{
530
// TODO: modify the function that reads a specified count such that
531
// if the user specifies a count or bcount on the command line that is obeyed
532
// and we don't try the following line
533
count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ?
534
std::min(optionsJIT->getInitialColdRunBCount(), optionsAOT->getInitialColdRunBCount()) :
535
std::min(optionsJIT->getInitialColdRunCount(), optionsAOT->getInitialColdRunCount());
536
}
537
// Increase counts for methods from non-bootstrap classes to improve throughput
538
else if (TR::Options::getCmdLineOptions()->getOption(TR_IncreaseCountsForNonBootstrapMethods))
539
{
540
if (!fe->isClassLibraryMethod((TR_OpaqueMethodBlock *)method))
541
count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR_DEFAULT_INITIAL_BCOUNT : TR_DEFAULT_INITIAL_COUNT;
542
}
543
// We may lower or increase the counts based on TR_HintMethodCompiledDuringStartup
544
if (count == -1 && // Not yet changed
545
jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP &&
546
(TR_HintMethodCompiledDuringStartup & TR::Options::getAOTCmdLineOptions()->getEnableSCHintFlags()) && sc)
547
{
548
bool wasCompiledDuringStartup = sc->isHint(method, TR_HintMethodCompiledDuringStartup);
549
if (wasCompiledDuringStartup)
550
{
551
// Lower the counts for any method that doesn't have an AOT body,
552
// but we know it has been compiled in previous runs.
553
if (TR::Options::getCmdLineOptions()->getOption(TR_ReduceCountsForMethodsCompiledDuringStartup))
554
count = TR::Options::getCountForMethodsCompiledDuringStartup();
555
}
556
else // method was not compiled during startup
557
{
558
if (TR::Options::getCmdLineOptions()->getOption(TR_IncreaseCountsForMethodsCompiledOutsideStartup) &&
559
TR::Options::startupTimeMatters() == TR_maybe) // For TR_no the counts are already high, for TR_yes we cannot get in here
560
count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR_DEFAULT_INITIAL_BCOUNT : TR_DEFAULT_INITIAL_COUNT;
561
}
562
}
563
}
564
if (optionsAOT->getOption(TR_EnableSharedCacheTiming))
565
{
566
sharedQueryTime = j9time_hires_delta(sharedQueryTime, j9time_hires_clock(), J9PORT_TIME_DELTA_IN_MICROSECONDS);
567
compInfo->setAotQueryTime(compInfo->getAotQueryTime() + (UDATA)sharedQueryTime);
568
}
569
}
570
else // ROM class not in shared class cache
571
{
572
#if !defined(J9ZOS390) // Do not change the counts on zos at the moment since the
573
// shared cache capacity is higher on this platform and by
574
// increasing counts we could end up significantly impacting startup
575
if (TR::Options::getCmdLineOptions()->getOption(TR_UseHigherCountsForNonSCCMethods))
576
count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR_DEFAULT_INITIAL_BCOUNT : TR_DEFAULT_INITIAL_COUNT;
577
#endif // !J9ZOS390
578
}
579
#endif // defined(J9VM_INTERP_AOT_COMPILE_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))
580
} // if (TR::Options::sharedClassCache())
581
if (count == -1) // count didn't change yet
582
{
583
if (!TR::Options::getCountsAreProvidedByUser() &&
584
fe->isClassLibraryMethod((TR_OpaqueMethodBlock *)method))
585
count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR::Options::getCountForLoopyBootstrapMethods() : TR::Options::getCountForLooplessBootstrapMethods();
586
if (count == -1)
587
count = getCount(romMethod, optionsJIT, optionsAOT);
588
589
// If add-spreading-invocation mode is enabled, add a hash value (hashed from method name) to count
590
if (optionsAOT->getOption(TR_EnableCompilationSpreading) || optionsJIT->getOption(TR_EnableCompilationSpreading))
591
{
592
count += initializeSendTargetHelperFuncHashValueForSpreading(method);
593
}
594
else if (TR::Options::getCmdLineOptions()->getOption(TR_EnableEarlyCompilationDuringIdleCpu))
595
{
596
// Set only a fraction of a count to accelerate compilations
597
if (count > 20)
598
count = count * TR::Options::_countPercentageForEarlyCompilation / 100;
599
// TODO: disable this mechanism after an hour or so to conserve idle time
600
}
601
}
602
}
603
604
// Option to display chosen counts to track possible bugs
605
if (optionsJIT->getVerboseOption(TR_VerboseCounts))
606
{
607
char buffer[500];
608
fe->printTruncatedSignature(buffer, 500, (TR_OpaqueMethodBlock *) method);
609
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Setting count=%d for %s", count, buffer);
610
}
611
612
TR::CompilationInfo::setInitialInvocationCountUnsynchronized(method,count);
613
614
if (TR::Options::getJITCmdLineOptions()->getOption(TR_DumpInitialMethodNamesAndCounts) || TR::Options::getAOTCmdLineOptions()->getOption(TR_DumpInitialMethodNamesAndCounts))
615
{
616
bool containsInfo = sharedCacheContainsProfilingInfoForMethod(vmThread, compInfo, romMethod);
617
char buf[3072];
618
J9UTF8 * className = J9ROMCLASS_CLASSNAME(J9_CLASS_FROM_METHOD(method)->romClass);
619
J9UTF8 * name = J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(method));
620
J9UTF8 * signature = J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(method));
621
int32_t sigLen = sprintf(buf, "%.*s.%.*s%.*s", J9UTF8_LENGTH(className), utf8Data(className), J9UTF8_LENGTH(name), utf8Data(name), J9UTF8_LENGTH(signature), utf8Data(signature));
622
printf("Initial: Signature %s Count %d isLoopy %d isAOT %" OMR_PRIuPTR " is in SCC %d SCCContainsProfilingInfo %d \n",buf,TR::CompilationInfo::getInvocationCount(method),J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod),
623
TR::Options::sharedClassCache() ? jitConfig->javaVM->sharedClassConfig->existsCachedCodeForROMMethod(vmThread, romMethod) : 0,
624
TR::Options::sharedClassCache() ? TR_J9VMBase::get(jitConfig, vmThread, TR_J9VMBase::AOT_VM)->sharedCache()->isROMClassInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass) : 0,containsInfo) ; fflush(stdout);
625
}
626
}
627
628
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
629
630
static int32_t interpreterProfilingState = IPROFILING_STATE_OFF;
631
static int32_t interpreterProfilingRecordsCount = 0; // reset when state changes to IPROFILING_STATE_GOING_OFF
632
static int32_t interpreterProfilingJITSamples = 0;
633
static int32_t interpreterProfilingINTSamples = 0;
634
static int32_t interpreterProfilingMonitoringWindow = 0;
635
static bool interpreterProfilingWasOnAtStartup = false;
636
637
/**
638
* J9 VM hook, called when the profiling bytecode buffer is full.
639
*/
640
static void jitHookBytecodeProfiling(J9HookInterface * * hook, UDATA eventNum, void * eventData, void * userData);
641
642
static void turnOnInterpreterProfiling(J9JavaVM* javaVM, TR::CompilationInfo * compInfo)
643
{
644
if (interpreterProfilingState == IPROFILING_STATE_OFF)
645
{
646
TR_J9VMBase * vmj9 = (TR_J9VMBase *)(TR_J9VMBase::get(javaVM->jitConfig, 0));
647
TR_IProfiler *iProfiler = vmj9->getIProfiler();
648
649
if (iProfiler->getProfilerMemoryFootprint() >= TR::Options::_iProfilerMemoryConsumptionLimit)
650
return;
651
652
J9HookInterface ** hook = javaVM->internalVMFunctions->getVMHookInterface(javaVM);
653
654
interpreterProfilingRecordsCount = 0;
655
interpreterProfilingState = IPROFILING_STATE_ON;
656
interpreterProfilingJITSamples = 0;
657
658
PORT_ACCESS_FROM_JAVAVM(javaVM);
659
660
661
if ((*hook)->J9HookRegisterWithCallSite(hook, J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL, jitHookBytecodeProfiling, OMR_GET_CALLSITE(), NULL))
662
{
663
j9tty_printf(PORTLIB, "Error: Unable to install J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL listener\n");
664
return;
665
}
666
else
667
{
668
if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))
669
{
670
TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler reactivated...", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime());
671
}
672
}
673
}
674
}
675
#endif
676
677
#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
678
static TR_YesNoMaybe shouldInitiateDLT(J9DLTInformationBlock *dltInfo, int32_t idx, bool *bcRepeats, int32_t *hitCnt)
679
{
680
static int32_t triggerCount = -1;
681
682
if (triggerCount == -1)
683
{
684
static char *envTrigger = feGetEnv("TR_DLTcount");
685
if (envTrigger == NULL)
686
{
687
triggerCount = 3;
688
}
689
else
690
triggerCount = atoi(envTrigger);
691
}
692
693
*bcRepeats = false;
694
*hitCnt = -1; // -1 means unknown
695
696
if (triggerCount <= 1)
697
return TR_yes;
698
699
J9Method *currentMethod = dltInfo->methods[idx];
700
int32_t hitCount=0, loopCnt=0, bcIdx = dltInfo->bcIndex[idx];
701
702
idx = (idx==0)?(J9DLT_HISTORY_SIZE-1):(idx-1);
703
704
while (loopCnt < J9DLT_HISTORY_SIZE-1)
705
{
706
loopCnt++;
707
if (dltInfo->methods[idx] == currentMethod)
708
{
709
if (dltInfo->bcIndex[idx] >= bcIdx)
710
*bcRepeats = true;
711
hitCount++;
712
}
713
idx = (idx==0)?(J9DLT_HISTORY_SIZE-1):(idx-1);
714
if (loopCnt==triggerCount-1 && hitCount==triggerCount-1)
715
return TR_maybe;
716
}
717
718
*hitCnt = hitCount;
719
if (hitCount>=triggerCount)
720
return TR_maybe;
721
722
void *extra = TR::CompilationInfo::getPCIfCompiled(currentMethod);
723
if(extra && !TR::Options::getCmdLineOptions()->getOption(TR_DisableFastDLTOnLongRunningInterpreter))
724
{
725
TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(extra);
726
if (bodyInfo && bodyInfo->isLongRunningInterpreted())
727
return TR_yes;
728
}
729
730
return TR_no;
731
}
732
733
void *jitLookupDLT(J9VMThread *currentThread, J9Method *method, UDATA bcIndex)
734
{
735
J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;
736
737
if (!jitConfig)
738
return 0;
739
740
TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);
741
void *dltEntry = compInfo->searchForDLTRecord(method, bcIndex);
742
743
if (!dltEntry)
744
return 0;
745
746
J9DLTInformationBlock *dltBlock = &(currentThread->dltBlock);
747
dltBlock->dltSP = (uintptr_t)CONVERT_TO_RELATIVE_STACK_OFFSET(currentThread, currentThread->sp);
748
dltBlock->dltEntry = dltEntry;
749
return (void *)1;
750
}
751
752
static UDATA dltTestIterator(J9VMThread * currentThread, J9StackWalkState * walkState)
753
{
754
switch(walkState->framesWalked)
755
{
756
case 1 :
757
if (((UDATA) walkState->pc <= J9SF_MAX_SPECIAL_FRAME_TYPE) || (walkState->pc == walkState->walkThread->javaVM->callInReturnPC))
758
return J9_STACKWALK_KEEP_ITERATING;
759
if (walkState->jitInfo!=NULL)
760
return J9_STACKWALK_STOP_ITERATING;
761
walkState->userData1 = (void *)1;
762
return J9_STACKWALK_STOP_ITERATING;
763
break;
764
765
case 2 :
766
if (((UDATA) walkState->pc <= J9SF_MAX_SPECIAL_FRAME_TYPE) || (walkState->pc == walkState->walkThread->javaVM->callInReturnPC))
767
return J9_STACKWALK_STOP_ITERATING;
768
769
if (walkState->jitInfo!=NULL)
770
return J9_STACKWALK_STOP_ITERATING;
771
772
// We can stop at this point: candidate for sync transfer
773
walkState->userData1 = (void *)2;
774
return J9_STACKWALK_STOP_ITERATING;
775
break;
776
777
case 3 : // unused currently
778
if (walkState->jitInfo!=NULL || ((UDATA) walkState->pc <= J9SF_MAX_SPECIAL_FRAME_TYPE) ||
779
(walkState->pc == walkState->walkThread->javaVM->callInReturnPC) || (*walkState->bp & J9SF_A0_INVISIBLE_TAG))
780
return J9_STACKWALK_STOP_ITERATING;
781
break;
782
}
783
784
return J9_STACKWALK_KEEP_ITERATING;
785
}
786
787
static void emptyJitGCMapCheck(J9VMThread * currentThread, J9StackWalkState * walkState, j9object_t * objectSlot, const void * stackLocation)
788
{
789
return;
790
}
791
792
793
static void jitGCMapCheck(J9VMThread* vmThread, IDATA handlerKey, void* userData)
794
{
795
796
J9StackWalkState walkState;
797
walkState.flags = J9_STACKWALK_ITERATE_O_SLOTS | J9_STACKWALK_ITERATE_HIDDEN_JIT_FRAMES | J9_STACKWALK_CHECK_I_SLOTS_FOR_OBJECTS;
798
walkState.objectSlotWalkFunction = emptyJitGCMapCheck;
799
walkState.maxFrames = 2;
800
walkState.walkThread = vmThread;
801
walkState.userData1=0;
802
803
static char *verbose = feGetEnv("TR_GCMapCheckVerbose");
804
if (verbose)
805
walkState.userData1 = (void*)((uintptr_t) walkState.userData1 | 1);
806
807
static char *local = feGetEnv("TR_GCMapCheckLocalScavenge");
808
if (local)
809
walkState.userData1 = (void*)((uintptr_t) walkState.userData1 | 2);
810
811
static char *global = feGetEnv("TR_GCMapCheckGlobalScavenge");
812
if (global)
813
walkState.userData1 = (void*)((uintptr_t) walkState.userData1 | 4);
814
815
vmThread->javaVM->walkStackFrames(vmThread, &walkState);
816
817
818
return;
819
}
820
821
void DLTLogic(J9VMThread* vmThread, TR::CompilationInfo *compInfo)
822
{
823
#define SIG_SZ 150
824
char sig[SIG_SZ];
825
if (!TR::Options::canJITCompile() ||
826
TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug) ||
827
TR::Options::getCmdLineOptions()->getOption(TR_DisableDynamicLoopTransfer) )
828
return;
829
if (TR::Options::_compilationDelayTime > 0 && // feature enabled
830
TR::Options::_compilationDelayTime > compInfo->getPersistentInfo()->getElapsedTime())
831
return;
832
833
J9StackWalkState walkState;
834
walkState.maxFrames = 3;
835
walkState.userData1 = 0;
836
walkState.walkThread = vmThread;
837
walkState.frameWalkFunction = dltTestIterator;
838
walkState.flags = J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_COUNT_SPECIFIED | J9_STACKWALK_SKIP_INLINES;
839
vmThread->javaVM->walkStackFrames(vmThread, &walkState);
840
uint8_t * startPC = 0;
841
if (walkState.userData1 == 0)
842
startPC = (uint8_t *)-1;
843
844
J9DLTInformationBlock *dltBlock = &(vmThread->dltBlock);
845
int32_t idx = dltBlock->cursor + 1;
846
J9ROMMethod *romMethod = NULL;
847
bool bcRepeats;
848
void *extra = NULL;
849
850
if (startPC!=(uint8_t *)-1 && walkState.method!=0)
851
romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState.method);
852
853
idx = (idx==J9DLT_HISTORY_SIZE) ? 0 : idx;
854
dltBlock->cursor = idx;
855
if (startPC ||
856
walkState.method==0 ||
857
(romMethod->modifiers & J9AccNative) ||
858
((intptr_t)(walkState.method->constantPool) & J9_STARTPC_JNI_NATIVE) ||
859
!J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ||
860
TR::CompilationInfo::getJ9MethodVMExtra(walkState.method)==J9_JIT_NEVER_TRANSLATE ||
861
(J9CLASS_FLAGS(J9_CLASS_FROM_METHOD(walkState.method)) & J9AccClassHotSwappedOut) ||
862
walkState.bytecodePCOffset<=0) // FIXME: Deal with loop back on entry later
863
{
864
dltBlock->methods[idx] = 0;
865
return;
866
}
867
else
868
{
869
extra = TR::CompilationInfo::getPCIfCompiled(walkState.method);
870
if (extra)
871
{
872
TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(extra);
873
if (bodyInfo && bodyInfo->getMethodInfo()->hasFailedDLTCompRetrials())
874
{
875
dltBlock->methods[idx] = 0;
876
return;
877
}
878
}
879
}
880
881
// Check whether we need a DLT compilation
882
bool doPerformDLT = false;
883
dltBlock->methods[idx] = walkState.method;
884
dltBlock->bcIndex[idx] = walkState.bytecodePCOffset;
885
TR_J9ByteCode bc = TR_J9ByteCodeIterator::convertOpCodeToByteCodeEnum(J9_BYTECODE_START_FROM_ROM_METHOD(romMethod)[walkState.bytecodePCOffset]);
886
if ((walkState.unwindSP - walkState.walkSP) == 0 && bc != J9BCinvokevirtual &&
887
bc != J9BCinvokespecial && bc != J9BCinvokestatic && bc != J9BCinvokeinterface &&
888
bc != J9BCinvokedynamic && bc != J9BCinvokehandle && bc != J9BCinvokehandlegeneric &&
889
bc != J9BCinvokespecialsplit && bc != J9BCinvokestaticsplit)
890
{
891
int32_t numHitsInDLTBuffer = -1;
892
TR_YesNoMaybe answer = shouldInitiateDLT(dltBlock, idx, &bcRepeats, &numHitsInDLTBuffer);
893
if (answer != TR_no)
894
{
895
// Perform another test
896
if (compInfo->getDLT_HT())
897
{
898
// If numHitsInDLTBuffer was not computed by shouldInitiateDLT do it now
899
if (numHitsInDLTBuffer == -1)
900
{
901
// Search again for number of hits
902
int32_t i = 0;
903
for (numHitsInDLTBuffer = 0; i < J9DLT_HISTORY_SIZE; i++)
904
if (dltBlock->methods[i] == walkState.method)
905
numHitsInDLTBuffer++;
906
}
907
// Check the DLT_HT
908
doPerformDLT = compInfo->getDLT_HT()->shouldIssueDLTCompilation(walkState.method, numHitsInDLTBuffer);
909
}
910
else // DLT_HT is not allocated, so just issue the DLT request
911
{
912
doPerformDLT = true;
913
}
914
}
915
}
916
917
if (doPerformDLT)
918
{
919
int32_t bcIndex = walkState.bytecodePCOffset;
920
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
921
TR_J9VMBase * vm = TR_J9VMBase::get(jitConfig, vmThread);
922
923
static char *enableDebugDLT = feGetEnv("TR_DebugDLT");
924
bool dltMostOnce = false;
925
int32_t enableDLTidx = -1;
926
int32_t disableDLTidx = -1;
927
int32_t dltOptLevel = -1;
928
929
if (enableDebugDLT!=NULL)
930
{
931
TR::OptionSet *optionSet = findOptionSet(walkState.method, false);
932
TR::Options *options = optionSet ? optionSet->getOptions() : NULL;
933
934
enableDLTidx = options ? options->getEnableDLTBytecodeIndex() : -1;
935
disableDLTidx = options ? options->getDisableDLTBytecodeIndex() : -1;
936
937
if (enableDLTidx != -1)
938
{
939
J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(walkState.method);
940
bcIndex = enableDLTidx;
941
if (enableDLTidx >= (J9_BYTECODE_END_FROM_ROM_METHOD(romMethod)) - (J9_BYTECODE_START_FROM_ROM_METHOD(romMethod)))
942
return;
943
dltBlock->bcIndex[idx] = enableDLTidx;
944
}
945
if (disableDLTidx != -1 && disableDLTidx == bcIndex) return;
946
947
dltMostOnce = options ? options->getOption(TR_DLTMostOnce) :
948
TR::Options::getCmdLineOptions()->getOption(TR_DLTMostOnce);
949
dltOptLevel = options ? options->getDLTOptLevel() :
950
TR::Options::getCmdLineOptions()->getDLTOptLevel();
951
}
952
953
// This setup is for matching dltEntry to the right transfer point. It can be an issue only
954
// in rare situations where Java code is executed for asyncEvents, leading to recursive DLT.
955
dltBlock->dltSP = (uintptr_t)CONVERT_TO_RELATIVE_STACK_OFFSET(vmThread, vmThread->sp);
956
957
dltBlock->dltEntry = compInfo->searchForDLTRecord(dltBlock->methods[idx], bcIndex);
958
if (dltBlock->dltEntry != NULL)
959
return;
960
961
static char *TR_DLTmostOnce = feGetEnv("TR_DLTmostOnce");
962
if (TR_DLTmostOnce != NULL || dltMostOnce)
963
{
964
if (compInfo->searchForDLTRecord(dltBlock->methods[idx], -1))
965
return;
966
}
967
968
static char *TR_DLTforcedHot = feGetEnv("TR_DLTforcedHot");
969
static char *TR_DLTforcedCold = feGetEnv("TR_DLTforcedCold"); // Usage error: set both
970
TR_OptimizationPlan *plan = NULL;
971
TR_CompilationErrorCode eCode;
972
bool queued = false;
973
974
975
// TODO: add an event for the controller to decide what to do
976
TR_Hotness optLevel = warm;
977
// decide if we are going to compile this method to hot
978
if (dltOptLevel != -1)
979
{
980
optLevel = (TR_Hotness)dltOptLevel;
981
}
982
else if (TR_DLTforcedHot!=NULL)
983
{
984
optLevel = hot;
985
}
986
else if (TR_DLTforcedCold != NULL)
987
{
988
optLevel = cold;
989
}
990
else
991
{
992
bool systemClass = vm->isClassLibraryMethod((TR_OpaqueMethodBlock*)walkState.method);
993
if (systemClass)
994
{
995
optLevel = cold;
996
//return;
997
}
998
else // userClass
999
{
1000
// DLTs cannot be very important for large apps, so use cold compilations
1001
if (compInfo->getPersistentInfo()->getNumLoadedClasses() >= TR::Options::_bigAppThreshold)
1002
{
1003
optLevel = cold;
1004
}
1005
else
1006
{
1007
bool classLoadPhase = compInfo->getPersistentInfo()->isClassLoadingPhase();
1008
if (bcRepeats)
1009
{
1010
if (!classLoadPhase)
1011
optLevel = hot;
1012
}
1013
else
1014
{
1015
if (classLoadPhase)
1016
optLevel = cold;
1017
}
1018
}
1019
}
1020
}
1021
1022
plan = TR_OptimizationPlan::alloc(optLevel);
1023
if (!plan)
1024
return;
1025
1026
if (vm->isLogSamplingSet())
1027
{
1028
vm->printTruncatedSignature(sig, SIG_SZ, (TR_OpaqueMethodBlock*)walkState.method);
1029
TR_VerboseLog::writeLineLocked(TR_Vlog_DLT,"Will try to queue DLT compilation for %s bcIndex=%d", sig, bcIndex);
1030
}
1031
1032
// Issue a DLT compilation request (scope for compilation request)
1033
{
1034
J9::MethodInProgressDetails details(walkState.method, dltBlock->bcIndex[dltBlock->cursor]);
1035
dltBlock->dltEntry = compInfo->compileMethod(vmThread, details, 0, TR_maybe, &eCode, &queued, plan);
1036
}
1037
1038
if (walkState.userData1==(void *)2 && dltBlock->dltEntry) // Cannot transfer synchronously
1039
dltBlock->dltEntry = NULL;
1040
1041
for (idx=0; idx<J9DLT_HISTORY_SIZE; idx++)
1042
if (dltBlock->methods[idx] == walkState.method)
1043
dltBlock->methods[idx] = 0;
1044
1045
if (!queued)
1046
{
1047
// plan must exist because we checked above
1048
TR_OptimizationPlan::freeOptimizationPlan(plan);
1049
}
1050
else // DLT request has been queued
1051
{
1052
// Create a request for normal JIT compilation as well
1053
J9Method *j9method = walkState.method;
1054
if (!TR::CompilationInfo::isCompiled(j9method))
1055
{
1056
// No need to check for j9method->extra != (void*)J9_JIT_QUEUED_FOR_COMPILATION
1057
// because we check the count value below
1058
int32_t count = TR::CompilationInfo::getInvocationCount(j9method);
1059
if (count > 0)
1060
{
1061
// Change the count to 0 as if this interpreted method got a sample
1062
if (TR::CompilationInfo::setInvocationCount(j9method, count, 0))
1063
{
1064
if (vm->isLogSamplingSet())
1065
{
1066
TR_VerboseLog::writeLineLocked(TR_Vlog_DLT,"side-effect: reducing count to 0 for %s", sig);
1067
}
1068
if (vm->isAsyncCompilation())
1069
{
1070
TR_MethodEvent event;
1071
event._eventType = TR_MethodEvent::JitCompilationInducedByDLT;
1072
event._j9method = j9method;
1073
event._oldStartPC = 0;
1074
event._vmThread = vmThread;
1075
event._classNeedingThunk = 0;
1076
bool newPlanCreated;
1077
TR_OptimizationPlan *jitplan = TR::CompilationController::getCompilationStrategy()->processEvent(&event, &newPlanCreated);
1078
if (jitplan)
1079
{
1080
bool queued1 = false;
1081
vm->startAsyncCompile((TR_OpaqueMethodBlock *) j9method, 0, &queued1, jitplan);
1082
if (!queued1 && newPlanCreated)
1083
TR_OptimizationPlan::freeOptimizationPlan(jitplan);
1084
}
1085
}
1086
}
1087
}
1088
}
1089
}
1090
}
1091
} // DLTLogic
1092
1093
#endif
1094
1095
/**
1096
* Stack frame iterator. Causes a tracepoint to be triggered for each frame.
1097
*
1098
* Returns:
1099
* J9_STACKWALK_KEEP_ITERATING
1100
* J9_STACKWALK_STOP_ITERATING
1101
*/
1102
static UDATA
1103
walkStackIterator(J9VMThread *currentThread, J9StackWalkState *walkState)
1104
{
1105
if(walkState->userData1 == 0)
1106
{
1107
Trc_JIT_MethodSampleStart(currentThread, walkState->method, walkState->pc, walkState->jitInfo);
1108
walkState->userData1 = (void *) 1;
1109
}
1110
else
1111
{
1112
Trc_JIT_MethodSampleContinue(currentThread, walkState->method, walkState->pc, walkState->jitInfo);
1113
}
1114
return J9_STACKWALK_KEEP_ITERATING;
1115
}
1116
1117
static void walkStackForSampling(J9VMThread *vmThread)
1118
{
1119
J9StackWalkState walkState;
1120
1121
walkState.userData1 = 0;
1122
walkState.walkThread = vmThread;
1123
walkState.skipCount = 0;
1124
walkState.maxFrames = 32; // TODO arbitrary, will become a settable property
1125
walkState.flags = J9_STACKWALK_VISIBLE_ONLY |
1126
J9_STACKWALK_INCLUDE_NATIVES |
1127
J9_STACKWALK_ITERATE_FRAMES;
1128
walkState.frameWalkFunction = walkStackIterator;
1129
1130
if (vmThread->javaVM->walkStackFrames(vmThread, &walkState) != J9_STACKWALK_RC_NONE)
1131
{
1132
Trc_JIT_MethodSampleFail(vmThread, 0);
1133
}
1134
}
1135
1136
/**
1137
* Stack frame iterator (reduced version). Causes a tracepoint to be triggered for each frame.
1138
* Only sends the method name.
1139
* Every time tries to walk two frames (sample two methods) and send them out together.
1140
*
1141
* Returns:
1142
* J9_STACKWALK_KEEP_ITERATING
1143
* J9_STACKWALK_STOP_ITERATING
1144
*/
1145
static UDATA
1146
walkStackIteratorReduced(J9VMThread *currentThread, J9StackWalkState *walkState)
1147
{
1148
if(walkState->userData1 == 0)
1149
{
1150
Trc_JIT_MethodSampleStart1(currentThread, walkState->method);
1151
walkState->userData1 = (void *) 1;
1152
}
1153
else if(walkState->userData2 == 0)
1154
{
1155
// userData2 is used as the cache. If userData2 is NULL, the current method will be stored in userData2 temporarily
1156
walkState->userData2 = (void *) walkState->method;
1157
}
1158
else
1159
{
1160
// userData2 is used as the cache. If userData2 is nonempty, the previously stored method (in userData2)
1161
// and the current method will be sent out together, then userData2 will be cleared.
1162
Trc_JIT_MethodSampleContinue2(currentThread, (J9Method*) walkState->userData2, walkState->method);
1163
walkState->userData2 = (void *) 0;
1164
}
1165
return J9_STACKWALK_KEEP_ITERATING;
1166
}
1167
1168
static void walkStackForSamplingReduced(J9VMThread *vmThread)
1169
{
1170
J9StackWalkState walkState;
1171
1172
walkState.userData1 = 0;
1173
walkState.userData2 = 0;
1174
walkState.walkThread = vmThread;
1175
walkState.skipCount = 0;
1176
walkState.maxFrames = 32; // TODO arbitrary, will become a settable property
1177
walkState.flags = J9_STACKWALK_VISIBLE_ONLY |
1178
J9_STACKWALK_INCLUDE_NATIVES |
1179
J9_STACKWALK_ITERATE_FRAMES;
1180
walkState.frameWalkFunction = walkStackIteratorReduced;
1181
1182
if (vmThread->javaVM->walkStackFrames(vmThread, &walkState) != J9_STACKWALK_RC_NONE)
1183
{
1184
Trc_JIT_MethodSampleFail(vmThread, 0);
1185
}
1186
else if(walkState.userData2 != 0)
1187
{
1188
// If there is one last method left in userData2, send it out.
1189
Trc_JIT_MethodSampleContinue1(vmThread, (J9Method*) walkState.userData2);
1190
walkState.userData2 = (void *) 0;
1191
}
1192
}
1193
1194
inline static bool tryAndProcessBuffers(J9VMThread *vmThread, TR_J9VMBase *vm, TR_HWProfiler *hwProfiler)
1195
{
1196
bool canEnableRI = false;
1197
if (hwProfiler->getProcessBufferState() >= 0)
1198
{
1199
if (vm->_hwProfilerShouldNotProcessBuffers)
1200
{
1201
vm->_hwProfilerShouldNotProcessBuffers--;
1202
}
1203
else
1204
{
1205
vm->_hwProfilerShouldNotProcessBuffers = TR::Options::_hwProfilerRIBufferProcessingFrequency;
1206
canEnableRI = hwProfiler->processBuffers(vmThread, vm);
1207
}
1208
}
1209
return canEnableRI;
1210
}
1211
1212
static void processHWPBuffer(J9VMThread *vmThread, TR_J9VMBase *vm)
1213
{
1214
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
1215
if (!compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())
1216
return; // Nothing to do in a RI disabled environment
1217
1218
TR_HWProfiler *hwProfiler = compInfo->getHWProfiler();
1219
1220
if (hwProfiler->isExpired())
1221
{
1222
if (IS_THREAD_RI_INITIALIZED(vmThread))
1223
{
1224
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler))
1225
{
1226
TR_VerboseLog::writeLineLocked(TR_Vlog_HWPROFILER, "Thread %p will be de-initialized for RI because RI expiration time was reached", vmThread);
1227
}
1228
hwProfiler->deinitializeThread(vmThread);
1229
}
1230
}
1231
else if (hwProfiler->getProcessBufferState() >= 0 && // avoid overhead if RI is off
1232
hwProfiler->isHWProfilingAvailable(vmThread))
1233
{
1234
bool threadInitialized = false;
1235
// HW Available, but thread not initialized.
1236
if (!IS_THREAD_RI_INITIALIZED(vmThread))
1237
threadInitialized = hwProfiler->initializeThread(vmThread);
1238
else
1239
threadInitialized = true;
1240
1241
bool canUseStartUsingRI = (!TR::Options::getCmdLineOptions()->getOption(TR_DisableHardwareProfilerDuringStartup)
1242
|| vmThread->javaVM->phase == J9VM_PHASE_NOT_STARTUP);
1243
1244
// If RI is enabled, poll buffer to swap.
1245
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableHWProfilerDataCollection)
1246
&& threadInitialized
1247
&& canUseStartUsingRI)
1248
{
1249
if (IS_THREAD_RI_ENABLED(vmThread))
1250
{
1251
tryAndProcessBuffers(vmThread, vm, hwProfiler);
1252
}
1253
#ifdef J9VM_JIT_RUNTIME_INSTRUMENTATION
1254
else
1255
{
1256
PORT_ACCESS_FROM_VMC(vmThread);
1257
if (tryAndProcessBuffers(vmThread, vm, hwProfiler))
1258
{
1259
j9ri_enable(vmThread->riParameters);
1260
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler))
1261
TR_VerboseLog::writeLineLocked(TR_Vlog_HWPROFILER, "RI is enabled for vmThread 0x%p", vmThread);
1262
}
1263
}
1264
#endif
1265
}
1266
}
1267
}
1268
1269
static void jitMethodSampleInterrupt(J9VMThread* vmThread, IDATA handlerKey, void* userData)
1270
{
1271
J9StackWalkState walkState;
1272
1273
walkState.flags = J9_STACKWALK_SKIP_INLINES | J9_STACKWALK_VISIBLE_ONLY | J9_STACKWALK_INCLUDE_NATIVES | J9_STACKWALK_COUNT_SPECIFIED;
1274
walkState.skipCount = 0;
1275
walkState.maxFrames = 1;
1276
walkState.walkThread = vmThread;
1277
vmThread->javaVM->walkStackFrames(vmThread, &walkState);
1278
if (walkState.framesWalked == 0)
1279
return;
1280
1281
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1282
if (jitConfig == 0)
1283
return; // if a hook gets called after freeJitConfig then not much else we can do
1284
1285
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
1286
1287
TR_J9VMBase * vm = TR_J9VMBase::get(jitConfig, vmThread);
1288
1289
// Runtime Instrumentation
1290
processHWPBuffer(vmThread, vm);
1291
1292
if ((jitConfig->runtimeFlags & J9JIT_DEFER_JIT) == 0) // Reject any samples if we decided to postpone jitting
1293
{
1294
uint8_t * startPC = 0;
1295
int32_t codeSize = 0;
1296
TR_MethodMetaData * metaData = (TR_MethodMetaData *)walkState.jitInfo;
1297
if (metaData)
1298
{
1299
startPC = (uint8_t*)metaData->startPC;
1300
codeSize = compInfo->calculateCodeSize(metaData);
1301
}
1302
1303
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
1304
if (interpreterProfilingState != IPROFILING_STATE_OFF &&
1305
!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))
1306
{
1307
if (startPC)
1308
interpreterProfilingJITSamples ++;
1309
else
1310
interpreterProfilingINTSamples ++;
1311
}
1312
1313
if (interpreterProfilingState == IPROFILING_STATE_OFF &&
1314
!startPC && !TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))
1315
{
1316
interpreterProfilingINTSamples++;
1317
}
1318
#endif
1319
if (startPC)
1320
compInfo->_intervalStats._compiledMethodSamples++;
1321
else
1322
compInfo->_intervalStats._interpretedMethodSamples++;
1323
compInfo->getPersistentInfo()->incJitTotalSampleCount();
1324
1325
#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
1326
DLTLogic(vmThread, compInfo);
1327
#endif
1328
1329
if(TrcEnabled_Trc_JIT_MethodSampleStart1)
1330
{
1331
walkStackForSamplingReduced(vmThread);
1332
}
1333
else if(TrcEnabled_Trc_JIT_MethodSampleStart)
1334
{
1335
walkStackForSampling(vmThread);
1336
}
1337
1338
#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
1339
if (!TR::Options::getCmdLineOptions()->getOption(TR_MimicInterpreterFrameShape) &&
1340
!compInfo->getPersistentInfo()->getDisableFurtherCompilation())
1341
{
1342
static char *enableDebugDLT = feGetEnv("TR_DebugDLT");
1343
static J9Method *skipDLTMethod = NULL;
1344
bool skipSampleMethod = false;
1345
1346
/* Code to support disableCompilationAfterDLT option:
1347
* If env var TR_DebugDLT & option disableCompilationAfterDLT
1348
* is used, do not allow sampling interrupt to queue a standard
1349
* compilation for any method that has already been DLT compiled.
1350
*
1351
* A static J9Method pointer is used to avoid incurring the overhead
1352
* of finding option sets as much as possible.
1353
*/
1354
if (enableDebugDLT != NULL && compInfo->searchForDLTRecord(walkState.method, -1) != NULL)
1355
{
1356
if (skipDLTMethod==walkState.method)
1357
{
1358
skipSampleMethod = true;
1359
}
1360
else if (TR::Options::getCmdLineOptions()->getOption(TR_DisableCompilationAfterDLT))
1361
{
1362
skipDLTMethod = walkState.method;
1363
skipSampleMethod = true;
1364
}
1365
else
1366
{
1367
TR::OptionSet *optionSet = findOptionSet(walkState.method, false);
1368
if (optionSet != NULL &&
1369
optionSet->getOptions() != NULL &&
1370
optionSet->getOptions()->getOption(TR_DisableCompilationAfterDLT))
1371
{
1372
skipDLTMethod = walkState.method;
1373
skipSampleMethod = true;
1374
}
1375
}
1376
}
1377
/* If TR_DebugDLT env var is not used, no DLT has been done
1378
* for this method, or the disableCompilationAfterDLT option was not
1379
* used for the method, then queue a compilation with sampleMethod()
1380
*/
1381
if (!skipSampleMethod)
1382
TR::Recompilation::sampleMethod(vmThread, vm, startPC, codeSize, walkState.pc, walkState.method, jitConfig->samplingTickCount);
1383
}
1384
#else // !J9VM_JIT_DYNAMIC_LOOP_TRANSFER
1385
if (!TR::Options::getCmdLineOptions()->getOption(TR_MimicInterpreterFrameShape) &&
1386
!compInfo->getPersistentInfo()->getDisableFurtherCompilation())
1387
{
1388
TR::Recompilation::sampleMethod(vmThread, vm, startPC, codeSize, walkState.pc, walkState.method, jitConfig->samplingTickCount);
1389
}
1390
#endif
1391
}
1392
}
1393
1394
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
1395
static void jitHookClassesUnloadEnd(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1396
{
1397
}
1398
#endif
1399
1400
typedef struct J9JitPrivateThreadData{
1401
U_8 numberOfFrames;
1402
U_8 numberOfBuffers;
1403
U_8 frameCount;
1404
int index;
1405
U_8 * pcList[1];
1406
}J9JitPrivateThreadData;
1407
1408
/**
1409
* Collect jitted stack frames during GC stack walks to help with debugging GC map PMRs.
1410
*
1411
* CAUTION walkThread is the thread doing the walking - usually a GC worker thread. It is not
1412
* the thread we want to use to find the appropriate buffer to update. For that we need to look
1413
* in walkState->walkThread. The walkThread parameter seems to be unnecessary.
1414
*/
1415
static UDATA collectJitPrivateThreadData(J9VMThread * walkThread, J9StackWalkState * walkState)
1416
{
1417
J9JitPrivateThreadData * jitData = NULL;
1418
J9VMThread * threadBeingWalked = walkState->walkThread;
1419
if (threadBeingWalked)
1420
jitData = (J9JitPrivateThreadData *)threadBeingWalked->jitPrivateData;
1421
1422
if(NULL != walkState->jitInfo && jitData && (jitData->frameCount < (jitData->numberOfFrames-1) ))
1423
{
1424
jitData->pcList[jitData->index] = walkState->pc;
1425
jitData->frameCount++;
1426
jitData->index = (jitData->index+1);
1427
}
1428
1429
return J9_STACKWALK_KEEP_ITERATING;
1430
}
1431
1432
void finalizeJitPrivateThreadData(J9VMThread * currentThread)
1433
{
1434
J9VMThread *thread = currentThread;
1435
J9JitPrivateThreadData * jitData;
1436
do
1437
{
1438
if(thread->jitPrivateData)
1439
{
1440
jitData= (J9JitPrivateThreadData *)thread->jitPrivateData;
1441
while(jitData->index%jitData->numberOfFrames!=0 && jitData->index <(jitData->numberOfFrames)*(jitData->numberOfBuffers))
1442
{
1443
jitData->pcList[jitData->index]=0;
1444
jitData->index = (jitData->index+1)%((jitData->numberOfFrames)*(jitData->numberOfBuffers));
1445
}
1446
jitData->frameCount=0;
1447
}
1448
thread = thread->linkNext;
1449
}
1450
while (thread &&(thread != currentThread));
1451
}
1452
1453
void initJitPrivateThreadData(J9VMThread * currentThread)
1454
{
1455
if(!currentThread->javaVM->collectJitPrivateThreadData)
1456
{
1457
currentThread->javaVM->collectJitPrivateThreadData = &collectJitPrivateThreadData;
1458
}
1459
J9VMThread *thread = currentThread;
1460
J9JitPrivateThreadData * jitData;
1461
do
1462
{
1463
if(thread->jitPrivateData)
1464
{
1465
jitData= (J9JitPrivateThreadData *)thread->jitPrivateData;
1466
while(jitData->index%jitData->numberOfFrames!=0 && jitData->index <(jitData->numberOfFrames)*(jitData->numberOfBuffers))
1467
{
1468
jitData->pcList[jitData->index]=0;
1469
jitData->index = (jitData->index+1)%((jitData->numberOfFrames)*(jitData->numberOfBuffers));
1470
}
1471
1472
if(jitData->frameCount!=0)
1473
{
1474
if(jitData->index!=0)
1475
jitData->pcList[jitData->index-1] =(U_8*) 1;
1476
else
1477
jitData->pcList[jitData->numberOfFrames*jitData->numberOfBuffers-1] = (U_8*)1;
1478
}
1479
1480
jitData->frameCount=0;
1481
}
1482
thread = thread->linkNext;
1483
}
1484
while (thread &&(thread != currentThread));
1485
}
1486
1487
static void jitHookGlobalGCStart(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1488
{
1489
J9VMThread* vmThread = (J9VMThread*)((MM_GlobalGCStartEvent *)eventData)->currentThread->_language_vmthread;
1490
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1491
1492
if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers() && TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames())
1493
initJitPrivateThreadData(vmThread);
1494
1495
if (jitConfig && jitConfig->runtimeFlags & J9JIT_GC_NOTIFY)
1496
printf("\n{GGC");
1497
jitReclaimMarkedAssumptions(false);
1498
}
1499
1500
static void jitHookLocalGCStart(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1501
{
1502
MM_LocalGCStartEvent * localGCStartEventData = (MM_LocalGCStartEvent *)eventData;
1503
J9VMThread * vmThread = (J9VMThread *)localGCStartEventData->currentThread->_language_vmthread;
1504
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1505
1506
if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers() && TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames())
1507
initJitPrivateThreadData(vmThread);
1508
1509
if (jitConfig == 0)
1510
return; // if a hook gets called after freeJitConfig then not much else we can do
1511
1512
if (jitConfig->runtimeFlags & J9JIT_GC_NOTIFY)
1513
printf("\n{Scavenge");
1514
1515
if (jitConfig->gcTraceThreshold && jitConfig->gcCount == jitConfig->gcTraceThreshold)
1516
{
1517
printf("\n<jit: enabling stack tracing at gc %" OMR_PRIuPTR ">", jitConfig->gcCount);
1518
TR::Options::getCmdLineOptions()->setVerboseOption(TR_VerboseGc);
1519
}
1520
jitReclaimMarkedAssumptions(false);
1521
}
1522
1523
static void jitHookGlobalGCEnd(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1524
{
1525
J9VMThread* vmThread = (J9VMThread*)((MM_GlobalGCStartEvent *)eventData)->currentThread->_language_vmthread;
1526
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1527
1528
if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers() && TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames())
1529
finalizeJitPrivateThreadData(vmThread);
1530
1531
if (jitConfig == 0)
1532
return; // if a hook gets called after freeJitConfig then not much else we can do
1533
1534
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
1535
1536
getOutOfIdleStatesUnlocked(TR::CompilationInfo::SAMPLER_DEEPIDLE, compInfo, "GC");
1537
1538
TR::CodeCacheManager::instance()->synchronizeTrampolines();
1539
if (jitConfig->runtimeFlags & J9JIT_GC_NOTIFY)
1540
printf("}");
1541
1542
}
1543
1544
static void jitHookLocalGCEnd(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1545
{
1546
J9VMThread * vmThread = (J9VMThread *) ((MM_LocalGCEndEvent *)eventData)->currentThread->_language_vmthread;
1547
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1548
1549
if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers() && TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames())
1550
finalizeJitPrivateThreadData(vmThread);
1551
1552
if (jitConfig == 0)
1553
return; // if a hook gets called after freeJitConfig then not much else we can do
1554
1555
if (jitConfig->runtimeFlags & J9JIT_GC_NOTIFY)
1556
printf("}");
1557
}
1558
1559
static void initThreadAfterCreation(J9VMThread *vmThread)
1560
{
1561
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1562
if (jitConfig == 0)
1563
return; // if a hook gets called after freeJitConfig then not much else we can do
1564
1565
if (TR::Options::getCmdLineOptions()->getOption(TR_EnableValueTracing))
1566
{
1567
PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);
1568
1569
TR_JitPrivateConfig *pJitConfig = (TR_JitPrivateConfig *)jitConfig->privateConfig;
1570
1571
if (pJitConfig)
1572
{
1573
int32_t size = pJitConfig->maxRuntimeTraceBufferSizeInBytes;
1574
UDATA buffer = (UDATA)j9mem_allocate_memory(size, J9MEM_CATEGORY_JIT);
1575
if (!buffer)
1576
return;
1577
1578
VMTHREAD_TRACINGBUFFER_CURSOR(vmThread) = buffer;
1579
1580
// Leave some headroom at the top of each buffer.
1581
//
1582
VMTHREAD_TRACINGBUFFER_TOP(vmThread) = buffer + size - pJitConfig->maxTraceBufferEntrySizeInBytes;
1583
1584
// Create a tracing file handle and prepare the file for writing.
1585
//
1586
char fileName[64];
1587
IDATA tracefp= -1;
1588
1589
sprintf(fileName, "%s_" POINTER_PRINTF_FORMAT, pJitConfig->itraceFileNamePrefix, vmThread);
1590
1591
if ((tracefp = j9file_open(fileName, EsOpenWrite | EsOpenAppend | EsOpenCreate, 0644)) == -1)
1592
{
1593
j9tty_err_printf(PORTLIB, "Error: Failed to open jit trace file %s.\n", fileName);
1594
}
1595
1596
VMTHREAD_TRACINGBUFFER_FH(vmThread) = tracefp;
1597
}
1598
}
1599
1600
#if defined(TR_HOST_S390)
1601
vmThread->codertTOC = (void *)jitConfig->pseudoTOC;
1602
#endif
1603
1604
if (TR::Options::getCmdLineOptions()->getOption(TR_CountWriteBarriersRT))
1605
{
1606
vmThread->debugEventData6 = 0;
1607
vmThread->debugEventData7 = 0;
1608
}
1609
1610
TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);
1611
#if defined(ENABLE_GPU)
1612
extern void *initGPUThread(J9VMThread *vmThread, TR::PersistentInfo *persistentInfo);
1613
initGPUThread(vmThread, compInfo->getPersistentInfo());
1614
#endif
1615
getOutOfIdleStates(TR::CompilationInfo::SAMPLER_DEEPIDLE, compInfo, "thread creation");
1616
1617
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableSamplingJProfiling))
1618
{
1619
uint8_t jitState = compInfo->getPersistentInfo()->getJitState();
1620
if (jitState == IDLE_STATE || jitState == STARTUP_STATE)
1621
vmThread->debugEventData4 = 1;
1622
else
1623
vmThread->debugEventData4 = 1;
1624
}
1625
1626
vmThread->jitCountDelta = 2; // by default we assume there are compilation threads active
1627
if (compInfo)
1628
{
1629
compInfo->acquireCompMonitor(vmThread);
1630
if (compInfo->getNumUsableCompilationThreads() > 0 && compInfo->getNumCompThreadsActive() == 0)
1631
{
1632
vmThread->jitCountDelta = 0;
1633
}
1634
compInfo->releaseCompMonitor(vmThread);
1635
1636
vmThread->maxProfilingCount = (UDATA)encodeCount(compInfo->getIprofilerMaxCount());
1637
}
1638
1639
U_8 numberOfBuffers,numberOfFrames;
1640
if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers() <= 255)
1641
numberOfBuffers=TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfBuffers();
1642
else
1643
numberOfBuffers=255;
1644
1645
if(TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames() <= 254)
1646
numberOfFrames=TR::Options::getCmdLineOptions()->getStackPCDumpNumberOfFrames();
1647
else
1648
numberOfFrames=254;
1649
1650
if(!vmThread->jitPrivateData && numberOfFrames && numberOfBuffers)
1651
{
1652
numberOfFrames++;
1653
vmThread->jitPrivateData = (J9JitPrivateThreadData *) TR_Memory::jitPersistentAlloc(sizeof(J9JitPrivateThreadData)+(numberOfFrames*numberOfBuffers -1)*sizeof(U_8*));
1654
J9JitPrivateThreadData * jitData= (J9JitPrivateThreadData *)vmThread->jitPrivateData;
1655
//199878 : jitPersistentAlloc may return NULL and this extra diagnostics should take an extra care to not segfault in such a scenario.
1656
if (!jitData)
1657
{
1658
return;
1659
}
1660
jitData->numberOfBuffers = numberOfBuffers;
1661
jitData->numberOfFrames = numberOfFrames;
1662
memset(jitData->pcList,0,(jitData->numberOfFrames)*(jitData->numberOfBuffers)*sizeof(U_8*));
1663
jitData->index=0;
1664
jitData->frameCount=0;
1665
}
1666
1667
return;
1668
}
1669
1670
static void accumulateAndPrintDebugCounters(J9JITConfig *jitConfig)
1671
{
1672
TR_Debug *debug = TR::Options::getDebug();
1673
if (debug)
1674
{
1675
TR::DebugCounterGroup *counters;
1676
counters = TR::CompilationInfo::get(jitConfig)->getPersistentInfo()->getStaticCounters();
1677
if (counters)
1678
{
1679
counters->accumulate();
1680
debug->printDebugCounters(counters, "Static debug counters");
1681
}
1682
counters = TR::CompilationInfo::get(jitConfig)->getPersistentInfo()->getDynamicCounters();
1683
if (counters)
1684
{
1685
counters->accumulate();
1686
debug->printDebugCounters(counters, "Dynamic debug counters");
1687
}
1688
}
1689
}
1690
1691
static void jitHookThreadStart(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1692
{
1693
#if defined(TR_HOST_POWER)
1694
J9VMThread *vmThread = ((J9VMThreadStartedEvent *)eventData)->currentThread;
1695
1696
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1697
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
1698
if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())
1699
{
1700
if (!IS_THREAD_RI_INITIALIZED(vmThread))
1701
{
1702
TR_HWProfiler *hwProfiler = compInfo->getHWProfiler();
1703
hwProfiler->initializeThread(vmThread);
1704
}
1705
}
1706
#endif //defined(TR_HOST_POWER)
1707
}
1708
1709
1710
static void jitHookThreadCreate(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1711
{
1712
J9VMThread *vmThread = ((J9VMThreadCreatedEvent *)eventData)->vmThread;
1713
initThreadAfterCreation(vmThread);
1714
}
1715
1716
static void jitHookThreadCrash(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1717
{
1718
J9VMThread * vmThread = ((J9VMThreadCrashEvent *)eventData)->currentThread;
1719
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1720
1721
if (jitConfig == 0)
1722
return; // if a hook gets called after freeJitConfig then not much else we can do
1723
1724
accumulateAndPrintDebugCounters(jitConfig);
1725
1726
fflush(stdout);
1727
1728
} // jitHookThreadCrash
1729
1730
static void jitHookThreadEnd(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1731
{
1732
J9VMThread * vmThread = ((J9VMThreadEndEvent *)eventData)->currentThread;
1733
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1734
PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM);
1735
1736
if (jitConfig == 0)
1737
return; // if a hook gets called after freeJitConfig then not much else we can do
1738
1739
if (TR::Options::getCmdLineOptions()->getOption(TR_CountWriteBarriersRT))
1740
{
1741
fprintf(stderr,"Thread %p: Executed %" OMR_PRIuPTR " barriers, %" OMR_PRIuPTR " went to slow path\n", vmThread, vmThread->debugEventData6, vmThread->debugEventData7);
1742
}
1743
return;
1744
}
1745
1746
static void jitHookThreadDestroy(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1747
{
1748
J9VMThread * vmThread = ((J9VMThreadEndEvent *)eventData)->currentThread;
1749
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1750
PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM);
1751
1752
// Runtime Instrumentation
1753
TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);
1754
#if defined(ENABLE_GPU)
1755
extern void *terminateGPUThread(J9VMThread *vmThread);
1756
terminateGPUThread(vmThread);
1757
#endif
1758
TR_HWProfiler *hwProfiler = compInfo->getHWProfiler();
1759
if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled() && hwProfiler->isHWProfilingAvailable(vmThread))
1760
{
1761
if (IS_THREAD_RI_INITIALIZED(vmThread))
1762
hwProfiler->deinitializeThread(vmThread);
1763
}
1764
1765
void *vmWithThreadInfo = vmThread->jitVMwithThreadInfo;
1766
1767
if (vmWithThreadInfo)
1768
{
1769
TR_J9VMBase *fej9 = (TR_J9VMBase *)vmWithThreadInfo;
1770
fej9->freeSharedCache();
1771
vmThread->jitVMwithThreadInfo = 0;
1772
j9mem_free_memory(vmWithThreadInfo);
1773
}
1774
1775
void *ExceptionHandlerCache = vmThread->jitExceptionHandlerCache;
1776
1777
if (ExceptionHandlerCache)
1778
{
1779
vmThread->jitExceptionHandlerCache = 0;
1780
j9mem_free_memory(ExceptionHandlerCache);
1781
}
1782
1783
void *ArtifactSearchCache = vmThread->jitArtifactSearchCache;
1784
if (ArtifactSearchCache)
1785
{
1786
vmThread->jitArtifactSearchCache=0;
1787
j9mem_free_memory(ArtifactSearchCache);
1788
}
1789
1790
J9JitPrivateThreadData * jitData = (J9JitPrivateThreadData *)vmThread->jitPrivateData;
1791
if(jitData && jitConfig)
1792
{
1793
vmThread->jitPrivateData=0;
1794
TR_Memory::jitPersistentFree(jitData);
1795
}
1796
1797
1798
#ifdef J9VM_INTERP_AOT_COMPILE_SUPPORT
1799
vmWithThreadInfo = vmThread->aotVMwithThreadInfo;
1800
if (vmWithThreadInfo)
1801
{
1802
TR_J9VMBase *vm = (TR_J9VMBase *)vmWithThreadInfo;
1803
vm->freeSharedCache();
1804
vmThread->aotVMwithThreadInfo = 0;
1805
j9mem_free_memory(vmWithThreadInfo);
1806
}
1807
#endif
1808
1809
return;
1810
}
1811
1812
#if defined(J9VM_OPT_CRIU_SUPPORT)
1813
static void jitHookPrepareCheckpoint(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1814
{
1815
}
1816
1817
static void jitHookPrepareRestore(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1818
{
1819
J9VMClassesUnloadEvent * restoreEvent = (J9VMClassesUnloadEvent *)eventData;
1820
J9VMThread * vmThread = restoreEvent->currentThread;
1821
J9JavaVM * javaVM = vmThread->javaVM;
1822
1823
/* If the restored run does not allow further checkpoints, then
1824
* remove the portability restrictions on the target CPU (used
1825
* for JIT compiles) to allow optimal code generation
1826
*/
1827
if (!javaVM->internalVMFunctions->isCheckpointAllowed(vmThread))
1828
{
1829
TR::Compiler->target.cpu = TR::CPU::detect(TR::Compiler->omrPortLib);
1830
jitConfig->targetProcessor = TR::Compiler->target.cpu.getProcessorDescription();
1831
}
1832
}
1833
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
1834
1835
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
1836
static void jitHookClassesUnload(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1837
{
1838
J9VMClassesUnloadEvent * unloadedEvent = (J9VMClassesUnloadEvent *)eventData;
1839
J9VMThread * vmThread = unloadedEvent->currentThread;
1840
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
1841
1842
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
1843
TR::PersistentInfo * persistentInfo = compInfo->getPersistentInfo();
1844
1845
// Here we need to set CompilationShouldBeInterrupted. Currently if the TR_EnableNoVMAccess is not
1846
// set the compilation is stopped, but should be notify not to continue afterwards.
1847
//
1848
compInfo->setAllCompilationsShouldBeInterrupted();
1849
1850
bool firstRange = true;
1851
bool coldRangeUninitialized = true;
1852
uintptr_t rangeStartPC = 0;
1853
uintptr_t rangeEndPC = 0;
1854
uintptr_t rangeColdStartPC = 0;
1855
uintptr_t rangeColdEndPC = 0;
1856
1857
uintptr_t rangeStartMD = 0;
1858
uintptr_t rangeEndMD = 0;
1859
1860
TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();
1861
1862
bool hasMethodOverrideAssumptions = false;
1863
bool hasClassExtendAssumptions = false;
1864
bool hasClassUnloadAssumptions = false;
1865
bool hasClassRedefinitionAssumptions = false;
1866
bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassUnloading);
1867
if (p)
1868
{
1869
TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "Classes unloaded \n");
1870
}
1871
1872
//All work here is only done if there is a chtable. Small have no table, thus nothing to do.
1873
1874
TR_PersistentCHTable * table = 0;
1875
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))
1876
table = persistentInfo->getPersistentCHTable();
1877
1878
if (table && table->isActive())
1879
{
1880
TR_FrontEnd * fe = TR_J9VMBase::get(jitConfig, vmThread);
1881
1882
// If space for the array of visited superclasses has not yet been allocated, do it now
1883
// There is no race condition because everything is frozen during class unloading
1884
if (!persistentInfo->getVisitedSuperClasses())
1885
persistentInfo->setVisitedSuperClasses((TR_OpaqueClassBlock **)TR_Memory::jitPersistentAlloc(MAX_SUPERCLASSES*sizeof(TR_OpaqueClassBlock *), TR_Memory::PersistentInfo));
1886
// The following is safe to execute even if there is no backing for the visitedSuperClasses array
1887
persistentInfo->clearVisitedSuperClasses();
1888
1889
PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM);
1890
J9ClassWalkState classWalkState;
1891
J9Class * j9clazz;
1892
TR_OpaqueClassBlock *clazz;
1893
j9clazz = vmThread->javaVM->internalVMFunctions->allClassesStartDo(&classWalkState, vmThread->javaVM, NULL);
1894
while (j9clazz)
1895
{
1896
// If the romableAotITable field is set to 0, that means this class was not caught
1897
// by the JIT load hook and has not been loaded.
1898
//
1899
if (J9CLASS_FLAGS(j9clazz) & J9AccClassDying && j9clazz->romableAotITable !=0 )
1900
{
1901
clazz = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(j9clazz);
1902
table->classGotUnloadedPost(fe,clazz); // side-effect: builds the array of visited superclasses
1903
}
1904
j9clazz = vmThread->javaVM->internalVMFunctions->allClassesNextDo(&classWalkState);
1905
}
1906
1907
vmThread->javaVM->internalVMFunctions->allClassesEndDo(&classWalkState);
1908
1909
1910
TR_OpaqueClassBlock **visitedSuperClasses = persistentInfo->getVisitedSuperClasses();
1911
if (visitedSuperClasses && !persistentInfo->tooManySuperClasses())
1912
{
1913
int32_t numSuperClasses = persistentInfo->getNumVisitedSuperClasses();
1914
1915
for (int32_t index = 0; index < numSuperClasses; index++)
1916
{
1917
clazz = visitedSuperClasses[index];
1918
TR_PersistentClassInfo *classInfo = table->findClassInfo(clazz);
1919
if (classInfo)
1920
classInfo->resetVisited();
1921
}
1922
}
1923
else
1924
{
1925
table->resetVisitedClasses();
1926
}
1927
}
1928
1929
return;
1930
}
1931
1932
/// Side effect
1933
/// 1. Every anon class to be unloaded will have j9clazz->classLoader = NULL
1934
/// 2. Every j9clazz->jitMetaDataList will be set to NULL
1935
static void jitHookAnonClassesUnload(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
1936
{
1937
J9VMAnonymousClassesUnloadEvent * unloadedEvent = (J9VMAnonymousClassesUnloadEvent *)eventData;
1938
J9VMThread * vmThread = unloadedEvent->currentThread;
1939
UDATA anonymousClassUnloadCount = unloadedEvent->anonymousClassUnloadCount;
1940
1941
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseClassUnloading))
1942
TR_VerboseLog::writeLineLocked(TR_Vlog_GC, "jitHookAnonClassesUnload: unloading %u anonymous classes\n", (uint32_t)anonymousClassUnloadCount);
1943
1944
// Create a dummy classLoader and change j9class->classLoader to point to this fake one
1945
J9ClassLoader dummyClassLoader;
1946
int32_t numClasses = 0;
1947
bool needsMCCCleaning = false;
1948
for (J9Class* j9clazz = unloadedEvent->anonymousClassesToUnload; j9clazz; j9clazz = j9clazz->gcLink)
1949
{
1950
numClasses++;
1951
j9clazz->classLoader = &dummyClassLoader;
1952
1953
if (j9clazz->classFlags & J9ClassContainsMethodsPresentInMCCHash)
1954
{
1955
needsMCCCleaning = true;
1956
}
1957
}
1958
// TODO assert that numClasses == anonymousClassUnloadCount
1959
1960
// Concatenate all the lists of metadata from each class to be unloaded into
1961
// a bigger list (fullChainOfMetaData). Then attach this bigger list to the dummy classloader
1962
//
1963
J9JITExceptionTable* fullChainOfMetaData = NULL;
1964
uint32_t numMetaData = 0;
1965
for (J9Class* j9clazz = unloadedEvent->anonymousClassesToUnload; j9clazz; j9clazz = j9clazz->gcLink)
1966
{
1967
if (j9clazz->jitMetaDataList) // is there any metadata for this class?
1968
{
1969
// ASSUME that j9clazz->extendedClassFlags & J9ClassContainsJittedMethods is non zero
1970
// Find the end the metadata list
1971
J9JITExceptionTable *lastMetaData = j9clazz->jitMetaDataList;
1972
for (; lastMetaData->nextMethod; lastMetaData = lastMetaData->nextMethod)
1973
numMetaData++;
1974
// Attach the chain assembled so far at the end of the current list
1975
lastMetaData->nextMethod = fullChainOfMetaData;
1976
if (fullChainOfMetaData)
1977
fullChainOfMetaData->prevMethod = lastMetaData;
1978
fullChainOfMetaData = j9clazz->jitMetaDataList;
1979
j9clazz->jitMetaDataList = NULL; // don't want metadata appearing in two lists
1980
}
1981
}
1982
// If I have any metadata to be cleaned up
1983
if (fullChainOfMetaData)
1984
{
1985
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseClassUnloading))
1986
TR_VerboseLog::writeLineLocked(TR_Vlog_GC, "jitHookAnonClassesUnload: will remove %u metadata entities\n", numMetaData);
1987
// Attach the full chain to the dummy classloader
1988
dummyClassLoader.jitMetaDataList = fullChainOfMetaData;
1989
// Perform the cleanup
1990
jitRemoveAllMetaDataForClassLoader(vmThread, &dummyClassLoader);
1991
}
1992
1993
// Remove entries from the MCC hash tables related to trampolines
1994
if (needsMCCCleaning)
1995
{
1996
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseClassUnloading))
1997
TR_VerboseLog::writeLineLocked(TR_Vlog_GC, "jitHookAnonClassesUnload: will perform MCC cleaning\n");
1998
TR::CodeCacheManager::instance()->onClassUnloading(&dummyClassLoader);
1999
}
2000
2001
J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;
2002
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2003
#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
2004
compInfo->cleanDLTRecordOnUnload();
2005
if (compInfo->getDLT_HT())
2006
compInfo->getDLT_HT()->onClassUnloading();
2007
#endif
2008
2009
compInfo->getLowPriorityCompQueue().purgeEntriesOnClassLoaderUnloading(&dummyClassLoader);
2010
2011
compInfo->getPersistentInfo()->incGlobalClassUnloadID();
2012
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
2013
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableIProfilerThread))
2014
{
2015
TR_J9VMBase * vmj9 = (TR_J9VMBase *)(TR_J9VMBase::get(jitConfig, vmThread));
2016
TR_IProfiler *iProfiler = vmj9->getIProfiler();
2017
if (iProfiler) // even if Iprofiler is disabled, there might be some buffers in the queue
2018
{ // which need to be invalidated
2019
iProfiler->invalidateProfilingBuffers();
2020
}
2021
}
2022
#endif
2023
2024
// Invalidate the buffers from the hardware profiler
2025
if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())
2026
compInfo->getHWProfiler()->invalidateProfilingBuffers();
2027
2028
// Don't want j9classes to point to the dummy class loader that will disappear
2029
for (J9Class* j9clazz = unloadedEvent->anonymousClassesToUnload; j9clazz; j9clazz = j9clazz->gcLink)
2030
{
2031
cgOnClassUnloading(j9clazz);
2032
j9clazz->classLoader = NULL;
2033
}
2034
}
2035
#endif /* defined (J9VM_GC_DYNAMIC_CLASS_UNLOADING)*/
2036
2037
2038
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
2039
static void jitHookClassUnload(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
2040
{
2041
J9VMClassUnloadEvent * unloadedEvent = (J9VMClassUnloadEvent *)eventData;
2042
J9VMThread * vmThread = unloadedEvent->currentThread;
2043
J9Class * j9clazz = unloadedEvent->clazz;
2044
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
2045
2046
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2047
2048
TR_J9VMBase * fej9 = TR_J9VMBase::get(jitConfig, vmThread);
2049
TR_OpaqueClassBlock *clazz = fej9->convertClassPtrToClassOffset(j9clazz);
2050
2051
{
2052
TR::ClassTableCriticalSection removeClasses(fej9);
2053
TR_ASSERT(!removeClasses.acquiredVMAccess(), "jitHookClassUnload should already have VM access");
2054
TR_LinkHead0<TR_ClassHolder> *classList = compInfo->getListOfClassesToCompile();
2055
2056
TR_ClassHolder *prevClass = NULL;
2057
TR_ClassHolder *crtClass = classList->getFirst();
2058
while (crtClass)
2059
{
2060
if (crtClass->getClass() == j9clazz) // found the class; remove it from the list
2061
{
2062
classList->removeAfter(prevClass, crtClass);
2063
//break; // we cannot have duplicates - we might have duplicates, see JTC-JAT 67575 comment 104
2064
}
2065
prevClass = crtClass;
2066
crtClass = crtClass->getNext();
2067
}
2068
}
2069
2070
bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassUnloading);
2071
if (p)
2072
{
2073
TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "Class unloading for class=0x%p\n", j9clazz);
2074
}
2075
2076
PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM);
2077
2078
// remove from compilation request queue any methods that belong to this class
2079
fej9->acquireCompilationLock();
2080
fej9->invalidateCompilationRequestsForUnloadedMethods(clazz, false);
2081
fej9->releaseCompilationLock();
2082
2083
J9Method * resolvedMethods = (J9Method *) fej9->getMethods((TR_OpaqueClassBlock*)j9clazz);
2084
uint32_t numMethods = fej9->getNumMethods((TR_OpaqueClassBlock*)j9clazz);
2085
uintptr_t methodsStartAddr = 0;
2086
uintptr_t methodsEndAddr = 0;
2087
2088
if ( numMethods >0 )
2089
{
2090
methodsStartAddr = TR::Compiler->mtd.bytecodeStart( (TR_OpaqueMethodBlock *)&(resolvedMethods[0]));
2091
methodsEndAddr = TR::Compiler->mtd.bytecodeStart( (TR_OpaqueMethodBlock *)&(resolvedMethods[numMethods-1]))
2092
+ TR::Compiler->mtd.bytecodeSize( (TR_OpaqueMethodBlock *)&(resolvedMethods[numMethods-1]) );
2093
}
2094
2095
static char *disableUnloadedClassRanges = feGetEnv("TR_disableUnloadedClassRanges");
2096
if (!disableUnloadedClassRanges)
2097
compInfo->getPersistentInfo()->addUnloadedClass(clazz, methodsStartAddr, (uint32_t)(methodsEndAddr-methodsStartAddr));
2098
2099
TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();
2100
rat->notifyClassUnloadEvent(fej9, 0, clazz, clazz);
2101
2102
// Patch all the sites registered with dummy class pointer (-1)
2103
// These sites are patched each time any class is loaded
2104
//
2105
// These will be IPIC slots registered at compile time (PICs have not been populated yet)
2106
//
2107
rat->notifyClassUnloadEvent(fej9, 0, (TR_OpaqueClassBlock *)-1, clazz);
2108
2109
// THIS ONLY NEEDS TO BE DONE FOR s390-31
2110
// BEGIN
2111
2112
{
2113
TR::VMAccessCriticalSection notifyClassUnloadEvent(fej9);
2114
for (J9ITable * iTableEntry = (J9ITable *) TR::Compiler->cls.convertClassOffsetToClassPtr(clazz)->iTable; iTableEntry; iTableEntry = iTableEntry->next)
2115
{
2116
TR_OpaqueClassBlock *interfaceCl = fej9->convertClassPtrToClassOffset(iTableEntry->interfaceClass);
2117
rat->notifyClassUnloadEvent(fej9, 0, interfaceCl, clazz);
2118
}
2119
}
2120
2121
// END
2122
2123
TR_PersistentCHTable * table = 0;
2124
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))
2125
table = compInfo->getPersistentInfo()->getPersistentCHTable();
2126
if (table && table->isActive())
2127
table->classGotUnloaded(fej9, clazz);
2128
2129
#if defined(J9VM_OPT_JITSERVER)
2130
// Add to JITServer unload list
2131
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)
2132
{
2133
compInfo->getUnloadedClassesTempList()->push_back(clazz);
2134
// Loop through the set to find the class that needs to be purged.
2135
// Once found erase from the set.
2136
compInfo->getclassesCachedAtServer().erase(unloadedEvent->clazz);
2137
if (auto deserializer = compInfo->getJITServerAOTDeserializer())
2138
deserializer->invalidateClass(vmThread, j9clazz);
2139
}
2140
#endif
2141
}
2142
#endif /* defined (J9VM_GC_DYNAMIC_CLASS_UNLOADING)*/
2143
2144
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
2145
static void jitHookClassLoaderUnload(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
2146
{
2147
J9VMClassLoaderUnloadEvent * unloadedEvent = (J9VMClassLoaderUnloadEvent *)eventData;
2148
J9VMThread * vmThread = unloadedEvent->currentThread;
2149
J9ClassLoader * classLoader = unloadedEvent->classLoader;
2150
2151
// Assumptions are registered during class loading event. For a class loader that has never loaded a class, the JIT won't know about it
2152
if (classLoader->classSegments == NULL)
2153
return;
2154
2155
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
2156
2157
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2158
2159
bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassUnloading);
2160
if (p)
2161
{
2162
TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "Class unloading for classLoader=0x%p\n", classLoader);
2163
}
2164
compInfo->getPersistentInfo()->incGlobalClassUnloadID();
2165
2166
PORT_ACCESS_FROM_JAVAVM(vmThread->javaVM);
2167
2168
if (classLoader->flags & J9CLASSLOADER_CONTAINS_JITTED_METHODS)
2169
jitRemoveAllMetaDataForClassLoader(vmThread, classLoader);
2170
2171
if (classLoader->flags & J9CLASSLOADER_CONTAINS_METHODS_PRESENT_IN_MCC_HASH)
2172
TR::CodeCacheManager::instance()->onClassUnloading(classLoader);
2173
2174
// CodeGen-specific actions on class unloading
2175
cgOnClassUnloading(classLoader);
2176
2177
compInfo->getLowPriorityCompQueue().purgeEntriesOnClassLoaderUnloading(classLoader);
2178
2179
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
2180
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableIProfilerThread))
2181
{
2182
TR_J9VMBase * vmj9 = (TR_J9VMBase *)(TR_J9VMBase::get(jitConfig, vmThread));
2183
TR_IProfiler *iProfiler = vmj9->getIProfiler();
2184
if (iProfiler) // even if Iprofiler is disabled, there might be some buffers in the queue
2185
{ // which need to be invalidated
2186
iProfiler->invalidateProfilingBuffers();
2187
}
2188
}
2189
#endif
2190
2191
// Invalidate the buffers from the hardware profiler
2192
if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())
2193
compInfo->getHWProfiler()->invalidateProfilingBuffers();
2194
2195
compInfo->getPersistentInfo()->getPersistentClassLoaderTable()->removeClassLoader(vmThread, classLoader);
2196
2197
#if defined(J9VM_OPT_JITSERVER)
2198
if (auto deserializer = compInfo->getJITServerAOTDeserializer())
2199
deserializer->invalidateClassLoader(vmThread, classLoader);
2200
#endif /* defined(J9VM_OPT_JITSERVER) */
2201
}
2202
2203
#endif /* defined (J9VM_GC_DYNAMIC_CLASS_UNLOADING)*/
2204
2205
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING) && defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
2206
static void jitHookClassLoadersUnload(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
2207
{
2208
J9VMClassUnloadEvent * unloadedEvent = (J9VMClassUnloadEvent *)eventData;
2209
J9VMThread * vmThread = unloadedEvent->currentThread;
2210
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
2211
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2212
compInfo->cleanDLTRecordOnUnload();
2213
if (compInfo->getDLT_HT())
2214
compInfo->getDLT_HT()->onClassUnloading();
2215
}
2216
#endif /* defined (J9VM_GC_DYNAMIC_CLASS_UNLOADING) and defined (J9VM_JIT_DYNAMIC_LOOP_TRANSFER) */
2217
2218
void jitDiscardPendingCompilationsOfNatives(J9VMThread *vmThread, J9Class *clazz)
2219
{
2220
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
2221
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2222
// need to get the compilation lock before updating the queue
2223
compInfo->acquireCompilationLock();
2224
compInfo->setAllCompilationsShouldBeInterrupted();
2225
compInfo->invalidateRequestsForNativeMethods(clazz, vmThread);
2226
compInfo->releaseCompilationLock();
2227
}
2228
2229
static bool classesAreRedefinedInPlace()
2230
{
2231
if(TR::Options::getCmdLineOptions()->getOption(TR_EnableHCR))
2232
return true;
2233
else return false;
2234
}
2235
2236
static bool methodsAreRedefinedInPlace()
2237
{
2238
// NOTE: making this return "true" will require careful thought.
2239
// Don't expect callers to respond properly. At the time this comment was
2240
// written, we had never tested that configuration. Consider calls to this
2241
// function just to be markers for places in the code that may require attention.
2242
//
2243
return false;
2244
}
2245
2246
// Hack markers
2247
#define VM_PASSES_SAME_CLASS_TWICE 1
2248
2249
#if (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))
2250
void jitClassesRedefined(J9VMThread * currentThread, UDATA classCount, J9JITRedefinedClass *classList, UDATA extensionsUsed)
2251
{
2252
reportHook(currentThread, "jitClassesRedefined");
2253
2254
if ((classCount == 0 || classList == NULL) && TR::Options::getCmdLineOptions()->getOption(TR_EnableHCR))
2255
{
2256
reportHookFinished(currentThread, "jitClassesRedefined", "Nothing to do");
2257
return;
2258
}
2259
2260
J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;
2261
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2262
TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, currentThread);
2263
TR_PersistentCHTable * table = 0;
2264
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))
2265
table = compInfo->getPersistentInfo()->getPersistentCHTable();
2266
2267
TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();
2268
2269
TR_OpaqueClassBlock *oldClass, *newClass;
2270
J9Method *oldMethod, *newMethod;
2271
2272
// A few definitions. In the jit's terminology:
2273
// The "stale method" is the one that points at the old bytecodes from before the hot swap.
2274
// The "stale class" is the one that points at the stale methods.
2275
// The "old class" is the j9class struct that existed before the hot swap.
2276
// The "new class" is the one created in response to the hot swap.
2277
//
2278
// NOTE: THIS MAY NOT MATCH THE VM'S TERMINOLOGY!
2279
//
2280
// Here we define various aliases so we can freely use the terminology we want.
2281
//
2282
TR_OpaqueClassBlock *&freshClass = classesAreRedefinedInPlace()? oldClass : newClass;
2283
TR_OpaqueClassBlock *&staleClass = classesAreRedefinedInPlace()? newClass : oldClass;
2284
J9Method *&freshMethod = methodsAreRedefinedInPlace()? oldMethod : newMethod;
2285
J9Method *&staleMethod = methodsAreRedefinedInPlace()? newMethod : oldMethod;
2286
2287
int methodCount;
2288
J9JITMethodEquivalence *methodList;
2289
bool equivalent;
2290
void* startPC;
2291
int i, j;
2292
2293
// JIT compilation thread could be running without exclusive access so we need to explicitly stop it
2294
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableNoVMAccess))
2295
{
2296
TR::MonitorTable::get()->getClassUnloadMonitor()->enter_write();
2297
}
2298
2299
// need to get the compilation lock before updating the queue
2300
fe->acquireCompilationLock();
2301
compInfo->setAllCompilationsShouldBeInterrupted();
2302
J9JITRedefinedClass *classPair = classList;
2303
if (!TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug))
2304
{
2305
for (i = 0; i < classCount; i++)
2306
{
2307
freshClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->newClass);
2308
if (VM_PASSES_SAME_CLASS_TWICE)
2309
staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(((J9Class*)freshClass)->replacedClass);
2310
else
2311
staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->oldClass);
2312
methodCount = classPair->methodCount;
2313
methodList = classPair->methodList;
2314
2315
int32_t length;
2316
char *name = fe->getClassNameChars((TR_OpaqueClassBlock*)freshClass, length);
2317
reportHookDetail(currentThread, "jitClassesRedefined", "Redefined class old=%p new=%p stale=%p fresh=%p %.*s", oldClass, newClass, staleClass, freshClass, length, name);
2318
2319
compInfo->getLowPriorityCompQueue().purgeEntriesOnClassRedefinition((J9Class*)staleClass);
2320
2321
// Step 1 remove from compilation request queue any methods that are redefined
2322
reportHookDetail(currentThread, "jitClassesRedefined", " Invalidate compilation requests for classes old=%p and new=%p", oldClass, newClass);
2323
fe->invalidateCompilationRequestsForUnloadedMethods(oldClass, true);
2324
fe->invalidateCompilationRequestsForUnloadedMethods(newClass, true);
2325
2326
for (j = 0; j < methodCount; j++)
2327
{
2328
staleMethod = methodList[j].oldMethod;
2329
freshMethod = methodList[j].newMethod;
2330
equivalent = (bool) methodList[j].equivalent;
2331
2332
reportHookDetail(currentThread, "jitClassesRedefined", " Notify MCC for method stale=%p fresh=%p e=%d", staleMethod, freshMethod, equivalent);
2333
TR::CodeCacheManager::instance()->onClassRedefinition(reinterpret_cast<TR_OpaqueMethodBlock *>(staleMethod),
2334
reinterpret_cast<TR_OpaqueMethodBlock *>(freshMethod));
2335
// Step 2 invalidate methods that are already compiled and trigger a new compilation.
2336
if (staleMethod && freshMethod && (startPC = compInfo->getPCIfCompiled(staleMethod)))
2337
{
2338
// Update the ram method information in PersistentMethodInfo
2339
TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(startPC);
2340
if (bodyInfo)
2341
{
2342
reportHookDetail(currentThread, "jitClassesRedefined", " Invalidate method body stale=%p startPC=%p", staleMethod, startPC);
2343
TR::Recompilation::invalidateMethodBody(startPC, fe);
2344
bodyInfo->setDisableSampling(true);
2345
TR_PersistentMethodInfo *pmi = bodyInfo->getMethodInfo();
2346
if (pmi)
2347
{
2348
pmi->setHasBeenReplaced();
2349
}
2350
// Note: we don't do pmi->setMethodInfo here because (a) they'll be patched by runtime
2351
// assumptions anyway, and (b) we can only get our hands on the latest PMI, not all the
2352
// older ones.
2353
}
2354
// Same as TR_ResolvedMethod::isNative without allocating Scratch Memory
2355
else if(_J9ROMMETHOD_J9MODIFIER_IS_SET((J9_ROM_METHOD_FROM_RAM_METHOD(staleMethod)), J9AccNative ))
2356
{
2357
reportHookDetail(currentThread, "jitClassesRedefined", "No need to invalidate native method stale=%p startPC=%p", staleMethod, startPC);
2358
}
2359
else
2360
{
2361
reportHookDetail(currentThread, "jitClassesRedefined", "WARNING! Cannot invalidate method body stale=%p startPC=%p", staleMethod, startPC);
2362
TR_ASSERT(0,"JIT HCR should make all methods recompilable, so startPC=%p should have a persistentBodyInfo", startPC);
2363
}
2364
}
2365
}
2366
classPair = (J9JITRedefinedClass *) ((char *) classPair->methodList + (classPair->methodCount * sizeof(struct J9JITMethodEquivalence)));
2367
}
2368
}
2369
//for extended HCR under FSD, all the methods in code cache needs to be
2370
//discarded because of inlining
2371
else
2372
{
2373
// Don't know what got replaced, so get pessimistic and clear the whole compilation queue
2374
reportHookDetail(currentThread, "jitClassesRedefined", " Invalidate all compilation requests");
2375
fe->invalidateCompilationRequestsForUnloadedMethods(NULL, true);
2376
2377
//clean up the trampolines
2378
TR::CodeCacheManager::instance()->onFSDDecompile();
2379
}
2380
2381
fe->releaseCompilationLock();
2382
2383
classPair = classList;
2384
for (i = 0; i < classCount; i++)
2385
{
2386
#if defined(J9VM_OPT_JITSERVER)
2387
// Add to JITServer unload list
2388
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)
2389
{
2390
compInfo->getUnloadedClassesTempList()->push_back((TR_OpaqueClassBlock *) classPair->oldClass);
2391
if (auto deserializer = compInfo->getJITServerAOTDeserializer())
2392
deserializer->invalidateClass(currentThread, classPair->oldClass);
2393
}
2394
#endif
2395
freshClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->newClass);
2396
if (VM_PASSES_SAME_CLASS_TWICE)
2397
staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(((J9Class*)freshClass)->replacedClass);
2398
else
2399
staleClass = ((TR_J9VMBase *)fe)->convertClassPtrToClassOffset(classPair->oldClass);
2400
methodCount = classPair->methodCount;
2401
methodList = classPair->methodList;
2402
2403
// Do this before modifying the CHTable
2404
if (table && table->isActive() && TR::Options::sharedClassCache() && TR::Options::getCmdLineOptions()->getOption(TR_EnableClassChainValidationCaching))
2405
{
2406
table->resetCachedCCVResult(fe, oldClass);
2407
}
2408
2409
// Step 3 patch modified classes
2410
if (rat)
2411
{
2412
reportHookDetail(currentThread, "jitClassesRedefined", " Notify RAT on class old=%p fresh=%p", oldClass, freshClass);
2413
rat->notifyClassRedefinitionEvent(fe, 0, oldClass, freshClass);
2414
}
2415
for (j = 0; j < methodCount; j++)
2416
{
2417
staleMethod = methodList[j].oldMethod;
2418
freshMethod = methodList[j].newMethod;
2419
bool isSMP = 1; // conservative
2420
if (table)
2421
{
2422
reportHookDetail(currentThread, "jitClassesRedefined", " Notify CHTable on method old=%p fresh=%p", oldMethod, freshMethod);
2423
table->methodGotOverridden(fe, compInfo->persistentMemory(), (TR_OpaqueMethodBlock*)freshMethod, (TR_OpaqueMethodBlock*)oldMethod, isSMP);
2424
}
2425
// Step 4 patch modified J9Method
2426
if (oldMethod && newMethod && rat)
2427
{
2428
reportHookDetail(currentThread, "jitClassesRedefined", " Notify RAT on method old=%p fresh=%p", oldMethod, freshMethod);
2429
rat->notifyClassRedefinitionEvent(fe, 0,
2430
oldMethod,
2431
freshMethod);
2432
2433
// Same as TR_ResolvedMethod::virtualMethodIsOverridden without allocating Scratch Memory
2434
if ((UDATA)oldMethod->constantPool & J9_STARTPC_METHOD_IS_OVERRIDDEN)
2435
{
2436
UDATA *cp = (UDATA*)&(newMethod->constantPool);
2437
*cp |= J9_STARTPC_METHOD_IS_OVERRIDDEN;
2438
}
2439
}
2440
}
2441
// Step 5 patch and update virtual guard. may also need to refresh CHTable
2442
if (table)
2443
{
2444
reportHookDetail(currentThread, "jitClassesRedefined", " Notify CHTable on class old=%p fresh=%p", oldClass, freshClass);
2445
table->classGotRedefined(fe, oldClass, freshClass);
2446
}
2447
2448
classPair = (J9JITRedefinedClass *) ((char *) classPair->methodList + (classPair->methodCount * sizeof(struct J9JITMethodEquivalence)));
2449
}
2450
2451
#if defined(J9VM_OPT_JITSERVER)
2452
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT && extensionsUsed)
2453
{
2454
compInfo->getUnloadedClassesTempList()->push_back(ClientSessionData::mustClearCachesFlag);
2455
}
2456
#endif
2457
2458
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableNoVMAccess))
2459
{
2460
TR::MonitorTable::get()->getClassUnloadMonitor()->exit_write();
2461
}
2462
2463
// In extended HCR, empty classList means methods are being added or removed from classes
2464
// Fall back to TR_MimicInterpreterFrameShape in this case because it's not properly
2465
// handled from VM side
2466
if (classCount == 0 || classList == NULL)
2467
TR::Options::getCmdLineOptions()->setOption(TR_MimicInterpreterFrameShape);
2468
2469
reportHookFinished(currentThread, "jitClassesRedefined");
2470
}
2471
2472
void jitFlushCompilationQueue(J9VMThread * currentThread, J9JITFlushCompilationQueueReason reason)
2473
{
2474
char *buffer = "unknown reason";
2475
if (reason == J9FlushCompQueueDataBreakpoint)
2476
buffer = "DataBreakpoint";
2477
else
2478
TR_ASSERT(0, "unexpected use of jitFlushCompilationQueue");
2479
2480
reportHook(currentThread, "jitFlushCompilationQueue ", buffer);
2481
2482
J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;
2483
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2484
TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, currentThread);
2485
2486
// JIT compilation thread could be running without exclusive access so we need to explicitly stop it
2487
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableNoVMAccess))
2488
{
2489
TR::MonitorTable::get()->getClassUnloadMonitor()->enter_write();
2490
}
2491
2492
// need to get the compilation lock before updating the queue
2493
fe->acquireCompilationLock();
2494
compInfo->setAllCompilationsShouldBeInterrupted();
2495
reportHookDetail(currentThread, "jitFlushCompilationQueue", " Invalidate all compilation requests");
2496
fe->invalidateCompilationRequestsForUnloadedMethods(NULL, true);
2497
//clean up the trampolines
2498
TR::CodeCacheManager::instance()->onFSDDecompile();
2499
fe->releaseCompilationLock();
2500
2501
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableNoVMAccess))
2502
{
2503
TR::MonitorTable::get()->getClassUnloadMonitor()->exit_write();
2504
}
2505
2506
reportHookFinished(currentThread, "jitFlushCompilationQueue ", buffer);
2507
}
2508
2509
#endif // #if (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64))
2510
2511
void jitMethodBreakpointed(J9VMThread *currentThread, J9Method *j9method)
2512
{
2513
J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;
2514
TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, currentThread);
2515
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2516
TR_RuntimeAssumptionTable *rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();
2517
2518
reportHook(currentThread, "jitMethodbreakpointed", "j9method %p\n", j9method);
2519
2520
if (rat)
2521
{
2522
rat->notifyMethodBreakpointed(fe, reinterpret_cast<TR_OpaqueMethodBlock *>(j9method));
2523
}
2524
2525
reportHookFinished(currentThread, "jitMethodbreakpointed");
2526
}
2527
2528
/*
2529
* JIT hook called by the VM on the event of illegal modification. Runtime assumption table will be notified.
2530
*/
2531
void jitIllegalFinalFieldModification(J9VMThread *currentThread, J9Class *fieldClass)
2532
{
2533
J9JITConfig * jitConfig = currentThread->javaVM->jitConfig;
2534
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2535
TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, currentThread);
2536
2537
// Set the bit so that VM doesn't report the modification next time
2538
fieldClass->classFlags |= J9ClassHasIllegalFinalFieldModifications;
2539
2540
#if defined(J9VM_OPT_JITSERVER)
2541
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
2542
{
2543
// Don't execute this hook at the jitserver side
2544
return;
2545
}
2546
else if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)
2547
{
2548
TR_OpaqueClassBlock *clazz = fe->convertClassPtrToClassOffset(fieldClass);
2549
compInfo->getSequencingMonitor()->enter();
2550
compInfo->getIllegalFinalFieldModificationList()->push_back(clazz);
2551
compInfo->getSequencingMonitor()->exit();
2552
}
2553
#endif
2554
2555
int32_t length;
2556
char *className = fe->getClassNameChars((TR_OpaqueClassBlock*)fieldClass, length);
2557
reportHook(currentThread, "jitIllegalFinalFieldModification", "class %p %.*s", fieldClass, length, className);
2558
2559
TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();
2560
if (rat)
2561
{
2562
rat->notifyIllegalStaticFinalFieldModificationEvent(fe, fieldClass);
2563
}
2564
reportHookFinished(currentThread, "jitIllegalFinalFieldModification");
2565
}
2566
2567
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
2568
// JIT hook called by the VM to update the target of a MutableCallSite.
2569
void jitSetMutableCallSiteTarget(J9VMThread *vmThread, j9object_t mcs, j9object_t newTarget)
2570
{
2571
J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;
2572
TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);
2573
TR_J9VMBase *fej9 = TR_J9VMBase::get(jitConfig, vmThread);
2574
TR_RuntimeAssumptionTable *rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();
2575
2576
bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks);
2577
bool details = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHookDetails);
2578
verbose = verbose || details;
2579
2580
TR_OpaqueClassBlock *mcsClass = fej9->getObjectClass((uintptr_t)mcs);
2581
uintptr_t targetOffset = fej9->getInstanceFieldOffset(
2582
mcsClass, "target", "Ljava/lang/invoke/MethodHandle;");
2583
2584
TR::ClassTableCriticalSection commit(fej9);
2585
2586
// There are no concurrent modifications because target is only modified
2587
// while holding the CH table lock.
2588
uintptr_t prevTarget = fej9->getReferenceFieldAt((uintptr_t)mcs, targetOffset);
2589
if ((uintptr_t)newTarget == prevTarget)
2590
return; // Nothing to do.
2591
2592
// The CH table lock must be acquired before reading the cookie. Otherwise,
2593
// a nonzero value written by another thread (in the compiler's CH table
2594
// commit phase) won't necessarily be observed; and worse, if this MCS
2595
// object were first inlined in a compilation that is committing
2596
// concurrently, the following would be possible even with strong memory
2597
// ordering:
2598
//
2599
// 1. jitSetMutableCallSiteTarget() reads the cookie, which is zero, so no
2600
// assumptions will be invalidated; then
2601
//
2602
// 2. the compilation reads the MCS target during CH table commit, which
2603
// matches what it saw during inlining, so it considers its assumption
2604
// valid; then
2605
//
2606
// 3. in any order, the compilation finishes and the MCS target is updated,
2607
// resulting in a compiled body that has inlined the wrong target.
2608
2609
uintptr_t cookie = fej9->mutableCallSiteCookie((uintptr_t)mcs);
2610
if (cookie == 0)
2611
{
2612
if (verbose)
2613
{
2614
TR_VerboseLog::writeLineLocked(
2615
TR_Vlog_HD, "%p skipping nonexistent cookie", vmThread);
2616
}
2617
}
2618
else
2619
{
2620
// There may be assumptions to invalidate. Any such assumptions must be
2621
// invalidated before updating the target field. Otherwise, another
2622
// thread concurrently running JIT-compiled code where the previous
2623
// target is inlined could read the new target object from the field and
2624
// still pass the MCS target guard into the inlined body, even though the
2625
// freshly loaded target differs from the known object used during
2626
// optimization.
2627
//
2628
// While it would actually be OK to continue using the old target until
2629
// syncAll() is called, code optimized based on known object information
2630
// does not keep using the original reference it had when it was
2631
// compiled. Instead, it retrieves the reference at runtime using the
2632
// original chain of loads. The compiler will have transformed some but
2633
// not necessarily all of the uses of this reference, so if a different
2634
// reference is found at runtime, inconsistencies will result.
2635
//
2636
// For example, suppose the compiled code gets the mutable call site MCS
2637
// and then updates ((Foo)((Species_L)MCS.target).argL0).f. Making use of
2638
// the known object information, the compiler has likely improved the
2639
// code so that it stores to MCS.target.argL0.f without any casts, but
2640
// (crucially) the object reference MCS.target.argL0 is not truly
2641
// constant-folded, so it must be found by chasing pointers at runtime.
2642
// If MCS.target is changed to e.g. an instance of Species_I, and if the
2643
// optimized code is still allowed to run, then the load of argL0 will
2644
// reinterpret the bound integer as a reference, and the subsequent store
2645
// will dereference it. Kaboom!
2646
2647
if (verbose)
2648
{
2649
TR_VerboseLog::writeLineLocked(
2650
TR_Vlog_HD, "%p notifying cookie %p", vmThread, (void*)cookie);
2651
}
2652
2653
rat->notifyMutableCallSiteChangeEvent(fej9, cookie);
2654
2655
if (verbose)
2656
{
2657
TR_VerboseLog::writeLineLocked(
2658
TR_Vlog_HD, "%p finished notifying cookie %p", vmThread, (void*)cookie);
2659
}
2660
}
2661
2662
// Finally, update the target. This must be done while the CH table lock is
2663
// still held. Otherwise, it would be possible for a concurrent compilation
2664
// to inline the wrong target without invalidating its guard:
2665
//
2666
// 1. jitSetMutableCallSiteTarget() invalidates MCS target guards for this
2667
// call site and releases the CH table lock; then
2668
//
2669
// 2. the compilation gets the CH table lock and starts its CH table commit,
2670
// wherein it observes the previous target, which matches what it saw
2671
// during inlining, so it considers its assumption valid; then
2672
//
2673
// 3. finally, the target is updated.
2674
//
2675
// Note that it's fine to use a regular (non-volatile) store here. For other
2676
// threads loading the target at runtime / in the interpreter, they are not
2677
// required to see the update before syncAll() is called. For compilations
2678
// in other threads, any subsequent CH table commit is guaranteed to see the
2679
// update due to synchronization via the CH table lock.
2680
2681
targetOffset += TR::Compiler->om.objectHeaderSizeInBytes();
2682
vmThread->javaVM->memoryManagerFunctions->j9gc_objaccess_mixedObjectStoreObject(
2683
vmThread, mcs, targetOffset, newTarget, 0);
2684
}
2685
#endif
2686
2687
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
2688
static void jitHookInterruptCompilation(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
2689
{
2690
MM_InterruptCompilationEvent * interruptCompilationEvent = (MM_InterruptCompilationEvent *)eventData;
2691
J9VMThread * vmThread = interruptCompilationEvent->currentThread;
2692
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
2693
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2694
2695
//compInfo->setAllCompilationsShouldBeInterrupted();
2696
compInfo->getPersistentInfo()->setGCwillBlockOnClassUnloadMonitor();
2697
}
2698
#endif /* defined (J9VM_GC_DYNAMIC_CLASS_UNLOADING)*/
2699
2700
// jitUpdateMethodOverride is called indirectly from updateCHTable
2701
//
2702
void jitUpdateMethodOverride(J9VMThread * vmThread, J9Class * cl, J9Method * overriddenMethod, J9Method * overriddingMethod)
2703
{
2704
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
2705
2706
TR_FrontEnd * vm = TR_J9VMBase::get(jitConfig, vmThread);
2707
2708
PORT_ACCESS_FROM_PORT(jitConfig->javaVM->portLibrary);
2709
2710
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
2711
2712
// Pretend that we are always running smp; current implementation
2713
// of virtual guard patching (on ia32/ppc) ignore it. Since patching
2714
// is infrequent anyway probably it is not worth maintaining two versions
2715
// of code for patching.
2716
// On Linux, get_number_CPUs calls sysconfig which has to generate and
2717
// parse /proc/stat (slow) -- if re-enabling, cache the isSMP flag
2718
// rather than querying each time.
2719
//
2720
bool isSMP = 1; // conservative
2721
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))
2722
{
2723
jitAcquireClassTableMutex(vmThread);
2724
compInfo->getPersistentInfo()->getPersistentCHTable()->methodGotOverridden(
2725
vm, compInfo->persistentMemory(), (TR_OpaqueMethodBlock *) overriddingMethod, (TR_OpaqueMethodBlock *) overriddenMethod, isSMP);
2726
jitReleaseClassTableMutex(vmThread);
2727
}
2728
}
2729
2730
/* updateOverriddenFlag() replaces jitUpdateInlineAttribute. See Design 1812 */
2731
2732
static void updateOverriddenFlag( J9VMThread *vm , J9Class *cl)
2733
{
2734
2735
static const char *traceIt = 0; // feGetEnv("TR_TraceUpdateOverridenFlag"); //this trace should only be enabled if it is needed
2736
2737
J9ROMClass *ROMCl = cl->romClass;
2738
2739
if(ROMCl->modifiers & J9AccInterface ) //Do nothing if interface
2740
return;
2741
2742
int32_t classDepth = J9CLASS_DEPTH(cl) - 1;
2743
2744
if (classDepth >= 0) // Do nothing if we don't have a superclass
2745
{
2746
J9Class * superCl = cl->superclasses[classDepth];
2747
2748
J9VTableHeader * superVTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(superCl);
2749
intptr_t methodCount = (intptr_t)superVTableHeader->size;
2750
J9Method ** superVTable = J9VTABLE_FROM_HEADER(superVTableHeader);
2751
J9Method ** subVTable = J9VTABLE_FROM_RAM_CLASS(cl);
2752
2753
intptr_t methodIndex=0;
2754
2755
while(methodCount--)
2756
{
2757
J9Method * superMethod = *superVTable++;
2758
J9Method * subMethod = *subVTable++;
2759
2760
J9ROMMethod *subROM = J9_ROM_METHOD_FROM_RAM_METHOD(subMethod);
2761
J9ROMMethod *superROM = J9_ROM_METHOD_FROM_RAM_METHOD(superMethod);
2762
2763
bool methodModifiersAreSafe = (subROM->modifiers & J9AccForwarderMethod) && !((subROM->modifiers & J9AccSynchronized) || (subROM->modifiers & J9AccStrict) || (subROM->modifiers & J9AccNative)) ;
2764
2765
if (traceIt)
2766
{
2767
char *classNameChars = (char *)J9UTF8_DATA(J9ROMCLASS_CLASSNAME(ROMCl));
2768
int32_t classNameLen = (int32_t)J9UTF8_LENGTH(J9ROMCLASS_CLASSNAME(ROMCl));
2769
char *superSignature = (char*)J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod)));
2770
int32_t superSigLen = (int32_t)J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod)));
2771
char *superName = (char*)J9UTF8_DATA(J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod)));
2772
int32_t superNameLen = (int32_t) J9UTF8_LENGTH(J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod)));
2773
char *subSignature = (char*)J9UTF8_DATA(J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(subMethod)));
2774
int32_t subSigLen = (int32_t)J9UTF8_LENGTH(J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(subMethod)));
2775
char *subName = (char*)J9UTF8_DATA(J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(subMethod)));
2776
int32_t subNameLen = (int32_t)J9UTF8_LENGTH(J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(subMethod)));
2777
2778
printf("class = %.*s superSignature = %.*s, superName = %.*s, supermodifers = %x , subSignature = %.*s, subName = %.*s, submodifiers = %x subMethod = %p methodModifiersAreSafe = %d\n"
2779
,classNameLen,classNameChars,superSigLen,superSignature,superNameLen,superName,(int)superROM->modifiers,subSigLen,subSignature,subNameLen,subName,(int)subROM->modifiers,subMethod,methodModifiersAreSafe );
2780
printf("For subROM %p:\n",subROM);
2781
2782
if(subROM->modifiers & J9AccAbstract) printf("\tsubMethod is J9AccAbstract (%x)\n",J9AccAbstract);
2783
if(subROM->modifiers & J9AccAnnotation) printf("\tsubMethod is J9AccAnnotation\n");
2784
if(subROM->modifiers & J9AccBridge) printf("\tsubMethod is J9AccBridge\n");
2785
if(subROM->modifiers & J9AccEmptyMethod) printf("\tsubMethod is J9AccEmptyMethod\n");
2786
if(subROM->modifiers & J9AccEnum) printf("\tsubMethod is J9AccEnum\n");
2787
if(subROM->modifiers & J9AccFinal) printf("\tsubMethod is J9AccFinal\n");
2788
if(subROM->modifiers & J9AccForwarderMethod) printf("\tsubMethod is J9AccForwarderMethod\n");
2789
if(subROM->modifiers & J9AccGetterMethod) printf("\tsubMethod is J9AccGetterMethod\n");
2790
if(subROM->modifiers & J9AccInterface) printf("\tsubMethod is J9AccInterface\n");
2791
if(subROM->modifiers & J9AccMethodCallerSensitive) printf("\tsubMethod is J9AccMethodCallerSensitive\n");
2792
if(subROM->modifiers & J9AccMethodFrameIteratorSkip) printf("\tsubMethod is J9AccMethodFrameIteratorSkip\n");
2793
if(subROM->modifiers & J9AccMethodHasBackwardBranches) printf("\tsubMethod is J9AccMethodHasBackwardBranches\n");
2794
if(subROM->modifiers & J9AccMethodHasDebugInfo) printf("\tsubMethod is J9AccMethodHasDebugInfo\n");
2795
if(subROM->modifiers & J9AccMethodHasDefaultAnnotation) printf("\tsubMethod is J9AccMethodHasDefaultAnnotation\n");
2796
if(subROM->modifiers & J9AccMethodHasExceptionInfo) printf("\tsubMethod is J9AccMethodHasExceptionInfo\n");
2797
if(subROM->modifiers & J9AccMethodHasGenericSignature) printf("\tsubMethod is J9AccMethodHasGenericSignature\n");
2798
if(subROM->modifiers & J9AccMethodHasMethodAnnotations) printf("\tsubMethod is J9AccMethodHasMethodAnnotations\n");
2799
if(subROM->modifiers & J9AccMethodHasParameterAnnotations) printf("\tsubMethod is J9AccMethodHasParameterAnnotations\n");
2800
if(subROM->modifiers & J9AccMethodHasStackMap) printf("\tsubMethod is J9AccMethodHasStackMap\n");
2801
if(subROM->modifiers & J9AccMethodObjectConstructor) printf("\tsubMethod is J9AccMethodObjectConstructor\n");
2802
if(subROM->modifiers & J9AccMethodReturn0) printf("\tsubMethod is J9AccMethodReturn0\n");
2803
if(subROM->modifiers & J9AccMethodReturn1) printf("\tsubMethod is J9AccMethodReturn1\n");
2804
if(subROM->modifiers & J9AccMethodReturn2) printf("\tsubMethod is J9AccMethodReturn2\n");
2805
if(subROM->modifiers & J9AccMethodReturnA) printf("\tsubMethod is J9AccMethodReturnA\n");
2806
if(subROM->modifiers & J9AccMethodReturnD) printf("\tsubMethod is J9AccMethodReturnD\n");
2807
if(subROM->modifiers & J9AccMethodReturnF) printf("\tsubMethod is J9AccMethodReturnF\n");
2808
if(subROM->modifiers & J9AccMethodReturnMask) printf("\tsubMethod is J9AccMethodReturnMask\n");
2809
if(subROM->modifiers & J9AccMethodReturnShift) printf("\tsubMethod is J9AccMethodReturnShift\n");
2810
if(subROM->modifiers & J9AccMethodVTable) printf("\tsubMethod is J9AccMethodVTable\n");
2811
if(subROM->modifiers & J9AccNative) printf("\tsubMethod is J9AccNative\n");
2812
if(subROM->modifiers & J9AccPrivate) printf("\tsubMethod is J9AccPrivate\n");
2813
if(subROM->modifiers & J9AccProtected) printf("\tsubMethod is J9AccProtected\n");
2814
if(subROM->modifiers & J9AccPublic) printf("\tsubMethod is J9AccPublic\n");
2815
if(subROM->modifiers & J9AccStatic) printf("\tsubMethod is J9AccStatic\n");
2816
if(subROM->modifiers & J9AccStrict) printf("\tsubMethod is J9AccStrict\n");
2817
if(subROM->modifiers & J9AccSuper) printf("\tsubMethod is J9AccSuper\n");
2818
if(subROM->modifiers & J9AccSynchronized) printf("\tsubMethod is J9AccSynchronized\n");
2819
if(subROM->modifiers & J9AccSynthetic) printf("\tsubMethod is J9AccSynthetic\n");
2820
if(subROM->modifiers & J9AccTransient) printf("\tsubMethod is J9AccTransient\n");
2821
if(subROM->modifiers & J9AccVarArgs) printf("\tsubMethod is J9AccVarArgs\n");
2822
if(subROM->modifiers & J9AccVolatile) printf("\tsubMethod is J9AccVolatile\n");
2823
2824
printf("For superROM %p:\n",superROM);
2825
2826
if(superROM->modifiers & J9AccAbstract) printf("\tsuperMethod is J9AccAbstract\n");
2827
if(superROM->modifiers & J9AccAnnotation) printf("\tsuperMethod is J9AccAnnotationt\n");
2828
if(superROM->modifiers & J9AccBridge) printf("\tsuperMethod is J9AccBridge\n");
2829
if(superROM->modifiers & J9AccEmptyMethod) printf("\tsuperMethod is J9AccEmptyMethod\n");
2830
if(superROM->modifiers & J9AccEnum) printf("\tsuperMethod is J9AccEnum\n");
2831
if(superROM->modifiers & J9AccFinal) printf("\tsuperMethod is J9AccFinal\n");
2832
if(superROM->modifiers & J9AccForwarderMethod) printf("\tsuperMethod is J9AccForwarderMethod\n");
2833
if(superROM->modifiers & J9AccGetterMethod) printf("\tsuperMethod is J9AccGetterMethod\n");
2834
if(superROM->modifiers & J9AccInterface) printf("\tsuperMethod is J9AccInterface\n");
2835
if(superROM->modifiers & J9AccMethodCallerSensitive) printf("\tsuperMethod is J9AccMethodCallerSensitive\n");
2836
if(superROM->modifiers & J9AccMethodFrameIteratorSkip) printf("\tsuperMethod is J9AccMethodFrameIteratorSkip\n");
2837
if(superROM->modifiers & J9AccMethodHasBackwardBranches) printf("\tsuperMethod is J9AccMethodHasBackwardBranches\n");
2838
if(superROM->modifiers & J9AccMethodHasDebugInfo) printf("\tsuperMethod is J9AccMethodHasDebugInfo\n");
2839
if(superROM->modifiers & J9AccMethodHasDefaultAnnotation) printf("\tsuperMethod is J9AccMethodHasDefaultAnnotation\n");
2840
if(superROM->modifiers & J9AccMethodHasExceptionInfo) printf("\tsuperMethod is J9AccMethodHasExceptionInfo\n");
2841
if(superROM->modifiers & J9AccMethodHasGenericSignature) printf("\tsuperMethod is J9AccMethodHasGenericSignature\n");
2842
if(superROM->modifiers & J9AccMethodHasMethodAnnotations) printf("\tsuperMethod is J9AccMethodHasMethodAnnotations\n");
2843
if(superROM->modifiers &J9AccMethodHasParameterAnnotations) printf("\tsuperMethod is J9AccMethodHasParameterAnnotations\n");
2844
if(superROM->modifiers & J9AccMethodHasStackMap) printf("\tsuperMethod is J9AccMethodHasStackMap\n");
2845
if(superROM->modifiers & J9AccMethodObjectConstructor) printf("\tsuperMethod is J9AccMethodObjectConstructor\n");
2846
if(superROM->modifiers & J9AccMethodReturn0) printf("\tsuperMethod is J9AccMethodReturn0\n");
2847
if(superROM->modifiers & J9AccMethodReturn1) printf("\tsuperMethod is J9AccMethodReturn1\n");
2848
if(superROM->modifiers & J9AccMethodReturn2) printf("\tsuperMethod is J9AccMethodReturn2\n");
2849
if(superROM->modifiers & J9AccMethodReturnA) printf("\tsuperMethod is J9AccMethodReturnA\n");
2850
if(superROM->modifiers & J9AccMethodReturnD) printf("\tsuperMethod is J9AccMethodReturnD\n");
2851
if(superROM->modifiers & J9AccMethodReturnF) printf("\tsuperMethod is J9AccMethodReturnF\n");
2852
if(superROM->modifiers & J9AccMethodReturnMask) printf("\tsuperMethod is J9AccMethodReturnMask\n");
2853
if(superROM->modifiers & J9AccMethodReturnShift) printf("\tsuperMethod is J9AccMethodReturnShift\n");
2854
if(superROM->modifiers & J9AccMethodVTable) printf("\tsuperMethod is J9AccMethodVTable\n");
2855
if(superROM->modifiers & J9AccNative) printf("\tsuperMethod is J9AccNative\n");
2856
if(superROM->modifiers & J9AccPrivate) printf("\tsuperMethod is J9AccPrivate\n");
2857
if(superROM->modifiers & J9AccProtected) printf("\tsuperMethod is J9AccProtected\n");
2858
if(superROM->modifiers & J9AccPublic) printf("\tsuperMethod is J9AccPublic\n");
2859
if(superROM->modifiers & J9AccStatic) printf("\tsuperMethod is J9AccStatic\n");
2860
if(superROM->modifiers & J9AccStrict) printf("\tsuperMethod is J9AccStrict\n");
2861
if(superROM->modifiers & J9AccSuper) printf("\tsuperMethod is J9AccSuper\n");
2862
if(superROM->modifiers & J9AccSynchronized) printf("\tsuperMethod is J9AccSynchronized\n");
2863
if(superROM->modifiers & J9AccSynthetic) printf("\tsuperMethod is J9AccSynthetic\n");
2864
if(superROM->modifiers & J9AccTransient) printf("\tsuperMethod is J9AccTransient\n");
2865
if(superROM->modifiers & J9AccVarArgs) printf("\tsuperMethod is J9AccVarArgs\n");
2866
if(superROM->modifiers & J9AccVolatile) printf("\tsuperMethod is J9AccVolatile\n");
2867
2868
fflush(stdout);
2869
}
2870
2871
if((subMethod != superMethod) && methodModifiersAreSafe && (J9_BYTECODE_END_FROM_ROM_METHOD(subROM) - J9_BYTECODE_START_FROM_ROM_METHOD(subROM))>0 ) //If the j9methods don't match, method has been overridden
2872
{
2873
if (traceIt)
2874
{
2875
printf("For submethod %p, trying to match signature for overridden bit\n",subMethod);
2876
fflush(stdout);
2877
}
2878
2879
2880
const uint8_t * _code = subMethod->bytecodes; //a pointer to bytecodes
2881
bool matches=false;
2882
bool finishedArgs = false;
2883
int32_t curLocalSize;
2884
int32_t i = 0;
2885
uint16_t cpIndex = 0;
2886
for (int32_t nextLocalIndex = 0; !matches && !finishedArgs && nextLocalIndex<255; nextLocalIndex += curLocalSize)
2887
{
2888
curLocalSize = 1;
2889
switch (TR_J9ByteCodeIterator::convertOpCodeToByteCodeEnum(_code[i++]))
2890
{
2891
case J9BCaload0:
2892
finishedArgs = (nextLocalIndex != 0);
2893
break;
2894
case J9BClload1: case J9BCdload1:
2895
curLocalSize = 2;
2896
// fall through
2897
case J9BCiload1: case J9BCfload1: case J9BCaload1:
2898
finishedArgs = (nextLocalIndex != 1);
2899
break;
2900
case J9BClload2: case J9BCdload2:
2901
curLocalSize = 2;
2902
// fall through
2903
case J9BCiload2: case J9BCfload2: case J9BCaload2:
2904
finishedArgs = (nextLocalIndex != 2);
2905
break;
2906
case J9BClload3: case J9BCdload3:
2907
curLocalSize = 2;
2908
// fall through
2909
case J9BCiload3: case J9BCfload3: case J9BCaload3:
2910
finishedArgs = (nextLocalIndex != 3);
2911
break;
2912
case J9BClload: case J9BCdload:
2913
curLocalSize = 2;
2914
// fall through
2915
case J9BCiload: case J9BCfload: case J9BCaload:
2916
finishedArgs = (nextLocalIndex != _code[i++]);
2917
break;
2918
case J9BCinvokespecial:
2919
cpIndex = BC_OP_U16(&_code[i]); //will need to compare signature with superMethod.
2920
matches=true;
2921
break;
2922
case J9BCinvokespecialsplit:
2923
cpIndex = *(U_16*)(J9ROMCLASS_SPECIALSPLITMETHODREFINDEXES(ROMCl) + BC_OP_U16(&_code[i])); //will need to compare signature with superMethod.
2924
matches=true;
2925
break;
2926
default:
2927
finishedArgs = true;
2928
break;
2929
}
2930
}
2931
2932
J9UTF8 * callSignature;
2933
J9UTF8 * callName;
2934
if(matches) //so far we are matching our pattern
2935
{
2936
if (traceIt)
2937
{
2938
printf("For submethod %p, pattern matches after bc walk\n",subMethod);
2939
fflush(stdout);
2940
}
2941
2942
2943
J9ROMFieldRef * ref1 = &(((J9ROMFieldRef *)((char *)ROMCl+sizeof(J9ROMClass)))[cpIndex]);
2944
J9ROMNameAndSignature *nameAndSignature = J9ROMFIELDREF_NAMEANDSIGNATURE(ref1); //this isn't a string its a struct.
2945
callSignature = J9ROMNAMEANDSIGNATURE_SIGNATURE(nameAndSignature);
2946
callName = J9ROMNAMEANDSIGNATURE_NAME(nameAndSignature);
2947
2948
J9UTF8 *superSignature = J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod));
2949
J9UTF8 *superName = J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(superMethod));
2950
2951
if( J9UTF8_LENGTH(superSignature) != J9UTF8_LENGTH(callSignature)
2952
|| J9UTF8_LENGTH(superName) != J9UTF8_LENGTH(callName)
2953
|| !(strncmp((char *)J9UTF8_DATA(superSignature),(char *)J9UTF8_DATA(callSignature),J9UTF8_LENGTH(superSignature))==0)
2954
|| !(strncmp((char *)J9UTF8_DATA(superName),(char *)J9UTF8_DATA(callName),J9UTF8_LENGTH(superSignature))==0) )
2955
2956
{
2957
if (traceIt)
2958
{
2959
printf("For submethod %p,signature compare fails after bc walk superSiglen = %d subsiglen = %d supernamelen = %d subnamelen =%d\n"
2960
,subMethod,J9UTF8_LENGTH(superSignature),J9UTF8_LENGTH(callSignature),J9UTF8_LENGTH(superName),J9UTF8_LENGTH(callName));
2961
fflush(stdout);
2962
}
2963
matches=false;
2964
}
2965
else
2966
{
2967
uint8_t opcode = _code[i+2]; //an invokespecial takes up 3 bytes.. we point at second byte after for loop, so increment by 2
2968
TR_J9ByteCode bc = TR_J9ByteCodeIterator::convertOpCodeToByteCodeEnum(opcode);
2969
if(bc != J9BCgenericReturn || &(_code[i+3]) != J9_BYTECODE_END_FROM_ROM_METHOD(subROM)) //second condition ensures that the return is the last bytecode. See defect 148222.
2970
{
2971
if (traceIt)
2972
{
2973
printf("For submethod %p,signature compare fails after bc walk bc !=genericReturn at i(%d)+2\n", subMethod, i);
2974
fflush(stdout);
2975
}
2976
matches=false;
2977
}
2978
}
2979
}
2980
2981
if(!matches) //matches is false if method is overridden.
2982
{
2983
jitUpdateMethodOverride(vm, cl, superMethod,subMethod);
2984
vm->javaVM->internalVMFunctions->atomicOrIntoConstantPool(vm->javaVM, superMethod,J9_STARTPC_METHOD_IS_OVERRIDDEN);
2985
2986
if (traceIt)
2987
{
2988
printf("For submethod %p, pattern does not match after sig compares.\n",subMethod);
2989
fflush(stdout);
2990
}
2991
2992
2993
//Updating all grandparent classes overridden bits
2994
J9Class * tempsuperCl;
2995
J9VTableHeader * tempsuperVTableHeader;
2996
J9Method ** tempsuperVTable;
2997
J9Method * tempsuperMethod;
2998
intptr_t tempmethodCount;
2999
for(int32_t k=classDepth-1;k>=0;k--)
3000
{
3001
3002
tempsuperCl = cl->superclasses[k];
3003
tempsuperVTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(tempsuperCl);
3004
tempmethodCount = (intptr_t)tempsuperVTableHeader->size;
3005
3006
if(methodIndex>= tempmethodCount) //we are outside the grandparent's vft slots
3007
break;
3008
3009
tempsuperVTable = J9VTABLE_FROM_HEADER(tempsuperVTableHeader);
3010
tempsuperVTable = tempsuperVTable + methodIndex;
3011
tempsuperMethod= *tempsuperVTable;
3012
jitUpdateMethodOverride(vm, cl, tempsuperMethod,subMethod);
3013
vm->javaVM->internalVMFunctions->atomicOrIntoConstantPool(vm->javaVM, tempsuperMethod,J9_STARTPC_METHOD_IS_OVERRIDDEN);
3014
}
3015
}
3016
else
3017
{
3018
if (traceIt)
3019
{
3020
printf("For submethod %p, determined it is not overridden by bytecode walk and signature compare\n",subMethod);
3021
fflush(stdout);
3022
}
3023
}
3024
}
3025
else if (superMethod != subMethod) // we don't have bytecodes, but the j9methods don't match, so set the overridden bit anyways
3026
{
3027
jitUpdateMethodOverride(vm, cl, superMethod,subMethod);
3028
vm->javaVM->internalVMFunctions->atomicOrIntoConstantPool(vm->javaVM, superMethod,J9_STARTPC_METHOD_IS_OVERRIDDEN);
3029
3030
if (traceIt)
3031
{
3032
printf("For submethod %p, j9methods don't match. Setting overridden bit. endbc - startbc = %" OMR_PRIdPTR " methodmodifiersaresafe = %d\n",subMethod,(J9_BYTECODE_END_FROM_ROM_METHOD(subROM) - J9_BYTECODE_START_FROM_ROM_METHOD(subROM)),methodModifiersAreSafe);
3033
fflush(stdout);
3034
}
3035
3036
3037
//Updating all grandparent classes overridden bits
3038
J9Class * tempsuperCl;
3039
J9VTableHeader * tempsuperVTableHeader;
3040
J9Method ** tempsuperVTable;
3041
J9Method * tempsuperMethod;
3042
intptr_t tempmethodCount;
3043
for(int32_t k=classDepth-1;k>=0;k--)
3044
{
3045
3046
tempsuperCl = cl->superclasses[k];
3047
tempsuperVTableHeader = J9VTABLE_HEADER_FROM_RAM_CLASS(tempsuperCl);
3048
tempmethodCount = (intptr_t)tempsuperVTableHeader->size;
3049
3050
if(methodIndex >= tempmethodCount) //we are outside the grandparent's vft slots
3051
break;
3052
3053
tempsuperVTable = J9VTABLE_FROM_HEADER(tempsuperVTableHeader);
3054
tempsuperVTable = tempsuperVTable + methodIndex;
3055
tempsuperMethod= *tempsuperVTable;
3056
3057
jitUpdateMethodOverride(vm, cl, tempsuperMethod,subMethod);
3058
vm->javaVM->internalVMFunctions->atomicOrIntoConstantPool(vm->javaVM, tempsuperMethod,J9_STARTPC_METHOD_IS_OVERRIDDEN);
3059
}
3060
3061
}
3062
3063
methodIndex++;
3064
}
3065
}
3066
}
3067
3068
static bool updateCHTable(J9VMThread * vmThread, J9Class * cl)
3069
{
3070
typedef void JIT_METHOD_OVERRIDE_UPDATE(J9VMThread *, J9Class *, J9Method *, J9Method *);
3071
3072
JIT_METHOD_OVERRIDE_UPDATE * callBack = jitUpdateMethodOverride;
3073
bool updateFailed = false;
3074
3075
{
3076
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
3077
3078
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
3079
3080
#if defined(J9VM_OPT_JITSERVER)
3081
TR_ASSERT_FATAL(compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER, "updateCHTable() should not be called on JITServer!\n");
3082
#endif
3083
3084
TR_PersistentCHTable * table = 0;
3085
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))
3086
table = compInfo->getPersistentInfo()->getPersistentCHTable();
3087
3088
TR_J9VMBase *vm = TR_J9VMBase::get(jitConfig, vmThread);
3089
TR_OpaqueClassBlock *clazz = ((TR_J9VMBase *)vm)->convertClassPtrToClassOffset(cl);
3090
3091
char *name; int32_t len;
3092
bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassLoading);
3093
if (p)
3094
{
3095
name = vm->getClassNameChars(clazz, len);
3096
TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "--updt-- %.*s\n", len, name);
3097
}
3098
3099
int32_t classDepth = J9CLASS_DEPTH(cl) - 1;
3100
if (classDepth >= 0)
3101
{
3102
J9Class * superCl = cl->superclasses[classDepth];
3103
superCl->classDepthAndFlags |= J9AccClassHasBeenOverridden;
3104
3105
TR_OpaqueClassBlock *superClazz = ((TR_J9VMBase *)vm)->convertClassPtrToClassOffset(superCl);
3106
if (p)
3107
{
3108
name = vm->getClassNameChars(superClazz, len);
3109
TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "\textending %.*s\n", len, name);
3110
}
3111
if (table)
3112
{
3113
if (!table->classGotExtended(vm, compInfo->persistentMemory(), superClazz, clazz))
3114
updateFailed = true;
3115
}
3116
for (J9ITable * iTableEntry = (J9ITable *)cl->iTable; iTableEntry; iTableEntry = iTableEntry->next)
3117
{
3118
superCl = iTableEntry->interfaceClass;
3119
if (superCl != cl)
3120
{
3121
superCl->classDepthAndFlags |= J9AccClassHasBeenOverridden;
3122
superClazz = ((TR_J9VMBase *)vm)->convertClassPtrToClassOffset(superCl);
3123
if (p)
3124
{
3125
name = vm->getClassNameChars(superClazz, len);
3126
TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "\textending interface %.*s\n", len, name);
3127
}
3128
if (table)
3129
{
3130
if (!table->classGotExtended(vm, compInfo->persistentMemory(), superClazz, clazz))
3131
updateFailed = true;
3132
}
3133
}
3134
}
3135
}
3136
}
3137
// method override
3138
if(!TR::Options::getCmdLineOptions()->getOption(TR_DisableNewMethodOverride))
3139
updateOverriddenFlag(vmThread,cl);
3140
else
3141
jitUpdateInlineAttribute(vmThread, cl, (void *)callBack);
3142
3143
3144
return !updateFailed;
3145
}
3146
3147
void turnOffInterpreterProfiling(J9JITConfig *jitConfig);
3148
3149
3150
3151
/**
3152
* @brief A function to get the available virtual memory.
3153
*
3154
* Note: Only supported for 32 bit Windows in Production
3155
* Code currently runs under PROD_WITH_ASSUMES in 31/32 bit Linux and 31 bit z/OS but
3156
* returns -1 (error) to prevent any decision making
3157
*
3158
* @param compInfo TR::CompilationInfo needed for getting Port Access
3159
* @param vmThread J9VMThread needed for tracepoints
3160
* @param availableVirtualMemoryMB Pointer to availableVirtualMemoryKB
3161
* @return 0 if success, -1 if error
3162
*/
3163
int32_t getAvailableVirtualMemoryMB(TR::CompilationInfo *compInfo, J9VMThread *vmThread, uint32_t *availableVirtualMemoryMB)
3164
{
3165
TRC_JIT_getAvailableVirtualMemoryMBEnter(vmThread);
3166
#if defined(TR_TARGET_32BIT)
3167
3168
#if defined(WINDOWS)
3169
J9MemoryInfo memInfo;
3170
PORT_ACCESS_FROM_JITCONFIG(compInfo->getJITConfig());
3171
if (j9sysinfo_get_memory_info(&memInfo) != 0 ||
3172
memInfo.availVirtual == J9PORT_MEMINFO_NOT_AVAILABLE)
3173
{
3174
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3175
return -1; // error case
3176
}
3177
*availableVirtualMemoryMB = (uint32_t)(memInfo.availVirtual >> 20); // conversion to uint32_t is safe on 32-bit OS
3178
3179
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJitMemory))
3180
{
3181
uint32_t totalVirtualMemoryMB = (uint32_t)(memInfo.totalVirtual >> 20);
3182
uint32_t virtualMemoryUsedMB = totalVirtualMemoryMB - *availableVirtualMemoryMB;
3183
3184
TR_VerboseLog::writeLineLocked(TR_Vlog_MEMORY, "Virtual Memory Used: %d MB out of %d MB", virtualMemoryUsedMB, totalVirtualMemoryMB);
3185
}
3186
3187
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3188
return 0;
3189
#elif defined(LINUX)
3190
3191
// Having TR::Options::_userSpaceVirtualMemoryMB < 1 means to determine the
3192
// userspace size dynamically. However this isn't implemented on Linux so
3193
// the function returns -1
3194
if (TR::Options::_userSpaceVirtualMemoryMB < 0)
3195
{
3196
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3197
return -1;
3198
}
3199
3200
uint32_t totalVirtualMemoryMB = (uint32_t)TR::Options::_userSpaceVirtualMemoryMB;
3201
3202
/*
3203
See http://man7.org/linux/man-pages/man5/proc.5.html or run "man proc" for information on the
3204
/proc pseudo filesystem. The file we're using to get the virtual memory information
3205
is /proc/self/status. A small glimpse into the file:
3206
3207
...
3208
Utrace: 0
3209
FDSize: 256
3210
Groups: 476297 478112 819790 837093 887132 903597
3211
VmPeak: 99044 kB
3212
VmSize: 99044 kB
3213
VmLck: 0 kB
3214
...
3215
3216
We are interested in the VmSize field
3217
*/
3218
3219
::FILE* statFile = fopen("/proc/self/status", "r");
3220
if (statFile)
3221
{
3222
static const int bufferSize = 1024;
3223
char buffer[bufferSize];
3224
bool foundVirtualMemory = false;
3225
int bufferStartIndex = 0;
3226
3227
while (!foundVirtualMemory && !feof(statFile))
3228
{
3229
if (!fgets(buffer,bufferSize,statFile))
3230
break;
3231
3232
if (buffer[0] == 'V')
3233
{
3234
/* Check if we have the right field, namely "VmSize" */
3235
if (buffer[1] == 'm'
3236
&& buffer[2] == 'S'
3237
&& buffer[3] == 'i'
3238
&& buffer[4] == 'z'
3239
&& buffer[5] == 'e'
3240
&& buffer[6] == ':')
3241
{
3242
int bufferIndex = 0;
3243
3244
/* skip whitespace until we hit the first number */
3245
while (bufferIndex < bufferSize && buffer[bufferIndex] != '\0' && (buffer[bufferIndex] < '0' || buffer[bufferIndex] > '9'))
3246
bufferIndex++;
3247
3248
/* Out of bounds check */
3249
if (bufferIndex == bufferSize || buffer[bufferIndex] == '\0')
3250
break;
3251
3252
bufferStartIndex = bufferIndex;
3253
3254
/* Determine the end of the number */
3255
while (bufferIndex < bufferSize && buffer[bufferIndex] >= '0' && buffer[bufferIndex] <= '9')
3256
bufferIndex++;
3257
3258
/* Bounds and sanity check */
3259
if ((bufferIndex + 2) < bufferSize
3260
&& (bufferIndex - bufferStartIndex + 1) < 9
3261
&& buffer[bufferIndex] == ' '
3262
&& buffer[bufferIndex + 1] == 'k'
3263
&& buffer[bufferIndex + 2] == 'B')
3264
{
3265
buffer[bufferIndex] = '\0';
3266
foundVirtualMemory = true;
3267
}
3268
else
3269
break;
3270
}
3271
} // if (buffer[0] == 'V')
3272
} // while(!feof(statFile) && !foundVirtualMemory && !error)
3273
3274
fclose(statFile);
3275
3276
if (!foundVirtualMemory)
3277
{
3278
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3279
return -1; // error case
3280
}
3281
3282
uint32_t virtualMemoryUsedMB = (uint32_t)(atoi(&buffer[bufferStartIndex]) >> 10);
3283
3284
// Check if amount read from the file is less than or equal to the total virtual memory
3285
if (totalVirtualMemoryMB >= virtualMemoryUsedMB)
3286
*availableVirtualMemoryMB = totalVirtualMemoryMB - virtualMemoryUsedMB;
3287
else
3288
{
3289
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3290
return -1; // error case
3291
}
3292
3293
// Always return -1 to test this code out
3294
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3295
if (TR::Options::getCmdLineOptions()->getOption(TR_EnableLowerCompilationLimitsDecisionMaking))
3296
return 0;
3297
else
3298
return -1;
3299
3300
} // if (statFile)
3301
else
3302
{
3303
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3304
return -1; // error case
3305
}
3306
3307
#elif defined(J9ZOS390)
3308
3309
/*
3310
3311
In 31 bit z/OS, the address space is structured as follows:
3312
3313
LOCAL STORAGE MAP
3314
___________________________
3315
| |80000000 <- Top of Ext. Private
3316
| Extended |
3317
| LSQA/SWA/229/230 |80000000 <- Max Ext. User Region Address
3318
|___________________________|77636000 <- ELSQA Bottom
3319
| |
3320
| (Free Extended Storage) |
3321
|___________________________|289B8000 <- Ext. User Region Top
3322
| |
3323
| Extended User Region |
3324
|___________________________|25200000 <- Ext. User Region Start
3325
: :
3326
: Extended Global Storage :
3327
=======================================<- 16M Line
3328
: Global Storage :
3329
:___________________________: 900000 <- Top of Private
3330
| |
3331
| LSQA/SWA/229/230 | 900000 <- Max User Region Address
3332
|___________________________| 821000 <- LSQA Bottom
3333
| |
3334
| (Free Storage) |
3335
|___________________________| 4B000 <- User Region Top
3336
| |
3337
| User Region |
3338
|___________________________| 6000 <- User Region Start
3339
: System Storage :
3340
:___________________________: 0
3341
3342
The exact addresses may vary from system to system (with the exception of the "Top of Private" and "Top of Ext. Private"
3343
which generally stay the same). The System Storage, LSQA, Global Storage, Extended Global Storage, and Extended LSQA cannot be
3344
allocated. Thus the total userspace available can be approximated by doing:
3345
(Max Ext. User Region Address - (Ext. User Region Start - Max User Region Address))
3346
3347
The amount of memory used can be determined by the __heaprpt() function.
3348
3349
*/
3350
3351
// Determine how much memory is being used
3352
hreport_t heapReport;
3353
3354
if (__heaprpt(&heapReport) != 0)
3355
{
3356
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3357
return -1; // error case
3358
}
3359
3360
uint32_t virtualMemoryUsedMB = (uint32_t)(heapReport.__uheap_bytes_alloc >> 20);
3361
3362
// Determine how much memory is available
3363
if (TR::Options::_userSpaceVirtualMemoryMB > 0)
3364
{
3365
if (TR::Options::_userSpaceVirtualMemoryMB >= virtualMemoryUsedMB)
3366
*availableVirtualMemoryMB = (uint32_t)TR::Options::_userSpaceVirtualMemoryMB - virtualMemoryUsedMB;
3367
else
3368
{
3369
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3370
return -1;
3371
}
3372
}
3373
else // Use Dynamically determined user space
3374
{
3375
// A pointer to the current ASCB is located at offset PSAAOLD in the PSA
3376
void *ascb = (void *)(*((uint32_t *)PSAAOLD));
3377
3378
// A pointer to the LDA is located at offset ASCBLDA in the ASCB
3379
struct LDA *lda = (struct LDA *)(*((uint32_t *)((uint32_t)ascb + ASCBLDA)));
3380
3381
if (!lda)
3382
{
3383
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3384
return -1;
3385
}
3386
3387
// Determine how much of the 2 GB address space is user space
3388
void *maxUserRegionAddress = (void*)((uint32_t)(lda->strta) + lda->siza);
3389
void *maxExtUserRegionAddress = (void*)((uint32_t)(lda->estra) + lda->esiza);
3390
uint32_t totalVirtualMemoryMB = ((uint32_t)maxExtUserRegionAddress - ((uint32_t)(lda->estra) - (uint32_t)maxUserRegionAddress)) >> 20;
3391
3392
if (totalVirtualMemoryMB >= virtualMemoryUsedMB)
3393
*availableVirtualMemoryMB = totalVirtualMemoryMB - virtualMemoryUsedMB;
3394
else
3395
{
3396
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3397
return -1;
3398
}
3399
}
3400
3401
// Always return -1 to test this code out
3402
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3403
if (TR::Options::getCmdLineOptions()->getOption(TR_EnableLowerCompilationLimitsDecisionMaking))
3404
return 0;
3405
else
3406
return -1;
3407
3408
#else // Unsupported platforms
3409
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3410
return -1;
3411
#endif
3412
3413
#else // Not 32 bit
3414
TRC_JIT_getAvailableVirtualMemoryMBExit(vmThread);
3415
return -1;
3416
#endif //#if defined(TR_TARGET_32BIT)
3417
}
3418
3419
/**
3420
* @brief A function to lower compilation limits when the JIT detects low virtual memory remaining
3421
*
3422
* 32-bit Windows due to low 2GB virtual space limit available to user mode
3423
*
3424
* When the available virtual memory is too small we may reduce some compilation
3425
* parameters like: scratchSpaceLimit, number of compilation threads, optServer, GCR
3426
*
3427
* @param compInfo TR::CompilationInfo needed for getting Port Access
3428
* @param vmThread Current thread
3429
*/
3430
void lowerCompilationLimitsOnLowVirtualMemory(TR::CompilationInfo *compInfo, J9VMThread *vmThread)
3431
{
3432
#if defined(TR_TARGET_32BIT) && (defined(WINDOWS) || defined(LINUX) || defined(J9ZOS390))
3433
// Mechanism to disable this function
3434
if (0 == TR::Options::_userSpaceVirtualMemoryMB)
3435
return;
3436
3437
uint32_t availableVirtualMemoryMB;
3438
3439
int32_t rc = getAvailableVirtualMemoryMB(compInfo, vmThread, &availableVirtualMemoryMB);
3440
3441
if (rc)
3442
return; //error case
3443
3444
if ((availableVirtualMemoryMB < (uint32_t)TR::Options::getLowVirtualMemoryMBThreshold()/2) ||
3445
(availableVirtualMemoryMB < (uint32_t)TR::Options::getLowVirtualMemoryMBThreshold() &&
3446
compInfo->getPersistentInfo()->getNumLoadedClasses() >= TR::Options::_bigAppThreshold))
3447
{
3448
uint32_t crtTime = (uint32_t)compInfo->getPersistentInfo()->getElapsedTime(); // 49 days resolution through casting
3449
static bool traceSent = false;
3450
// Generate a trace point
3451
if (TrcEnabled_Trc_JIT_LowUserVirtualMemory && !traceSent)
3452
{
3453
traceSent = true; // prevent multiple messages to the trace file
3454
// Do I know the thread?
3455
if (vmThread)
3456
{
3457
// Generate a trace point
3458
Trc_JIT_LowUserVirtualMemory(vmThread, availableVirtualMemoryMB);
3459
}
3460
}
3461
3462
// Decrease the scratch space limit
3463
if (TR::Options::getScratchSpaceLimit() > TR::Options::getScratchSpaceLimitKBWhenLowVirtualMemory()*1024)
3464
{
3465
TR::Options::setScratchSpaceLimit(TR::Options::getScratchSpaceLimitKBWhenLowVirtualMemory() * 1024);
3466
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
3467
{
3468
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u WARNING: changed scratchSpaceLimit to %d KB because VMemAv=%u MB",
3469
crtTime, TR::Options::getScratchSpaceLimit() / 1024, availableVirtualMemoryMB);
3470
}
3471
}
3472
3473
// Shut down all compilation threads but one
3474
if (!compInfo->getRampDownMCT())
3475
{
3476
compInfo->setRampDownMCT();
3477
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
3478
{
3479
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%u setRampDownMCT because VMemAv=%u MB", crtTime, availableVirtualMemoryMB);
3480
}
3481
}
3482
3483
bool doDisableGCR = false;
3484
if (!TR::Options::getAOTCmdLineOptions()->getOption(TR_DisableGuardedCountingRecompilations))
3485
{
3486
TR::Options::getAOTCmdLineOptions()->setOption(TR_DisableGuardedCountingRecompilations);
3487
doDisableGCR = true;
3488
}
3489
if (!TR::Options::getJITCmdLineOptions()->getOption(TR_DisableGuardedCountingRecompilations))
3490
{
3491
TR::Options::getJITCmdLineOptions()->setOption(TR_DisableGuardedCountingRecompilations);
3492
doDisableGCR = true;
3493
}
3494
if (doDisableGCR && TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
3495
{
3496
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u WARNING: GCR disabled because VMemAv=%u MB", crtTime, availableVirtualMemoryMB);
3497
}
3498
3499
// Disable server mode
3500
bool doDisableServerMode = false;
3501
if (!TR::Options::getAOTCmdLineOptions()->getOption(TR_NoOptServer))
3502
{
3503
TR::Options::getAOTCmdLineOptions()->setOption(TR_NoOptServer);
3504
doDisableServerMode = true;
3505
}
3506
if (!TR::Options::getJITCmdLineOptions()->getOption(TR_NoOptServer))
3507
{
3508
TR::Options::getJITCmdLineOptions()->setOption(TR_NoOptServer);
3509
doDisableServerMode = true;
3510
}
3511
if (doDisableServerMode && TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
3512
{
3513
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u WARNING: server mode disabled because VMemAv=%u MB", crtTime, availableVirtualMemoryMB);
3514
}
3515
3516
// Turn off interpreter profiling
3517
turnOffInterpreterProfiling(compInfo->getJITConfig());
3518
3519
// Disable all future non-essential compilations if virtual memory is really low
3520
{
3521
compInfo->getPersistentInfo()->setDisableFurtherCompilation(true);
3522
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
3523
{
3524
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u WARNING: Disable non-essential compilations because VMemAv=%u MB", crtTime, availableVirtualMemoryMB);
3525
}
3526
}
3527
}
3528
#endif //#if defined(TR_TARGET_32BIT) && (defined(WINDOWS) || defined(LINUX) || defined(J9ZOS390))
3529
}
3530
3531
3532
J9Method * getNewInstancePrototype(J9VMThread * context);
3533
3534
static void getClassNameIfNecessary(TR_J9VMBase *vm, TR_OpaqueClassBlock *clazz, char *&className, int32_t &len)
3535
{
3536
if (className == NULL)
3537
className = vm->getClassNameChars(clazz, len);
3538
}
3539
3540
static bool chTableOnClassLoad(J9VMThread *vmThread, TR_OpaqueClassBlock *clazz, TR::CompilationInfo *compInfo, TR_J9VMBase *vm)
3541
{
3542
J9Class *cl = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz);
3543
bool allocFailed = false;
3544
3545
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts)
3546
#if defined(J9VM_OPT_JITSERVER)
3547
&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER
3548
#endif
3549
)
3550
{
3551
TR_PersistentClassInfo *info = compInfo->getPersistentInfo()->getPersistentCHTable()->classGotLoaded(vm, clazz);
3552
3553
if (info)
3554
{
3555
// If its an interface class it won't be initialized, so we have to update the CHTable now.
3556
// Otherwise, we will update the CHTable once the class gets initialized (i.e. live)
3557
//
3558
if (vm->isInterfaceClass(clazz))
3559
{
3560
if (!updateCHTable(vmThread, cl))
3561
{
3562
allocFailed = true;
3563
compInfo->getPersistentInfo()->getPersistentCHTable()->removeClass(vm, clazz, info, true);
3564
}
3565
}
3566
else if (vm->isClassArray(clazz))
3567
{
3568
if (!compInfo->getPersistentInfo()->getPersistentCHTable()->classGotInitialized(vm, compInfo->persistentMemory(), clazz))
3569
{
3570
TR_PersistentClassInfo *arrayClazzInfo = compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfo(clazz);
3571
if (arrayClazzInfo)
3572
compInfo->getPersistentInfo()->getPersistentCHTable()->removeClass(vm, clazz, arrayClazzInfo, false);
3573
}
3574
TR_OpaqueClassBlock *compClazz = vm->getComponentClassFromArrayClass(clazz);
3575
if (compClazz)
3576
{
3577
TR_PersistentClassInfo *clazzInfo = compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfo(compClazz);
3578
if (clazzInfo && !clazzInfo->isInitialized())
3579
{
3580
bool initFailed = false;
3581
if (!compInfo->getPersistentInfo()->getPersistentCHTable()->classGotInitialized(vm, compInfo->persistentMemory(), compClazz))
3582
initFailed = true;
3583
3584
if (!initFailed &&
3585
!vm->isClassArray(compClazz) &&
3586
!vm->isInterfaceClass(compClazz) &&
3587
!vm->isPrimitiveClass(compClazz))
3588
initFailed = !updateCHTable(vmThread, ((J9Class *) compClazz));
3589
3590
if (initFailed)
3591
{
3592
compInfo->getPersistentInfo()->getPersistentCHTable()->removeClass(vm, compClazz, clazzInfo, false);
3593
allocFailed = true;
3594
}
3595
}
3596
}
3597
}
3598
}
3599
else
3600
allocFailed = true;
3601
}
3602
3603
return allocFailed;
3604
}
3605
3606
static void checkForLockReservation(J9VMThread *vmThread,
3607
J9JITConfig *jitConfig,
3608
J9ClassLoader *classLoader,
3609
TR_OpaqueClassBlock *clazz,
3610
TR_J9VMBase *vm,
3611
TR::CompilationInfo *compInfo,
3612
char * className,
3613
int32_t classNameLen)
3614
{
3615
TR::Options * options = TR::Options::getCmdLineOptions();
3616
if (options->getOption(TR_ReservingLocks)
3617
#if defined(J9VM_OPT_JITSERVER)
3618
&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER
3619
#endif
3620
)
3621
{
3622
J9Class *cl = TR::Compiler->cls.convertClassOffsetToClassPtr(clazz);
3623
TR_J9VMBase *fej9 = (TR_J9VMBase *)(TR_J9VMBase::get(jitConfig, 0));
3624
int lwOffset = fej9->getByteOffsetToLockword(clazz);
3625
if (lwOffset > 0)
3626
{
3627
bool reserve = options->getOption(TR_ReserveAllLocks);
3628
3629
if (!reserve && ((J9JavaVM *)vmThread->javaVM)->systemClassLoader == classLoader)
3630
{
3631
getClassNameIfNecessary(vm, clazz, className, classNameLen);
3632
if (classNameLen == 22 && !strncmp(className, "java/lang/StringBuffer", 22))
3633
reserve = true;
3634
else if (classNameLen == 16 && !strncmp(className, "java/util/Random", 16))
3635
reserve = true;
3636
}
3637
3638
TR::SimpleRegex *resRegex = options->getLockReserveClass();
3639
if (!reserve && resRegex != NULL)
3640
{
3641
getClassNameIfNecessary(vm, clazz, className, classNameLen);
3642
if (TR::SimpleRegex::match(resRegex, className))
3643
reserve = true;
3644
}
3645
3646
if (reserve)
3647
{
3648
TR_PersistentClassInfo *classInfo = compInfo
3649
->getPersistentInfo()
3650
->getPersistentCHTable()
3651
->findClassInfo(clazz);
3652
3653
if (classInfo != NULL)
3654
{
3655
classInfo->setReservable();
3656
if (!TR::Options::_aggressiveLockReservation)
3657
J9CLASS_EXTENDED_FLAGS_SET(cl, J9ClassReservableLockWordInit);
3658
}
3659
}
3660
}
3661
}
3662
}
3663
3664
void jitHookClassLoadHelper(J9VMThread *vmThread,
3665
J9JITConfig * jitConfig,
3666
J9Class * cl,
3667
TR::CompilationInfo *compInfo,
3668
UDATA *classLoadEventFailed)
3669
{
3670
bool allocFailed = false;
3671
TR_J9VMBase *vm = TR_J9VMBase::get(jitConfig, vmThread);
3672
TR_OpaqueClassBlock *clazz = TR::Compiler->cls.convertClassPtrToClassOffset(cl);
3673
jitAcquireClassTableMutex(vmThread);
3674
3675
compInfo->getPersistentInfo()->incNumLoadedClasses();
3676
3677
if (compInfo->getPersistentInfo()->getNumLoadedClasses() == TR::Options::_bigAppThreshold)
3678
{
3679
#if defined(TR_TARGET_32BIT) && (defined(WINDOWS) || defined(LINUX) || defined(J9ZOS390))
3680
// When we reach the bigAppThreshold limit we examine the available virtual memory
3681
// and if this is too small we reduce some compilation parameters like:
3682
// scratchSpaceLimit, number of compilation threads, optServer, GCR
3683
lowerCompilationLimitsOnLowVirtualMemory(compInfo, vmThread);
3684
#endif
3685
// For large applications be more conservative with hot compilations
3686
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableConservativeHotRecompilationForServerMode))
3687
{
3688
TR::Options::_sampleThreshold /= 3; // divide by 3 to become more conservative (3% instead of 1%)
3689
TR::Options::_resetCountThreshold /= 3;
3690
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
3691
{
3692
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u INFO: Changed sampleThreshold to %d",
3693
(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), TR::Options::_sampleThreshold);
3694
}
3695
}
3696
}
3697
3698
// todo: why is the override bit on already....temporarily reset it
3699
// ALI 20031015: I think I have fixed the above todo - we should never
3700
// get an inconsistent state now. The following should be unnecessary -
3701
// verify and remove FIXME
3702
cl->classDepthAndFlags &= ~J9AccClassHasBeenOverridden;
3703
3704
// For regular classes, cl->classLoader points to the correct class loader by the time we enter this hook.
3705
// For anonymous classes however, it points to the anonymous class loader and not the correct class loader.
3706
// Once the class is fully loaded the classLoader member will be updated to point to the correct class loader,
3707
// which is the anonymous class's host class's class loader, but that doesn't do us any good in this hook.
3708
// We need the correct class loader right now, so we grab the host class's class loader instead.
3709
// For regular classes, cl->hostClass points back to the class itself, so by doing this we get the correct
3710
// class loader for both regular and anonymous classes without having to check if this is an anonymous class.
3711
J9ClassLoader *classLoader = cl->hostClass->classLoader;
3712
3713
bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassLoading);
3714
char * className = NULL;
3715
int32_t classNameLen = -1;
3716
if (p)
3717
{
3718
getClassNameIfNecessary(vm, clazz, className, classNameLen);
3719
TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "--load-- loader %p, class %p : %.*s\n", classLoader, cl, classNameLen, className);
3720
}
3721
3722
// add the newInstance hook
3723
#if defined(J9ZOS390)
3724
cl->romableAotITable = (UDATA) TOC_UNWRAP_ADDRESS((void *)&jitTranslateNewInstanceMethod);
3725
#elif defined(TR_HOST_POWER) && (defined(TR_HOST_64BIT) || defined(AIXPPC)) && !defined(__LITTLE_ENDIAN__)
3726
cl->romableAotITable = (UDATA) (*(void **)jitTranslateNewInstanceMethod);
3727
#else
3728
cl->romableAotITable = (UDATA) jitTranslateNewInstanceMethod;
3729
#endif
3730
3731
if (((J9JavaVM *)vmThread->javaVM)->systemClassLoader != classLoader)
3732
{
3733
TR::Options::_numberOfUserClassesLoaded ++;
3734
}
3735
3736
compInfo->getPersistentInfo()->getPersistentClassLoaderTable()->associateClassLoaderWithClass(vmThread, classLoader, clazz);
3737
3738
// Update the count for the newInstance
3739
//
3740
TR::Options * options = TR::Options::getCmdLineOptions();
3741
if (options->anOptionSetContainsACountValue())
3742
{
3743
J9Method *method = getNewInstancePrototype(vmThread);
3744
if (method)
3745
{
3746
TR::OptionSet * optionSet = findOptionSet(method, false);
3747
if (optionSet)
3748
options = optionSet->getOptions();
3749
}
3750
}
3751
//fprintf(stderr, "Will set the count for NewInstancePrototype to %d\n", options->getInitialCount());
3752
cl->newInstanceCount = options->getInitialCount();
3753
3754
allocFailed = chTableOnClassLoad(vmThread, clazz, compInfo, vm);
3755
3756
compInfo->getPersistentInfo()->ensureUnloadedAddressSetsAreInitialized();
3757
// TODO: change the above line to something like the following in order to handle allocation failures:
3758
// if (!allocFailed)
3759
// allocFailed = !compInfo->getPersistentInfo()->ensureUnloadedAddressSetsAreInitialized();
3760
3761
*classLoadEventFailed = allocFailed;
3762
3763
// Determine whether this class gets lock reservation
3764
checkForLockReservation(vmThread, jitConfig, classLoader, clazz, vm, compInfo, className, classNameLen);
3765
3766
jitReleaseClassTableMutex(vmThread);
3767
}
3768
3769
static void jitHookClassLoad(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
3770
{
3771
J9VMInternalClassLoadEvent * classLoadEvent = (J9VMInternalClassLoadEvent *)eventData;
3772
J9VMThread * vmThread = classLoadEvent->currentThread;
3773
J9Class * cl = classLoadEvent->clazz;
3774
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
3775
if (jitConfig == 0)
3776
return; // if a hook gets called after freeJitConfig then not much else we can do
3777
3778
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
3779
TR_PersistentCHTable * cht = NULL;
3780
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))
3781
cht = compInfo->getPersistentInfo()->getPersistentCHTable();
3782
if (cht && !cht->isActive())
3783
return;
3784
3785
getOutOfIdleStates(TR::CompilationInfo::SAMPLER_DEEPIDLE, compInfo, "class load");
3786
3787
jitHookClassLoadHelper(vmThread, jitConfig, cl, compInfo, &(classLoadEvent->failed));
3788
}
3789
3790
int32_t loadingClasses;
3791
3792
static bool chTableOnClassPreinitialize(J9VMThread *vmThread,
3793
J9Class *cl,
3794
TR_OpaqueClassBlock *clazz,
3795
TR::CompilationInfo *compInfo,
3796
TR_J9VMBase *vm)
3797
{
3798
bool initFailed = false;
3799
3800
#if defined(J9VM_OPT_JITSERVER)
3801
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER)
3802
#endif
3803
{
3804
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))
3805
{
3806
if (!initFailed && !compInfo->getPersistentInfo()->getPersistentCHTable()->classGotInitialized(vm, compInfo->persistentMemory(), clazz))
3807
initFailed = true;
3808
3809
if (!initFailed &&
3810
!vm->isInterfaceClass(clazz))
3811
updateCHTable(vmThread, cl);
3812
}
3813
else
3814
{
3815
if (!initFailed && !updateCHTable(vmThread, cl))
3816
initFailed = true;
3817
}
3818
3819
if (initFailed)
3820
{
3821
TR_PersistentClassInfo *info = compInfo->getPersistentInfo()->getPersistentCHTable()->findClassInfo(clazz);
3822
compInfo->getPersistentInfo()->getPersistentCHTable()->removeClass(vm, clazz, info, false);
3823
}
3824
}
3825
3826
return initFailed;
3827
}
3828
3829
void jitHookClassPreinitializeHelper(J9VMThread *vmThread,
3830
J9JITConfig *jitConfig,
3831
J9Class *cl,
3832
UDATA *classPreinitializeEventFailed)
3833
{
3834
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
3835
TR_J9VMBase *vm = TR_J9VMBase::get(jitConfig, vmThread);
3836
TR_OpaqueClassBlock *clazz = ((TR_J9VMBase *)vm)->convertClassPtrToClassOffset(cl);
3837
bool p = TR::Options::getVerboseOption(TR_VerboseHookDetailsClassLoading);
3838
if (p)
3839
{
3840
int32_t len;
3841
char * className = vm->getClassNameChars(clazz, len);
3842
TR_VerboseLog::writeLineLocked(TR_Vlog_HD, "--init-- %.*s\n", len, className);
3843
}
3844
3845
jitAcquireClassTableMutex(vmThread);
3846
3847
*classPreinitializeEventFailed = chTableOnClassPreinitialize(vmThread, cl, clazz, compInfo, vm);
3848
3849
jitReleaseClassTableMutex(vmThread);
3850
}
3851
3852
3853
/// This routine is used to indicate successful initialization of the J9Class
3854
/// before any Java code (<clinit>) is run. When analyzing code in the <clinit>
3855
/// with CHTable assumptions, this ensures that the CHTable is updated correctly.
3856
/// Otherwise a class will not be seen as having been initialized in the Java code
3857
/// reachable from the <clinit>; causing possibly incorrect devirtualization or other
3858
/// CHTable opts to be applied in a method called by <clinit> (if the <clinit> for class C calls a
3859
/// virtual method on an object of class C which is instantiated in the code reachable
3860
/// from <clinit> (this was an actual WSAD scenario)).
3861
///
3862
static void jitHookClassPreinitialize(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
3863
{
3864
J9VMClassPreinitializeEvent * classPreinitializeEvent = (J9VMClassPreinitializeEvent *)eventData;
3865
J9VMThread * vmThread = classPreinitializeEvent->currentThread;
3866
J9Class * cl = classPreinitializeEvent->clazz;
3867
3868
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
3869
if (jitConfig == 0)
3870
return; // if a hook gets called after freeJitConfig then not much else we can do
3871
3872
loadingClasses = true;
3873
3874
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
3875
TR_PersistentCHTable * cht = NULL;
3876
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableCHOpts))
3877
cht = compInfo->getPersistentInfo()->getPersistentCHTable();
3878
if (cht && !cht->isActive())
3879
return;
3880
3881
jitHookClassPreinitializeHelper(vmThread, jitConfig, cl, &(classPreinitializeEvent->failed));
3882
}
3883
3884
static void jitHookClassInitialize(J9HookInterface * * hookInterface, UDATA eventNum, void * eventData, void * userData)
3885
{
3886
J9VMClassInitializeEvent * classInitializeEvent = (J9VMClassInitializeEvent *)eventData;
3887
J9VMThread * vmThread = classInitializeEvent->currentThread;
3888
J9Class * cl = classInitializeEvent->clazz;
3889
3890
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
3891
if (jitConfig == 0)
3892
return; // if a hook gets called after freeJitConfig then not much else we can do
3893
3894
loadingClasses = false;
3895
}
3896
3897
int32_t returnIprofilerState()
3898
{
3899
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
3900
return interpreterProfilingState;
3901
#else
3902
return IPROFILING_STATE_OFF;
3903
#endif
3904
}
3905
3906
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
3907
3908
#define TEST_verbose 0
3909
#define TEST_events 0
3910
#define TEST_records 0
3911
3912
void turnOffInterpreterProfiling(J9JITConfig *jitConfig)
3913
{
3914
// Turn off interpreter profiling
3915
//
3916
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))
3917
{
3918
if (interpreterProfilingState != IPROFILING_STATE_OFF)
3919
{
3920
interpreterProfilingState = IPROFILING_STATE_OFF;
3921
J9HookInterface ** hook = jitConfig->javaVM->internalVMFunctions->getVMHookInterface(jitConfig->javaVM);
3922
(*hook)->J9HookUnregister(hook, J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL, jitHookBytecodeProfiling, NULL);
3923
3924
PORT_ACCESS_FROM_JITCONFIG(jitConfig);
3925
if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))
3926
{
3927
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
3928
TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler stopped", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime());
3929
}
3930
}
3931
}
3932
}
3933
3934
/// The following two methods (stopInterpreterProfiling and restartInterpreterProfiling)
3935
/// are used when we disable/enable JIT compilation at runtime
3936
/// @{
3937
void stopInterpreterProfiling(J9JITConfig *jitConfig)
3938
{
3939
// Turn off interpreter profiling
3940
//
3941
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))
3942
{
3943
turnOffInterpreterProfiling(jitConfig);
3944
TR::Options::getCmdLineOptions()->setOption(TR_DisableInterpreterProfiling, true);
3945
}
3946
}
3947
3948
void restartInterpreterProfiling()
3949
{
3950
if (interpreterProfilingWasOnAtStartup && TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))
3951
{
3952
TR::Options::getCmdLineOptions()->setOption(TR_DisableInterpreterProfiling, false);
3953
// The hook for interpreter profiling will be registered when a class load phase is detected
3954
// We could more fancy and memorize the state of interpreter profiling
3955
// and revert to the old state.
3956
}
3957
}
3958
3959
/// @}
3960
3961
static bool checkAndTurnOffProfilingHook(TR::CompilationInfo * compInfo)
3962
{
3963
if (!compInfo->getPersistentInfo()->isClassLoadingPhase())
3964
{
3965
if (interpreterProfilingState == IPROFILING_STATE_ON)
3966
{
3967
interpreterProfilingRecordsCount = 0;
3968
interpreterProfilingState = IPROFILING_STATE_GOING_OFF;
3969
}
3970
}
3971
else if ((interpreterProfilingState == IPROFILING_STATE_GOING_OFF) ||
3972
(interpreterProfilingState == IPROFILING_STATE_OFF))
3973
{
3974
interpreterProfilingState = IPROFILING_STATE_ON;
3975
}
3976
3977
return false;
3978
}
3979
3980
3981
3982
static void jitHookBytecodeProfiling(J9HookInterface * * hook, UDATA eventNum, void * eventData, void * userData)
3983
{
3984
J9VMProfilingBytecodeBufferFullEvent* event = (J9VMProfilingBytecodeBufferFullEvent*)eventData;
3985
J9VMThread * vmThread = event->currentThread;
3986
const U_8* cursor = event->bufferStart;
3987
UDATA size = event->bufferSize;
3988
UDATA records = 0;
3989
TR_J9VMBase * fe = NULL;
3990
3991
PORT_ACCESS_FROM_VMC(vmThread);
3992
3993
if (TEST_verbose)
3994
{
3995
j9tty_printf(PORTLIB, "%p - Buffer full: %zu bytes at %p\n", vmThread, size, cursor);
3996
}
3997
//TEST_events += 1;
3998
3999
J9JITConfig * jitConfig = vmThread->javaVM->jitConfig;
4000
if (jitConfig)
4001
fe = TR_J9VMBase::get(jitConfig, vmThread);
4002
else
4003
return;
4004
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
4005
// In DEEP_IDLE we seem to be interrupted too often by IProfiler buffers
4006
// sent by VM. To alleviate this issue the sampling thread will get out
4007
// of DEEP_IDLE only if the VM sends us buffers "very frequently".
4008
// Basically we measure the time needed for the arrival of several such
4009
// buffers and interrupt the sleep of the sampling thread if this time
4010
// is less than 5 seconds (configurable)
4011
if (compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_DEEPIDLE)
4012
{
4013
static const uint32_t ARRAY_SIZE = 4; // must be power of two due to wrap around logic
4014
static uint64_t _IPBufferArrivalTimes[ARRAY_SIZE] = { 0 };
4015
static uint32_t crtPos = 0;
4016
4017
if (compInfo->getIProfilerBufferArrivalMonitor()) // safety check; will most likely exist
4018
{
4019
PORT_ACCESS_FROM_JITCONFIG(jitConfig);
4020
uint64_t crtTime = j9time_current_time_millis();
4021
4022
compInfo->getIProfilerBufferArrivalMonitor()->enter();
4023
4024
uint32_t oldestPos = (crtPos + 1) & (ARRAY_SIZE - 1);
4025
uint64_t oldestTime = _IPBufferArrivalTimes[oldestPos]; // read the oldest entry
4026
crtPos = oldestPos; // update position in the circular buffer
4027
_IPBufferArrivalTimes[oldestPos] = crtTime; // write the new entry
4028
4029
compInfo->getIProfilerBufferArrivalMonitor()->exit();
4030
4031
// Get out of deepIdle only if ARRAY_SIZE buffers arrive within 5 seconds
4032
// Note that crtTime can go backwards, however, this means we will get
4033
// out of deep idle more often that we should for a small period of time
4034
// (until we fill the entire array with new values)
4035
if ((oldestTime != 0) && (crtTime < oldestTime + TR::Options::_iProfilerBufferInterarrivalTimeToExitDeepIdle))
4036
{
4037
getOutOfIdleStates(TR::CompilationInfo::SAMPLER_DEEPIDLE, compInfo, "IP buffer received"); // this changes the state to IDLE
4038
// TODO: try to induce compilations for methods on the Java stack
4039
}
4040
else
4041
{
4042
if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))
4043
{
4044
uint32_t t = (uint32_t)(crtTime - compInfo->getPersistentInfo()->getStartTime());
4045
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%u\tSampling thread avoided an interruption in DEEP_IDLE due to IProfiler buffer being received", t);
4046
}
4047
}
4048
}
4049
}
4050
TR_ASSERT(fe, "FrontEnd must exist\n");
4051
TR_IProfiler *iProfiler = fe->getIProfiler();
4052
if (!iProfiler || !iProfiler->isIProfilingEnabled())
4053
{
4054
// Even if Iprofiler has been turned-off/stopped/disabled we should clear
4055
// the iprofiler buffer the VM has given us to avoid livelock (RTC 61279)
4056
vmThread->profilingBufferCursor = (U_8*)cursor; // discard the content
4057
return;
4058
}
4059
iProfiler->incrementNumRequests();
4060
if (TR::Options::getCmdLineOptions()->getOption(TR_DisableIProfilerThread))
4061
{
4062
iProfiler->parseBuffer(vmThread, cursor, size);
4063
vmThread->profilingBufferCursor = (U_8*)cursor; // reuse the same buffer
4064
}
4065
else // use a separate thread for iprofiler
4066
{
4067
if (!iProfiler->processProfilingBuffer(vmThread, cursor, size))
4068
{
4069
// iprofilerThread did not process or discard the buffer,
4070
// but it delegated this task to the java thread itself
4071
iProfiler->parseBuffer(vmThread, cursor, size);
4072
vmThread->profilingBufferCursor = (U_8*)cursor; // reuse the same buffer
4073
}
4074
}
4075
4076
checkAndTurnOffProfilingHook(compInfo);
4077
if (iProfiler->getProfilerMemoryFootprint() >= TR::Options::_iProfilerMemoryConsumptionLimit)
4078
{
4079
if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))
4080
{
4081
TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler exceeded memory limit %d", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), iProfiler->getProfilerMemoryFootprint());
4082
}
4083
turnOffInterpreterProfiling(jitConfig);
4084
// Generate a trace point
4085
Trc_JIT_IProfilerCapReached(vmThread, (iProfiler->getProfilerMemoryFootprint() >> 10));
4086
}
4087
4088
if (interpreterProfilingState == IPROFILING_STATE_GOING_OFF)
4089
{
4090
//interpreterProfilingRecordsCount += records;
4091
// interpreterProfilingRecordsCount could be artificially set very high from other parts of the code
4092
4093
if (interpreterProfilingRecordsCount >= TR::Options::_iprofilerSamplesBeforeTurningOff )
4094
{
4095
(*hook)->J9HookUnregister(hook, J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL, jitHookBytecodeProfiling, NULL);
4096
if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))
4097
{
4098
TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler stopped after %d records", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), TEST_records+records);
4099
}
4100
interpreterProfilingState = IPROFILING_STATE_OFF;
4101
}
4102
}
4103
}
4104
4105
#endif /* J9VM_INTERP_PROFILING_BYTECODES */
4106
4107
extern IDATA compileClasses(J9VMThread *, const char * pattern);
4108
4109
static void jitHookAboutToRunMain(J9HookInterface * * hook, UDATA eventNum, void * eventData, void * userData)
4110
{
4111
J9VMLookupJNIIDEvent * event = (J9VMLookupJNIIDEvent *)eventData;
4112
J9VMThread * vmThread = event->currentThread;
4113
J9JavaVM * javaVM = vmThread->javaVM;
4114
J9JITConfig * jitConfig = javaVM->jitConfig;
4115
if (jitConfig == 0)
4116
return; // if a hook gets called after freeJitConfig then not much else we can do
4117
4118
if (!event->isStatic || event->isField || strncmp(event->name, "main", 4) || strncmp(event->signature, "([Ljava/lang/String;)V", 22))
4119
return;
4120
4121
J9HookInterface * * vmHooks = vmThread->javaVM->internalVMFunctions->getVMHookInterface(vmThread->javaVM);
4122
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_LOOKUP_JNI_ID, jitHookAboutToRunMain, NULL);
4123
4124
bool alreadyHaveVMAccess = ((vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS) != 0);
4125
if (!alreadyHaveVMAccess)
4126
javaVM->internalVMFunctions->internalAcquireVMAccess(vmThread);
4127
javaVM->internalVMFunctions->acquireExclusiveVMAccess(vmThread);
4128
jitConfig->runtimeFlags &= ~J9JIT_DEFER_JIT;
4129
4130
#ifdef J9VM_JIT_SUPPORTS_DIRECT_JNI
4131
initializeDirectJNI(javaVM);
4132
#endif
4133
4134
jitResetAllMethodsAtStartup(vmThread);
4135
javaVM->internalVMFunctions->releaseExclusiveVMAccess(vmThread);
4136
if (!alreadyHaveVMAccess)
4137
javaVM->internalVMFunctions->internalReleaseVMAccess(vmThread);
4138
4139
if (TR::Options::getCmdLineOptions()->getOption(TR_jitAllAtMain))
4140
compileClasses(vmThread, "");
4141
}
4142
4143
4144
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
4145
// Below, options and jitConfig are guaranteed to be not null
4146
void printIprofilerStats(TR::Options *options, J9JITConfig * jitConfig, TR_IProfiler *iProfiler)
4147
{
4148
if (!options->getOption(TR_DisableInterpreterProfiling))
4149
{
4150
PORT_ACCESS_FROM_JITCONFIG(jitConfig);
4151
if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))
4152
{
4153
j9tty_printf(PORTLIB, "VM shutdown event received.\n");
4154
j9tty_printf(PORTLIB, "Total events: %d\n", TEST_events);
4155
j9tty_printf(PORTLIB, "Total records: %d\n", TEST_records);
4156
j9tty_printf(PORTLIB, "Total method persistence opportunities: %d\n", TR_IProfiler::_STATS_methodPersistenceAttempts);
4157
j9tty_printf(PORTLIB, "Total jitprofile entries: %d\n", TR_IProfiler::_STATS_methodPersisted);
4158
j9tty_printf(PORTLIB, "Total IProfiler persistence aborted due to locked entry: %d\n", TR_IProfiler::_STATS_abortedPersistence);
4159
j9tty_printf(PORTLIB, "Total IProfiler persistence failed: %d\n", TR_IProfiler::_STATS_persistError);
4160
j9tty_printf(PORTLIB, "Total IProfiler persistence aborted because SCC full: %d\n", TR_IProfiler::_STATS_methodNotPersisted_SCCfull);
4161
j9tty_printf(PORTLIB, "Total IProfiler persistence aborted because ROM class in not in SCC: %d\n", TR_IProfiler::_STATS_methodNotPersisted_classNotInSCC);
4162
j9tty_printf(PORTLIB, "Total IProfiler persistence aborted due to other reasons: %d\n", TR_IProfiler::_STATS_methodNotPersisted_other);
4163
j9tty_printf(PORTLIB, "Total IProfiler persistence aborted because already stored: %d\n", TR_IProfiler::_STATS_methodNotPersisted_alreadyStored);
4164
j9tty_printf(PORTLIB, "Total IProfiler persistence aborted because nothing needs to be stored: %d\n", TR_IProfiler::_STATS_methodNotPersisted_noEntries);
4165
j9tty_printf(PORTLIB, "Total IProfiler persisted delayed: %d\n", TR_IProfiler::_STATS_methodNotPersisted_delayed);
4166
j9tty_printf(PORTLIB, "Total records persisted: %d\n", TR_IProfiler::_STATS_entriesPersisted);
4167
j9tty_printf(PORTLIB, "Total records not persisted_NotInSCC: %d\n", TR_IProfiler::_STATS_entriesNotPersisted_NotInSCC);
4168
j9tty_printf(PORTLIB, "Total records not persisted_unloaded: %d\n", TR_IProfiler::_STATS_entriesNotPersisted_Unloaded);
4169
j9tty_printf(PORTLIB, "Total records not persisted_noInfo in bc table: %d\n", TR_IProfiler::_STATS_entriesNotPersisted_NoInfo);
4170
j9tty_printf(PORTLIB, "Total records not persisted_Other: %d\n", TR_IProfiler::_STATS_entriesNotPersisted_Other);
4171
j9tty_printf(PORTLIB, "IP Total Persistent Read Failed Attempts: %d\n", TR_IProfiler::_STATS_persistedIPReadFail);
4172
4173
j9tty_printf(PORTLIB, "IP Total Persistent Reads with Bad Data: %d\n", TR_IProfiler::_STATS_persistedIPReadHadBadData);
4174
j9tty_printf(PORTLIB, "IP Total Persistent Read Success: %d\n", TR_IProfiler::_STATS_persistedIPReadSuccess);
4175
j9tty_printf(PORTLIB, "IP Total Persistent vs Current Data Differ: %d\n", TR_IProfiler::_STATS_persistedAndCurrentIPDataDiffer);
4176
j9tty_printf(PORTLIB, "IP Total Persistent vs Current Data Match: %d\n", TR_IProfiler::_STATS_persistedAndCurrentIPDataMatch);
4177
j9tty_printf(PORTLIB, "IP Total Current Read Fail: %d\n", TR_IProfiler::_STATS_currentIPReadFail);
4178
j9tty_printf(PORTLIB, "IP Total Current Read Success: %d\n", TR_IProfiler::_STATS_currentIPReadSuccess);
4179
j9tty_printf(PORTLIB, "IP Total Current Read Bad Data: %d\n", TR_IProfiler::_STATS_currentIPReadHadBadData);
4180
j9tty_printf(PORTLIB, "Total records read: %d\n", TR_IProfiler::_STATS_IPEntryRead);
4181
j9tty_printf(PORTLIB, "Total records choose persistent: %d\n", TR_IProfiler::_STATS_IPEntryChoosePersistent);
4182
}
4183
if (TR_IProfiler::_STATS_abortedPersistence > 0)
4184
{
4185
TR_ASSERT(TR_IProfiler::_STATS_methodPersisted / TR_IProfiler::_STATS_abortedPersistence > 20 ||
4186
TR_IProfiler::_STATS_methodPersisted < 200,
4187
"too many aborted persistence attempts due to locked entries (%d aborted, %d total methods persisted)",
4188
TR_IProfiler::_STATS_abortedPersistence, TR_IProfiler::_STATS_methodPersisted);
4189
}
4190
if (TR::Options::getCmdLineOptions()->getOption(TR_EnableNewAllocationProfiling))
4191
iProfiler->printAllocationReport();
4192
if (TEST_verbose || TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))
4193
iProfiler->outputStats();
4194
}
4195
}
4196
#endif
4197
4198
4199
/// JIT cleanup code
4200
void JitShutdown(J9JITConfig * jitConfig)
4201
{
4202
static bool jitShutdownCalled = false;
4203
4204
if (!jitConfig)
4205
return; // there isn't much we can do without a jitConfig
4206
4207
J9JavaVM * javaVM = jitConfig->javaVM;
4208
J9VMThread *vmThread = javaVM->internalVMFunctions->currentVMThread(javaVM);
4209
4210
// Prevent calling this function twice;
4211
// Races cannot occur because only the main thread executes shutdown stages
4212
if (jitShutdownCalled)
4213
{
4214
TRC_JIT_ShutDownEnd(vmThread, "jitShutdownCalled is true");
4215
return;
4216
}
4217
jitShutdownCalled = true;
4218
4219
TRC_JIT_ShutDownBegin(vmThread);
4220
4221
TR_J9VMBase * vm = TR_J9VMBase::get(jitConfig, NULL);
4222
// The rest of this function seems to only be valid if we have managed to allocate at least the global VM.
4223
if (!vm)
4224
{
4225
TRC_JIT_ShutDownEnd(vmThread, "vm variable is NULL");
4226
return;
4227
}
4228
4229
4230
PORT_ACCESS_FROM_JAVAVM(javaVM);
4231
4232
TR::Options *options = TR::Options::getCmdLineOptions();
4233
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
4234
TR_ASSERT(jitConfig->privateConfig, "privateConfig must exist if a frontend exists\n");
4235
TR_IProfiler *iProfiler = vm->getIProfiler();
4236
4237
// The TR_DisableInterpreterProfiling options can change during run
4238
// so the fact that this option is true doesn't mean that IProfiler structures were not allocated
4239
if (options /* && !options->getOption(TR_DisableInterpreterProfiling) */ && iProfiler)
4240
{
4241
printIprofilerStats(options, jitConfig, iProfiler);
4242
// Prevent the interpreter to accumulate more info
4243
// stopInterpreterProfiling is stronger than turnOff... because it prevents the reactivation
4244
// by setting TR_DisableInterpreterProfiling option to false
4245
stopInterpreterProfiling(jitConfig);
4246
if (!options->getOption(TR_DisableIProfilerThread))
4247
iProfiler->stopIProfilerThread();
4248
#ifdef DEBUG
4249
uint32_t lockedEntries = iProfiler->releaseAllEntries();
4250
TR_ASSERT(lockedEntries == 0, "some entries were still locked on shutdown");
4251
#endif
4252
// Dump all IProfiler related to virtual/interface invokes and instanceof/checkcasts
4253
// to track possible performance issues
4254
// iProfiler->dumpIPBCDataCallGraph(vmThread);
4255
4256
// free the IProfiler structures
4257
4258
// Deallocate the buffers used for interpreter profiling
4259
// Must be called when we are sure that no java thread can be running
4260
// Or at least that Java threads do not try to collect IProfiler info
4261
// We turn off IProfiler above, but let's add another check
4262
if (interpreterProfilingState == IPROFILING_STATE_OFF)
4263
iProfiler->deallocateIProfilerBuffers();
4264
iProfiler->shutdown();
4265
}
4266
#endif // J9VM_INTERP_PROFILING_BYTECODES
4267
4268
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
4269
4270
TR_HWProfiler *hwProfiler = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->hwProfiler;
4271
if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())
4272
{
4273
char * printRIStats = feGetEnv("TR_PrintRIStats");
4274
if (printRIStats)
4275
hwProfiler->printStats();
4276
4277
if (!options->getOption(TR_DisableHWProfilerThread))
4278
{
4279
hwProfiler->stopHWProfilerThread(javaVM);
4280
hwProfiler->releaseAllEntries();
4281
}
4282
}
4283
4284
// Hardware profiling
4285
#ifdef J9VM_JIT_RUNTIME_INSTRUMENTATION
4286
if (NULL != hwProfiler)
4287
shutdownJITRuntimeInstrumentation(javaVM);
4288
#endif
4289
4290
TR_JProfilerThread *jProfiler = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->jProfiler;
4291
if (jProfiler != NULL)
4292
jProfiler->stop(javaVM);
4293
4294
if (options && options->getOption(TR_DumpFinalMethodNamesAndCounts))
4295
{
4296
try
4297
{
4298
TR::RawAllocator rawAllocator(jitConfig->javaVM);
4299
J9::SegmentAllocator segmentAllocator(MEMORY_TYPE_JIT_SCRATCH_SPACE | MEMORY_TYPE_VIRTUAL, *jitConfig->javaVM);
4300
J9::SystemSegmentProvider regionSegmentProvider(
4301
1 << 20,
4302
1 << 20,
4303
TR::Options::getScratchSpaceLimit(),
4304
segmentAllocator,
4305
rawAllocator
4306
);
4307
TR::Region dispatchRegion(regionSegmentProvider, rawAllocator);
4308
TR_Memory trMemory(*compInfo->persistentMemory(), dispatchRegion);
4309
4310
compInfo->getPersistentInfo()->getPersistentCHTable()->dumpMethodCounts(vm, trMemory);
4311
}
4312
catch (const std::exception &e)
4313
{
4314
fprintf(stderr, "Failed to dump Final Method Names and Counts\n");
4315
}
4316
}
4317
4318
TR::Compilation::shutdown(vm);
4319
4320
TR::CompilationController::shutdown();
4321
4322
if (!vm->isAOT_DEPRECATED_DO_NOT_USE())
4323
stopSamplingThread(jitConfig);
4324
4325
#if defined(J9VM_OPT_JITSERVER)
4326
JITServerStatisticsThread *statsThreadObj = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->statisticsThreadObject;
4327
if (statsThreadObj)
4328
{
4329
statsThreadObj->stopStatisticsThread(jitConfig);
4330
}
4331
#endif
4332
4333
TR_DebuggingCounters::report();
4334
accumulateAndPrintDebugCounters(jitConfig);
4335
4336
// TODO:JSR292: Delete or protect with env var
4337
/*
4338
TR_FrontEnd *fe = TR_J9VMBase::get(jitConfig, vmThread);
4339
TR_J2IThunkTable *thunkTable = TR::CompilationInfo::get(jitConfig)->getPersistentInfo()->getInvokeExactJ2IThunkTable();
4340
if (thunkTable)
4341
thunkTable->dumpTo(fe, TR::IO::Stdout);
4342
*/
4343
4344
if (options && options->getOption(TR_VerboseInlineProfiling))
4345
{
4346
j9tty_printf(PORTLIB, "Inlining statistics:\n");
4347
j9tty_printf(PORTLIB, "\tFailed to devirtualize virtual calls: %10d\n", TR::Options::INLINE_failedToDevirtualize);
4348
j9tty_printf(PORTLIB, "\tFailed to devirtualize interface calls: %10d\n", TR::Options::INLINE_failedToDevirtualizeInterface);
4349
j9tty_printf(PORTLIB, "\tCallee method is too big: %10d\n", TR::Options::INLINE_calleeToBig);
4350
j9tty_printf(PORTLIB, "\tCallee method is too deep: %10d\n", TR::Options::INLINE_calleeToDeep);
4351
j9tty_printf(PORTLIB, "\tCallee method has too many nodes: %10d\n", TR::Options::INLINE_calleeHasTooManyNodes);
4352
j9tty_printf(PORTLIB, "\tRan out of inlining budget: %10d\n\n", TR::Options::INLINE_ranOutOfBudget);
4353
4354
if (TR::Options::INLINE_calleeToBig)
4355
j9tty_printf(PORTLIB, "\tCallee method is too big (avg): %10d\n", TR::Options::INLINE_calleeToBigSum / TR::Options::INLINE_calleeToBig);
4356
else
4357
j9tty_printf(PORTLIB, "\tCallee method is too big (avg): x\n");
4358
if (TR::Options::INLINE_calleeToDeep)
4359
j9tty_printf(PORTLIB, "\tCallee method is too deep (avg): %10d\n", TR::Options::INLINE_calleeToDeepSum / TR::Options::INLINE_calleeToDeep);
4360
else
4361
j9tty_printf(PORTLIB, "\tCallee method is too deep (avg): x\n");
4362
4363
if (TR::Options::INLINE_calleeHasTooManyNodes)
4364
j9tty_printf(PORTLIB, "\tCallee method has too many nodes (avg): %10d\n", TR::Options::INLINE_calleeHasTooManyNodesSum / TR::Options::INLINE_calleeHasTooManyNodes);
4365
else
4366
j9tty_printf(PORTLIB, "\tCallee method has too many nodes (avg): x\n");
4367
4368
j9tty_printf(PORTLIB, "\tHas no profiling info: %10d\n", TR_IProfiler::_STATS_noProfilingInfo);
4369
j9tty_printf(PORTLIB, "\tHas weak profiling info: %10d\n", TR_IProfiler::_STATS_weakProfilingRatio);
4370
j9tty_printf(PORTLIB, "\tDoesn't want to give profiling info: %10d\n", TR_IProfiler::_STATS_doesNotWantToGiveProfilingInfo);
4371
j9tty_printf(PORTLIB, "\tNo prof. info cause cannot get classInfo:%10d\n", TR_IProfiler::_STATS_cannotGetClassInfo);
4372
j9tty_printf(PORTLIB, "\tNo prof. info because timestamp expired: %10d\n", TR_IProfiler::_STATS_timestampHasExpired);
4373
}
4374
4375
#if defined(J9VM_OPT_JITSERVER)
4376
static char * isPrintJITServerMsgStats = feGetEnv("TR_PrintJITServerMsgStats");
4377
if (isPrintJITServerMsgStats)
4378
JITServerHelpers::printJITServerMsgStats(jitConfig, compInfo);
4379
static char * isPrintJITServerCHTableStats = feGetEnv("TR_PrintJITServerCHTableStats");
4380
if (isPrintJITServerCHTableStats)
4381
JITServerHelpers::printJITServerCHTableStats(jitConfig, compInfo);
4382
#endif
4383
4384
TRC_JIT_ShutDownEnd(vmThread, "end of JitShutdown function");
4385
}
4386
4387
static void samplingObservationsLogic(J9JITConfig * jitConfig, TR::CompilationInfo * compInfo)
4388
{
4389
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHeartbeat))
4390
{
4391
TR_VerboseLog::CriticalSection vlogLock;
4392
TR_VerboseLog::writeLine(TR_Vlog_INFO,"<samplewindow intervalTicks=%u interpretedMethodSamples=%u",
4393
jitConfig->samplingTickCount + 1 - compInfo->_stats._windowStartTick, compInfo->_stats._interpretedMethodSamples);
4394
TR_VerboseLog::writeLine(TR_Vlog_INFO," compiledMethodSamples=%u compiledMethodSamplesIgnored=%u",
4395
compInfo->_stats._compiledMethodSamples, compInfo->_stats._compiledMethodSamplesIgnored);
4396
TR_VerboseLog::writeLine(TR_Vlog_INFO," samplesSent=%u samplesReceived=%u ticksInIdleMode=%u",
4397
compInfo->_stats._sampleMessagesSent, compInfo->_stats._sampleMessagesReceived, compInfo->_stats._ticksInIdleMode);
4398
TR_VerboseLog::writeLine(TR_Vlog_INFO," methodsCompiledOnCount=%u methodsReachingSampleInterval=%u",
4399
compInfo->_stats._methodsCompiledOnCount, compInfo->_stats._methodsReachingSampleInterval);
4400
}
4401
4402
// sample tick is about to be incremented for the samples we're about to take
4403
compInfo->_stats._windowStartTick = jitConfig->samplingTickCount + 1;
4404
compInfo->_stats._sampleMessagesSent = 0;
4405
compInfo->_stats._sampleMessagesReceived = 0;
4406
compInfo->_stats._ticksInIdleMode = 0;
4407
compInfo->_stats._interpretedMethodSamples = 0;
4408
compInfo->_stats._compiledMethodSamples = 0;
4409
compInfo->_stats._compiledMethodSamplesIgnored = 0;
4410
compInfo->_stats._methodsCompiledOnCount=0;
4411
compInfo->_stats._methodsReachingSampleInterval = 0;
4412
compInfo->_stats._methodsSelectedToRecompile = 0;
4413
compInfo->_stats._methodsSampleWindowReset = 0;
4414
}
4415
4416
char* jitStateNames[]=
4417
{
4418
"UNDEFINED",
4419
"IDLE ",
4420
"STARTUP ",
4421
"RAMPUP ",
4422
"STEADY ",
4423
"DEEPSTEADY",
4424
};
4425
4426
static int32_t startupPhaseId = 0;
4427
static bool firstIdleStateAfterStartup = false;
4428
static uint64_t timeToAllocateTrackingHT = 0xffffffffffffffff; // never
4429
4430
#define GCR_HYSTERESIS 100
4431
4432
static void jitStateLogic(J9JITConfig * jitConfig, TR::CompilationInfo * compInfo, uint32_t diffTime)
4433
{
4434
// We enter STARTUP too often because IDLE is not operating correctly
4435
static uint64_t lastTimeInJITStartupMode = 0;
4436
TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();
4437
uint64_t crtElapsedTime = persistentInfo->getElapsedTime();
4438
4439
static int32_t rampupPhaseID = 0;
4440
static uint32_t oldNumClassesLoaded = 0;
4441
J9JavaVM * javaVM = jitConfig->javaVM;
4442
4443
uint32_t numClassesLoadedInInterval = (uint32_t)persistentInfo->getNumLoadedClasses() - oldNumClassesLoaded;
4444
uint32_t numClassesLoadedInIntervalNormalized = numClassesLoadedInInterval*1000/diffTime;
4445
oldNumClassesLoaded = (uint32_t)persistentInfo->getNumLoadedClasses(); // remember for next time
4446
4447
uint8_t oldState = persistentInfo->getJitState();
4448
uint8_t newState;
4449
uint32_t totalSamples = compInfo->_intervalStats._compiledMethodSamples + compInfo->_intervalStats._interpretedMethodSamples;
4450
uint32_t totalSamplesNormalized = totalSamples*1000/diffTime;
4451
uint32_t samplesSentNormalized = compInfo->_intervalStats._samplesSentInInterval*1000/diffTime;
4452
float iSamplesRatio = totalSamples ? compInfo->_intervalStats._interpretedMethodSamples/(float)totalSamples : 0;
4453
uint32_t totalCompilationsNormalized = (compInfo->_intervalStats._numRecompilationsInInterval + compInfo->_intervalStats._numFirstTimeCompilationsInInterval)*1000/diffTime;
4454
4455
// Read the CPU utilization as a percentage; -1 if not functional;
4456
// Can be greater than 100% if multiple cores
4457
static int32_t oldJvmCpuUtil = 10;
4458
int32_t avgJvmCpuUtil;
4459
if (compInfo->getCpuUtil()->isFunctional())
4460
{
4461
int32_t jvmCpuUtil = compInfo->getCpuUtil()->getVmCpuUsage();
4462
avgJvmCpuUtil = (oldJvmCpuUtil + jvmCpuUtil) >> 1;
4463
oldJvmCpuUtil = jvmCpuUtil;
4464
}
4465
else
4466
{
4467
avgJvmCpuUtil = -1;
4468
}
4469
4470
if (compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_IDLE || // No need to acquire the monitor to read these
4471
compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_DEEPIDLE ||
4472
(avgJvmCpuUtil >= 0 && avgJvmCpuUtil <= 2) || // 2% or less CPU utilization puts us in idle mode
4473
(!persistentInfo->isClassLoadingPhase() && // classLoadPhase put us in STARTUP state
4474
totalCompilationsNormalized < 10 && // if compilations are taking place we cannot be in IDLE mode
4475
avgJvmCpuUtil < 10 && // if the JVM is using 10% or more CPU it cannot be idle
4476
compInfo->getMethodQueueSize() < TR::CompilationInfo::LARGE_QUEUE && // we cannot be in IDLE mode if the queue is large
4477
((totalSamplesNormalized < 6 && samplesSentNormalized < 6) || // very few samples puts us in IDLE mode
4478
(oldState == IDLE_STATE && totalSamplesNormalized <= 15) || // while in IDLE mode the number of samples criterion becomes more lax
4479
(oldState != STARTUP_STATE && totalSamplesNormalized <=22 && iSamplesRatio > 0.5)
4480
)
4481
)
4482
)
4483
{
4484
newState = IDLE_STATE;
4485
}
4486
else if (persistentInfo->isClassLoadingPhase()) // new classe being injected into the system
4487
{
4488
newState = STARTUP_STATE;
4489
if (oldState != STARTUP_STATE)
4490
startupPhaseId++;
4491
lastTimeInJITStartupMode = crtElapsedTime;
4492
}
4493
// Make it easier to stay in STARTUP if we are already in startup, but harder otherwise
4494
else if ((oldState == STARTUP_STATE &&
4495
compInfo->_intervalStats._numRecompilationsInInterval*1000/diffTime < 30 && // many recompilations puts us in RAMPUP
4496
((compInfo->_intervalStats._compiledMethodSamples == 0) ||
4497
(iSamplesRatio > 0.25) || // we could go for 0.33 when there are many samples
4498
(compInfo->_intervalStats._numFirstTimeCompilationsInInterval*1000/diffTime > 200) // 200 new compilations per second
4499
)
4500
) ||
4501
(oldState != STARTUP_STATE && // to come back to STARTUP we need at least one class to be loaded
4502
(numClassesLoadedInIntervalNormalized > 0) &&
4503
((compInfo->_intervalStats._compiledMethodSamples == 0) ||
4504
// If many interpreter samples then go to STARTUP, but only if we have enough overall samples to decide
4505
((iSamplesRatio > 0.5) && (oldState != IDLE_STATE && totalSamplesNormalized > 15)) ||
4506
(compInfo->_intervalStats._numFirstTimeCompilationsInInterval*1000/diffTime > 250 &&
4507
compInfo->_intervalStats._numRecompilationsInInterval < 3)
4508
)
4509
)
4510
)
4511
// first-time-compilations/sec > threshold ==> must take into account machine speed; counts also affect this
4512
{
4513
newState = STARTUP_STATE;
4514
if (oldState != STARTUP_STATE)
4515
startupPhaseId++;
4516
lastTimeInJITStartupMode = crtElapsedTime;
4517
}
4518
else if ((oldState == RAMPUP_STATE &&
4519
((compInfo->getMethodQueueSize() > TR::CompilationInfo::SMALL_QUEUE) ||
4520
(compInfo->_intervalStats._numRecompilationsInInterval*1000/diffTime >= 1) ||
4521
(compInfo->_intervalStats._numRecompPrevInterval*1000/diffTime >= 1) ||
4522
(compInfo->_intervalStats._numFirstTimeCompilationsInInterval*1000/diffTime > 15) ||
4523
//(compInfo->_intervalStats._interpretedMethodSamples*1000/diffTime > 10) // too many int samples ==> don't go to steady state yet
4524
(iSamplesRatio > 0.15) // not enough compiled samples to go to STEADY
4525
)
4526
) ||
4527
(oldState != RAMPUP_STATE &&
4528
((compInfo->getMethodQueueSize() >= TR::CompilationInfo::MEDIUM_LARGE_QUEUE) ||
4529
(compInfo->_intervalStats._numRecompilationsInInterval*1000/diffTime > 6) ||
4530
(oldState != STEADY_STATE && oldState != DEEPSTEADY_STATE && compInfo->_intervalStats._numRecompilationsInInterval*1000/diffTime > 2) ||
4531
(compInfo->_intervalStats._numFirstTimeCompilationsInInterval*1000/diffTime > 55) ||
4532
(oldState == STARTUP_STATE && rampupPhaseID == 0) // if we never had a rampup phase, switch now
4533
)
4534
)
4535
)
4536
// If the number of recompilations is not that high up to this point, do not hurry up to move from RAMPUP to STEADY
4537
// Maybe those recompilations will happen later
4538
{
4539
newState = RAMPUP_STATE;
4540
if (oldState != RAMPUP_STATE)
4541
rampupPhaseID++;
4542
}
4543
else // We will go to STEADY or DEEP_STEADY
4544
{
4545
if (oldState == DEEPSTEADY_STATE || // keep the DEEPSTEADY_STATE
4546
// after 10 minutes or STEADY_STATE switch to DEEPSTEADY_STATE
4547
// The 10 minutes may be shorter when multiple threads are running full speed
4548
// or longer when there isn't much work to be done
4549
((oldState == STEADY_STATE) && ((persistentInfo->getJitTotalSampleCount() - persistentInfo->getJitSampleCountWhenActiveStateEntered()) > 60000)))
4550
{
4551
newState = DEEPSTEADY_STATE;
4552
}
4553
else
4554
{
4555
newState = STEADY_STATE;
4556
}
4557
}
4558
// A surge in compilations can make the transition back to STARTUP
4559
//t= 98186 oldState=3 newState=2 cSamples=125 iSamples= 11 comp=239 recomp= 4, Q_SZ=114
4560
4561
static uint64_t lastTimeInStartupMode = 0;
4562
4563
// current JPQ implementation does not use this, but it may need to be re-animated shortly so leaving commented out for now
4564
/*static char *disableJProfilingRecomp = feGetEnv("TR_DisableJProfilingRecomp");
4565
const int32_t intervalBase = 17000;
4566
if (disableJProfilingRecomp == NULL
4567
&& javaVM->phase == J9VM_PHASE_NOT_STARTUP)
4568
{
4569
if (*(TR_BlockFrequencyInfo::getEnableJProfilingRecompilation()) == 0)
4570
{
4571
if ((crtElapsedTime - lastTimeInJITStartupMode) > intervalBase)
4572
{
4573
TR_BlockFrequencyInfo::enableJProfilingRecompilation();
4574
if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerboseCompileEnd, TR_VerbosePerformance))
4575
{
4576
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"Enabling JProfiling recompilation. recompileThrehold = %d loopRecompileThreshold = %d nestedLoopRecompileThreshold = %d", TR_JProfiling::recompileThreshold, TR_JProfiling::loopRecompileThreshold, TR_JProfiling::nestedLoopRecompileThreshold);
4577
}
4578
}
4579
}
4580
else if (TR_JProfiling::recompileThreshold > 100)
4581
{
4582
bool thresholdsLowered = false;
4583
if ((crtElapsedTime - lastTimeInJITStartupMode) > intervalBase + 30000)
4584
{
4585
TR_JProfiling::recompileThreshold = 100;
4586
TR_JProfiling::loopRecompileThreshold = 10;
4587
TR_JProfiling::nestedLoopRecompileThreshold = 1;
4588
thresholdsLowered = true;
4589
}
4590
else if ((crtElapsedTime - lastTimeInJITStartupMode) > intervalBase + 20000)
4591
{
4592
TR_JProfiling::recompileThreshold = 10000;
4593
TR_JProfiling::loopRecompileThreshold = 1000;
4594
TR_JProfiling::nestedLoopRecompileThreshold = 100;
4595
thresholdsLowered = true;
4596
}
4597
else if ((crtElapsedTime - lastTimeInJITStartupMode) > intervalBase + 10000)
4598
{
4599
TR_JProfiling::recompileThreshold = 100000;
4600
TR_JProfiling::loopRecompileThreshold = 10000;
4601
TR_JProfiling::nestedLoopRecompileThreshold = 1000;
4602
thresholdsLowered = true;
4603
}
4604
if (thresholdsLowered && TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerboseCompileEnd, TR_VerbosePerformance))
4605
{
4606
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "Lowering JProfiling recompilation thresholds. recompileThrehold = %d loopRecompileThreshold = %d nestedLoopRecompileThreshold = %d", TR_JProfiling::recompileThreshold, TR_JProfiling::loopRecompileThreshold, TR_JProfiling::nestedLoopRecompileThreshold);
4607
}
4608
}
4609
}*/
4610
/*if (disableJProfilingRecomp == NULL
4611
&& javaVM->phase == J9VM_PHASE_NOT_STARTUP
4612
&& (crtElapsedTime - lastTimeInJITStartupMode) > 80000 //&& crtElapsedTime > 150000
4613
&& *(TR_BlockFrequencyInfo::getEnableJProfilingRecompilation()) == 0)
4614
{
4615
printf("Enabling JProfiling recompilation\n");
4616
TR_BlockFrequencyInfo::enableJProfilingRecompilation();
4617
}*/
4618
4619
4620
// Enable/disable GCR counting
4621
if (!TR::Options::getAOTCmdLineOptions()->getOption(TR_DisableGuardedCountingRecompilations) &&
4622
!TR::Options::getJITCmdLineOptions()->getOption(TR_DisableGuardedCountingRecompilations))
4623
{
4624
if (!persistentInfo->_countForRecompile)// if counting is not yet enabled
4625
{
4626
bool enable = false;
4627
if (TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods) ||
4628
TR::Options::getJITCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods))
4629
{
4630
if (newState != STARTUP_STATE && // Do not enable GCR counting during JIT startup
4631
javaVM->phase == J9VM_PHASE_NOT_STARTUP && // Do not enable GCR counting during VM startup
4632
newState != DEEPSTEADY_STATE && // Do not enable GCR counting during DEEPSTEADY
4633
crtElapsedTime - lastTimeInJITStartupMode > TR::Options::_waitTimeToGCR &&
4634
// Do not enable GCR counting if we already have a large number of queued GCR requests
4635
compInfo->getNumGCRRequestsQueued() <= TR::Options::_GCRQueuedThresholdForCounting-GCR_HYSTERESIS)
4636
enable = true;
4637
}
4638
else // Old scheme
4639
{
4640
if (crtElapsedTime - lastTimeInJITStartupMode > TR::Options::_waitTimeToGCR)
4641
enable = true;
4642
}
4643
if (enable)
4644
{
4645
persistentInfo->_countForRecompile = 1; // flip the bit
4646
// write a message in the vlog
4647
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))
4648
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u GCR enabled; GCR queued=%d", (uint32_t)crtElapsedTime, compInfo->getNumGCRRequestsQueued());
4649
}
4650
}
4651
else // GCR counting is already enabled; see if we need to disable it
4652
{
4653
if ((TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods) ||
4654
TR::Options::getJITCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods))
4655
&& // stop counting if STARTUP, DEEPSTEADY or too many queued GCR requests
4656
(newState == STARTUP_STATE ||
4657
newState == DEEPSTEADY_STATE ||
4658
compInfo->getNumGCRRequestsQueued() > TR::Options::_GCRQueuedThresholdForCounting+GCR_HYSTERESIS)
4659
)
4660
{
4661
persistentInfo->_countForRecompile = 0; // disable counting
4662
// write a message in the vlog
4663
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))
4664
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u GCR disabled; GCR queued=%d", (uint32_t)crtElapsedTime, compInfo->getNumGCRRequestsQueued());
4665
}
4666
}
4667
}
4668
4669
// Enable/Disable RI Buffer processing
4670
if (persistentInfo->isRuntimeInstrumentationEnabled())
4671
{
4672
TR_HWProfiler *hwProfiler = compInfo->getHWProfiler();
4673
4674
if (TR::Options::_hwProfilerExpirationTime != 0 &&
4675
crtElapsedTime > TR::Options::_hwProfilerExpirationTime)
4676
{
4677
if (!hwProfiler->isExpired())
4678
{
4679
hwProfiler->setExpired();
4680
hwProfiler->setProcessBufferState(-1);
4681
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler, TR_VerbosePerformance))
4682
TR_VerboseLog::writeLineLocked(TR_Vlog_HWPROFILER, "Buffer processing is disabled because expiration time has been reached");
4683
}
4684
}
4685
else if (hwProfiler->getProcessBufferState() >= 0) // Buffer profiling is ON
4686
{
4687
// Should we turn it off?
4688
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableDynamicRIBufferProcessing))
4689
{
4690
hwProfiler->checkAndTurnBufferProcessingOff();
4691
}
4692
else if (TR::Options::getCmdLineOptions()->getOption(TR_InhibitRIBufferProcessingDuringDeepSteady))
4693
{
4694
if (oldState != newState && newState == DEEPSTEADY_STATE)
4695
{
4696
hwProfiler->setProcessBufferState(-1);
4697
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler, TR_VerbosePerformance))
4698
TR_VerboseLog::writeLineLocked(TR_Vlog_HWPROFILER, "Buffer processing is disabled");
4699
}
4700
}
4701
}
4702
else // Should we turn it on?
4703
{
4704
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableDynamicRIBufferProcessing))
4705
{
4706
// Do not turn on during startup
4707
if (javaVM->phase == J9VM_PHASE_NOT_STARTUP)
4708
hwProfiler->checkAndTurnBufferProcessingOn();
4709
}
4710
else if (TR::Options::getCmdLineOptions()->getOption(TR_InhibitRIBufferProcessingDuringDeepSteady))
4711
{
4712
if (oldState != newState && oldState == DEEPSTEADY_STATE)
4713
{
4714
hwProfiler->setProcessBufferState(TR::Options::_hwProfilerRIBufferProcessingFrequency);
4715
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler, TR_VerbosePerformance))
4716
TR_VerboseLog::writeLineLocked(TR_Vlog_HWPROFILER, "Buffer processing is enabled");
4717
}
4718
}
4719
}
4720
}
4721
4722
// Control how much application threads will be sleeping to give
4723
// application threads more time on the CPU
4724
TR_YesNoMaybe starvation = compInfo->detectCompThreadStarvation();
4725
bool newStarvationStatus = (starvation == TR_yes);
4726
if (newStarvationStatus != compInfo->getStarvationDetected()) // did the status change?
4727
{
4728
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
4729
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Starvation status changed to %d QWeight=%d CompCPUUtil=%d CompThreadsActive=%d",
4730
(uint32_t)crtElapsedTime, starvation, compInfo->getOverallQueueWeight(),
4731
compInfo->getTotalCompThreadCpuUtilWhenStarvationComputed(),
4732
compInfo->getNumActiveCompThreadsWhenStarvationComputed());
4733
compInfo->setStarvationDetected(newStarvationStatus);
4734
}
4735
4736
if (TR::Options::getCmdLineOptions()->getOption(TR_EnableAppThreadYield))
4737
{
4738
int32_t oldSleepNano = compInfo->getAppSleepNano();
4739
int32_t newSleepNano = starvation != TR_yes ? 0 :compInfo->computeAppSleepNano(); // TODO should we look at JIT state as well
4740
if (newSleepNano != oldSleepNano)
4741
{
4742
compInfo->setAppSleepNano(newSleepNano);
4743
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
4744
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u SleepTime changed from %d to %d QWeight=%d", (uint32_t)crtElapsedTime, oldSleepNano, newSleepNano, compInfo->getOverallQueueWeight());
4745
}
4746
}
4747
4748
4749
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
4750
// Turn on Iprofiler if we started with it OFF and it has never been activated before
4751
//
4752
static bool IProfilerOffSinceStartup = true;
4753
4754
if (IProfilerOffSinceStartup &&
4755
!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling) &&
4756
TR::Options::getCmdLineOptions()->getOption(TR_NoIProfilerDuringStartupPhase) &&
4757
interpreterProfilingState == IPROFILING_STATE_OFF)
4758
{
4759
// Should we turn it ON?
4760
TR_IProfiler *iProfiler = TR_J9VMBase::get(jitConfig, 0)->getIProfiler();
4761
uint32_t failRate = iProfiler->getReadSampleFailureRate();
4762
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJitState))
4763
{
4764
TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler current fail rate = %u total=%u fail=%u samplesInBuffer=%u",
4765
(uint32_t)crtElapsedTime, failRate, iProfiler->getTotalReadSampleRequests(),
4766
iProfiler->getFailedReadSampleRequests(), iProfiler->numSamplesInHistoryBuffer());
4767
}
4768
if (crtElapsedTime - lastTimeInJITStartupMode > TR::Options::_waitTimeToStartIProfiler ||
4769
(int32_t)failRate > TR::Options::_iprofilerFailRateThreshold)
4770
{
4771
interpreterProfilingMonitoringWindow = 0;
4772
IProfilerOffSinceStartup = false;
4773
turnOnInterpreterProfiling(jitConfig->javaVM, compInfo);
4774
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))
4775
{
4776
TR_VerboseLog::writeLineLocked(TR_Vlog_IPROFILER,"t=%6u IProfiler enabled", (uint32_t)crtElapsedTime);
4777
}
4778
}
4779
iProfiler->advanceEpochForHistoryBuffer();
4780
}
4781
#endif // defined(J9VM_INTERP_PROFILING_BYTECODES)
4782
4783
if (TR::Options::getCmdLineOptions()->getOption(TR_UseIdleTime) &&
4784
TR::Options::getCmdLineOptions()->getOption(TR_EarlyLPQ))
4785
{
4786
if (!compInfo->getLowPriorityCompQueue().isTrackingEnabled() && timeToAllocateTrackingHT == 0xffffffffffffffff)
4787
{
4788
uint64_t t = crtElapsedTime + TR::Options::_delayToEnableIdleCpuExploitation;
4789
if (TR::Options::_compilationDelayTime > 0 && (uint64_t)TR::Options::_compilationDelayTime > t)
4790
t = TR::Options::_compilationDelayTime;
4791
timeToAllocateTrackingHT = t;
4792
}
4793
}
4794
4795
// We should accelerate compilations of methods that get samples during rampup or steady state
4796
// The invocation count is decremented too slow
4797
// Set the state in the VM
4798
if (javaVM->phase != J9VM_PHASE_NOT_STARTUP) // once in NOT_STARTUP we cannot perform any changes
4799
{
4800
if (javaVM->phase == J9VM_PHASE_STARTUP)
4801
{
4802
// Analyze if we exited the STARTUP stage
4803
// Tolerate situations when we temporarily go out from STARTUP
4804
// Use JIT heuristics if (1) 'beginningOfStartup' hint didn't arrive yet OR
4805
// (2) Both 'beginningOfStartup' and 'endOfStartup' hints arrived,
4806
// but we don't follow hints strictly outside startup
4807
if (!TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo) ||
4808
(persistentInfo->getExternalStartupEndedSignal() && !TR::Options::getCmdLineOptions()->getOption(TR_UseStrictStartupHints)))
4809
{
4810
//if (newState != STARTUP_STATE && oldState != STARTUP_STATE)
4811
// javaVM->internalVMFunctions->jvmPhaseChange(javaVM, J9VM_PHASE_NOT_STARTUP);
4812
if (newState != STARTUP_STATE)
4813
{
4814
int32_t waitTime = TR::Options::_waitTimeToExitStartupMode;
4815
// Double this value for zOS control region
4816
#if defined(J9ZOS390)
4817
if (compInfo->isInZOSSupervisorState())
4818
waitTime = waitTime * 2;
4819
#endif
4820
if (crtElapsedTime - lastTimeInStartupMode > waitTime)
4821
{
4822
javaVM->internalVMFunctions->jvmPhaseChange(javaVM, J9VM_PHASE_NOT_STARTUP);
4823
}
4824
}
4825
else
4826
{
4827
lastTimeInStartupMode = crtElapsedTime;
4828
}
4829
}
4830
else // The application will provide hints about startup ending
4831
{
4832
// Exit startup when the 'endOfStartup' arrives
4833
// The case where the 'endOfStartup' hint arrived, but don't want to follow strictly
4834
// is implemented above in the IF block
4835
if (persistentInfo->getExternalStartupEndedSignal())
4836
javaVM->internalVMFunctions->jvmPhaseChange(javaVM, J9VM_PHASE_NOT_STARTUP);
4837
}
4838
}
4839
else // javaVM->phase == J9VM_PHASE_EARLY_STARTUP
4840
{
4841
//TR_ASSERT(!TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo), "assertion failure"); // we should be in STARTUP
4842
// Use JIT heuristics if (1) 'beginningOfStartup' hint didn't arrive yet OR
4843
// (2) Both 'beginningOfStartup' and 'endOfStartup' hints arrived,
4844
// but we don't follow hints strictly outside startup
4845
if (!TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo) ||
4846
(persistentInfo->getExternalStartupEndedSignal() && !TR::Options::getCmdLineOptions()->getOption(TR_UseStrictStartupHints)))
4847
{
4848
// Normal gracePeriod rules apply
4849
if (crtElapsedTime >= (uint64_t)persistentInfo->getClassLoadingPhaseGracePeriod()) // grace period has ended
4850
javaVM->internalVMFunctions->jvmPhaseChange(javaVM, (newState == STARTUP_STATE) ? J9VM_PHASE_STARTUP : J9VM_PHASE_NOT_STARTUP);
4851
}
4852
else
4853
{
4854
// 'beginningOfStartup' hint was seen
4855
// If 'endOfStartup' was not seen, move to STARTUP, otherwise, following hints strictly,
4856
// we have to exit STARTUP
4857
javaVM->internalVMFunctions->jvmPhaseChange(javaVM, !persistentInfo->getExternalStartupEndedSignal() ? J9VM_PHASE_STARTUP : J9VM_PHASE_NOT_STARTUP);
4858
}
4859
}
4860
if (javaVM->phase == J9VM_PHASE_NOT_STARTUP)
4861
{
4862
// We just exited the STARTUP phase
4863
// Print a message in the vlog
4864
if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerboseCompileEnd, TR_VerbosePerformance))
4865
{
4866
TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"t=%6u VM changed state to NOT_STARTUP", (uint32_t)crtElapsedTime);
4867
}
4868
// Release AOT data caches to normal compilations
4869
TR_DataCacheManager::getManager()->startupOver();
4870
4871
// Logic related to IdleCPU exploitation
4872
// If we are in idle mode immediately after JVM exited startup mode, set specific flag
4873
if (newState == IDLE_STATE)
4874
{
4875
firstIdleStateAfterStartup = true;
4876
}
4877
// If we don't hit idle state when we exit JVM startup, set the desired timestamp to allocate the tracking hashtable
4878
else if (TR::Options::getCmdLineOptions()->getOption(TR_UseIdleTime) &&
4879
!compInfo->getLowPriorityCompQueue().isTrackingEnabled())
4880
{
4881
uint64_t t = crtElapsedTime + TR::Options::_delayToEnableIdleCpuExploitation;
4882
if (TR::Options::_compilationDelayTime > 0 && (uint64_t)TR::Options::_compilationDelayTime > t)
4883
t = TR::Options::_compilationDelayTime;
4884
timeToAllocateTrackingHT = t;
4885
}
4886
4887
// If we wanted to restrict inliner during startup, now it's the time to let the inliner go
4888
// Note: if we want to extend the heuristic of when Inliner should be restricted
4889
// we have to change the condition below
4890
if ((TR::Options::getCmdLineOptions()->getOption(TR_RestrictInlinerDuringStartup) ||
4891
TR::Options::getAOTCmdLineOptions()->getOption(TR_RestrictInlinerDuringStartup)) &&
4892
persistentInfo->getInlinerTemporarilyRestricted())
4893
{
4894
persistentInfo->setInlinerTemporarilyRestricted(false);
4895
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
4896
{
4897
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%6u Stopped restricting the inliner", (uint32_t)crtElapsedTime);
4898
}
4899
}
4900
4901
4902
// If using lower counts, start using higher counts
4903
if (TR::Options::getCmdLineOptions()->getOption(TR_UseHigherMethodCountsAfterStartup) &&
4904
TR::Options::sharedClassCache())
4905
{
4906
if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))
4907
{
4908
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u JIT counts: %d %d %d AOT counts: %d %d %d",
4909
(uint32_t)crtElapsedTime,
4910
TR::Options::getCmdLineOptions()->getInitialCount(),
4911
TR::Options::getCmdLineOptions()->getInitialBCount(),
4912
TR::Options::getCmdLineOptions()->getInitialMILCount(),
4913
TR::Options::getAOTCmdLineOptions()->getInitialCount(),
4914
TR::Options::getAOTCmdLineOptions()->getInitialBCount(),
4915
TR::Options::getAOTCmdLineOptions()->getInitialMILCount());
4916
}
4917
TR::Options::getCmdLineOptions()->setInitialCount(TR_DEFAULT_INITIAL_COUNT);
4918
TR::Options::getCmdLineOptions()->setInitialBCount(TR_DEFAULT_INITIAL_BCOUNT);
4919
TR::Options::getCmdLineOptions()->setInitialMILCount(TR_DEFAULT_INITIAL_MILCOUNT);
4920
TR::Options::getAOTCmdLineOptions()->setInitialCount(TR_DEFAULT_INITIAL_COUNT);
4921
TR::Options::getAOTCmdLineOptions()->setInitialBCount(TR_DEFAULT_INITIAL_BCOUNT);
4922
TR::Options::getAOTCmdLineOptions()->setInitialMILCount(TR_DEFAULT_INITIAL_MILCOUNT);
4923
4924
if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))
4925
{
4926
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%6u JIT changed invocation counts to: JIT: %d %d %d AOT: %d %d %d",
4927
(uint32_t)crtElapsedTime,
4928
TR::Options::getCmdLineOptions()->getInitialCount(),
4929
TR::Options::getCmdLineOptions()->getInitialBCount(),
4930
TR::Options::getCmdLineOptions()->getInitialMILCount(),
4931
TR::Options::getAOTCmdLineOptions()->getInitialCount(),
4932
TR::Options::getAOTCmdLineOptions()->getInitialBCount(),
4933
TR::Options::getAOTCmdLineOptions()->getInitialMILCount());
4934
}
4935
}
4936
} // if (javaVM->phase == J9VM_PHASE_NOT_STARTUP)
4937
4938
// May need to update the iprofilerMaxCount; this has a higher value in startup
4939
// mode to minimize overhead, but a higher value in throughput mode.
4940
// The startup mode for this variable is defined as classLoadPhase AND
4941
// VM->phase != NOT_STARTUP
4942
if (interpreterProfilingWasOnAtStartup) // if we used -Xjit:disableInterpreterProfiling don't bother
4943
{
4944
int32_t newIprofilerMaxCount = -1;
4945
//if (persistentInfo->isClassLoadingPhase() && javaVM->phase != J9VM_PHASE_NOT_STARTUP)
4946
if (javaVM->phase == J9VM_PHASE_EARLY_STARTUP || (persistentInfo->isClassLoadingPhase() && javaVM->phase == J9VM_PHASE_STARTUP))
4947
{
4948
if (compInfo->getIprofilerMaxCount() != TR::Options::_maxIprofilingCountInStartupMode)
4949
newIprofilerMaxCount = TR::Options::_maxIprofilingCountInStartupMode;
4950
}
4951
else
4952
{
4953
if (compInfo->getIprofilerMaxCount() != TR::Options::_maxIprofilingCount)
4954
newIprofilerMaxCount = TR::Options::_maxIprofilingCount;
4955
}
4956
if (newIprofilerMaxCount != -1) // needs to be updated
4957
{
4958
compInfo->setIprofilerMaxCount(newIprofilerMaxCount);
4959
4960
j9thread_monitor_enter(javaVM->vmThreadListMutex);
4961
J9VMThread * currentThread = javaVM->mainThread;
4962
do {
4963
currentThread->maxProfilingCount = (UDATA)encodeCount(newIprofilerMaxCount);
4964
} while ((currentThread = currentThread->linkNext) != javaVM->mainThread);
4965
j9thread_monitor_exit(javaVM->vmThreadListMutex);
4966
4967
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))
4968
{
4969
TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"t=%6u Changing maxIProfilingCount to %d", (uint32_t)crtElapsedTime, newIprofilerMaxCount);
4970
}
4971
}
4972
} // if (interpreterProfilingWasOnAtStartup)
4973
} // if (javaVM->phase != J9VM_PHASE_NOT_STARTUP)
4974
4975
4976
if (newState != oldState) // state changed
4977
{
4978
persistentInfo->setJitState(newState);
4979
persistentInfo->setJitStateChangeSampleCount(persistentInfo->getJitTotalSampleCount());
4980
if ((oldState == IDLE_STATE || oldState == STARTUP_STATE) &&
4981
(newState != IDLE_STATE && newState != STARTUP_STATE))
4982
persistentInfo->setJitSampleCountWhenActiveStateEntered(persistentInfo->getJitTotalSampleCount());
4983
4984
if (newState == STARTUP_STATE) // I have moved from some state into STARTUP
4985
{
4986
persistentInfo->setJitSampleCountWhenStartupStateEntered(persistentInfo->getJitTotalSampleCount());
4987
if (compInfo->getCpuUtil()->isFunctional())
4988
persistentInfo->setVmTotalCpuTimeWhenStartupStateEntered(compInfo->getCpuUtil()->getVmTotalCpuTime());
4989
}
4990
else
4991
{
4992
persistentInfo->setJitSampleCountWhenStartupStateExited(persistentInfo->getJitTotalSampleCount());
4993
if (compInfo->getCpuUtil()->isFunctional())
4994
persistentInfo->setVmTotalCpuTimeWhenStartupStateExited(compInfo->getCpuUtil()->getVmTotalCpuTime());
4995
}
4996
4997
4998
if (newState == IDLE_STATE)
4999
{
5000
static char *disableIdleRATCleanup = feGetEnv("TR_disableIdleRATCleanup");
5001
if (disableIdleRATCleanup == NULL)
5002
persistentInfo->getRuntimeAssumptionTable()->reclaimMarkedAssumptionsFromRAT(-1);
5003
}
5004
5005
// Logic related to IdleCPU exploitation
5006
// If I left IDLE state we may set a desired delay to allocate some data structures
5007
if (oldState == IDLE_STATE)
5008
{
5009
if (firstIdleStateAfterStartup) // This flag only gets set once if we happen to be in idle state when we exit JVM startup
5010
{
5011
firstIdleStateAfterStartup = false;
5012
if (TR::Options::getCmdLineOptions()->getOption(TR_UseIdleTime) &&
5013
!compInfo->getLowPriorityCompQueue().isTrackingEnabled())
5014
{
5015
uint64_t t = crtElapsedTime + TR::Options::_delayToEnableIdleCpuExploitation;
5016
if (TR::Options::_compilationDelayTime > 0 && (uint64_t)TR::Options::_compilationDelayTime > t)
5017
t = TR::Options::_compilationDelayTime;
5018
timeToAllocateTrackingHT = t;
5019
}
5020
}
5021
}
5022
5023
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))
5024
{
5025
TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"t=%6u JIT changed state from %s to %s cSmpl=%3u iSmpl=%3u comp=%3u recomp=%3u, Q_SZ=%3d CLP=%s jvmCPU=%d%%",
5026
(uint32_t)crtElapsedTime,
5027
jitStateNames[oldState], jitStateNames[newState], compInfo->_intervalStats._compiledMethodSamples,
5028
compInfo->_intervalStats._interpretedMethodSamples,
5029
compInfo->_intervalStats._numFirstTimeCompilationsInInterval,
5030
compInfo->_intervalStats._numRecompilationsInInterval,
5031
compInfo->getMethodQueueSize(),
5032
persistentInfo->isClassLoadingPhase()?"ON":"OFF",
5033
avgJvmCpuUtil);
5034
}
5035
5036
// Turn on/off profiling in the jit
5037
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableSamplingJProfiling))
5038
{
5039
int32_t newProfilingValue = -1;
5040
if ((oldState == STARTUP_STATE || oldState == IDLE_STATE) &&
5041
(newState == RAMPUP_STATE || newState == STEADY_STATE))
5042
newProfilingValue = 1;
5043
else if ((oldState == RAMPUP_STATE || oldState == STEADY_STATE) &&
5044
(newState == STARTUP_STATE || newState == IDLE_STATE))
5045
newProfilingValue = 0;
5046
if (newProfilingValue != -1)
5047
{
5048
//fprintf(stderr, "Changed profiling value to %d\n", newProfilingValue);
5049
j9thread_monitor_enter(javaVM->vmThreadListMutex);
5050
J9VMThread * currentThread = javaVM->mainThread;
5051
do
5052
{
5053
currentThread->debugEventData4 = newProfilingValue;
5054
} while ((currentThread = currentThread->linkNext) != javaVM->mainThread);
5055
j9thread_monitor_exit(javaVM->vmThreadListMutex);
5056
}
5057
}
5058
}
5059
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJitState))
5060
{
5061
TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"t=%6u oldState=%s newState=%s cls=%3u ssn=%u tsn=%3u cSmpl=%3u iSmpl=%3u comp=%3u recomp=%3u, Q_SZ=%3d VMSTATE=%d jvmCPU=%d%%",
5062
(uint32_t)crtElapsedTime,
5063
jitStateNames[oldState], jitStateNames[newState],
5064
numClassesLoadedInIntervalNormalized,
5065
samplesSentNormalized,
5066
totalSamplesNormalized,
5067
compInfo->_intervalStats._compiledMethodSamples,
5068
compInfo->_intervalStats._interpretedMethodSamples,
5069
compInfo->_intervalStats._numFirstTimeCompilationsInInterval,
5070
compInfo->_intervalStats._numRecompilationsInInterval,
5071
compInfo->getMethodQueueSize(),
5072
javaVM->phase,
5073
avgJvmCpuUtil);
5074
}
5075
if(TR::Options::getVerboseOption(TR_VerboseJitMemory))
5076
{
5077
TR_VerboseLog::writeLine(TR_Vlog_MEMORY, "FIXME: Report JIT memory usage\n");
5078
}
5079
5080
// Allocate the tracking hashtable if needed
5081
// Note that timeToAllocateTrackingHT will be set to something useful only if TR_UseIdleTime option is set
5082
if (crtElapsedTime >= timeToAllocateTrackingHT)
5083
{
5084
compInfo->getLowPriorityCompQueue().startTrackingIProfiledCalls(TR::Options::_numIProfiledCallsToTriggerLowPriComp);
5085
timeToAllocateTrackingHT = 0xfffffffffffffff0; // never again
5086
}
5087
5088
// Reset stats for next interval
5089
if (compInfo->getSamplerState() != TR::CompilationInfo::SAMPLER_DEEPIDLE &&
5090
compInfo->getSamplerState() != TR::CompilationInfo::SAMPLER_IDLE)
5091
compInfo->_intervalStats.decay();
5092
else
5093
compInfo->_intervalStats.reset(); // if we are going to sleep for seconds, do not keep any history
5094
}
5095
5096
/// Determine if CPU throttling may be enabled at this time.
5097
/// We use this to determine if we need to bother calculating CPU usage.
5098
bool CPUThrottleEnabled(TR::CompilationInfo *compInfo, uint64_t crtTime)
5099
{
5100
// test if feature is enabled
5101
if (TR::Options::_compThreadCPUEntitlement <= 0)
5102
return false;
5103
5104
// During startup we apply throttling only if enabled
5105
if (!TR::Options::getCmdLineOptions()->getOption(TR_EnableCompThreadThrottlingDuringStartup) &&
5106
compInfo->getJITConfig()->javaVM->phase != J9VM_PHASE_NOT_STARTUP)
5107
return false;
5108
5109
// Maybe the user wants to start throttling only after some time
5110
if (crtTime < (uint64_t)TR::Options::_startThrottlingTime)
5111
return false;
5112
5113
// Maybe the user wants to stop throttling after some time
5114
if (TR::Options::_stopThrottlingTime != 0 && crtTime >= (uint64_t)TR::Options::_stopThrottlingTime)
5115
{
5116
if (compInfo->exceedsCompCpuEntitlement() != TR_no)
5117
{
5118
compInfo->setExceedsCompCpuEntitlement(TR_no);
5119
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
5120
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Changed throttling value for compilation threads to NO because throttling reached expiration time", (uint32_t)crtTime);
5121
}
5122
return false;
5123
}
5124
return true;
5125
}
5126
5127
/// Sums up CPU utilization of all compilation thread and write this
5128
/// value in the compilation info (or -1 in case of error)
5129
static void DoCalculateOverallCompCPUUtilization(TR::CompilationInfo *compInfo, uint64_t crtTime, J9VMThread *currentThread, int32_t *cpuUtilizationValues)
5130
{
5131
// Sum up the CPU utilization of all the compilation threads
5132
int32_t totalCompCPUUtilization = 0;
5133
//TODO: Is getArrayOfCompilationInfoPerThread() called after setupCompilationThreads()
5134
TR::CompilationInfoPerThread * const *arrayOfCompInfoPT = compInfo->getArrayOfCompilationInfoPerThread();
5135
5136
for (int32_t i = 0; i < compInfo->getNumUsableCompilationThreads(); i++)
5137
{
5138
const CpuSelfThreadUtilization& cpuUtil = arrayOfCompInfoPT[i]->getCompThreadCPU();
5139
if (cpuUtil.isFunctional())
5140
{
5141
// If the last interval ended more than 1.5 second ago, do not include it
5142
// in the calculations.
5143
int32_t cpuUtilValue = cpuUtil.computeThreadCpuUtilOverLastNns(1500000000);
5144
cpuUtilizationValues[i] = cpuUtilValue; // memorize for later
5145
if (cpuUtilValue >= 0) // if first interval is not done, we read -1
5146
totalCompCPUUtilization += cpuUtilValue;
5147
}
5148
else
5149
{
5150
totalCompCPUUtilization = -1; // error
5151
break;
5152
}
5153
}
5154
compInfo->setOverallCompCpuUtilization(totalCompCPUUtilization);
5155
// Issue tracepoint indicating CPU usage percent (-1 on error)
5156
Trc_JIT_OverallCompCPU(currentThread, totalCompCPUUtilization);
5157
// Print the overall comp CPU utilization if the right verbose option is specified
5158
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompilationThreads, TR_VerboseCompilationThreadsDetails))
5159
{
5160
TR_VerboseLog::CriticalSection vlogLock;
5161
TR_VerboseLog::write(TR_Vlog_INFO, "t=%6u TotalCompCpuUtil=%3d%%.", static_cast<uint32_t>(crtTime), totalCompCPUUtilization);
5162
TR::CompilationInfoPerThread * const *arrayOfCompInfoPT = compInfo->getArrayOfCompilationInfoPerThread();
5163
for (int32_t i = 0; i < compInfo->getNumUsableCompilationThreads(); i++)
5164
{
5165
const CpuSelfThreadUtilization& cpuUtil = arrayOfCompInfoPT[i]->getCompThreadCPU();
5166
TR_VerboseLog::write(" compThr%d:%3d%% (%2d%%, %2d%%) ", i, cpuUtilizationValues[i], cpuUtil.getThreadLastCpuUtil(), cpuUtil.getThreadPrevCpuUtil());
5167
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreadsDetails))
5168
TR_VerboseLog::write("(%dms, %dms, lastCheckpoint=%u) ",
5169
static_cast<int32_t>(cpuUtil.getLastMeasurementInterval()) / 1000000,
5170
static_cast<int32_t>(cpuUtil.getSecondLastMeasurementInterval()) / 1000000,
5171
cpuUtil.getLowResolutionClockAtLastUpdate());
5172
}
5173
TR_VerboseLog::writeLine("");
5174
}
5175
}
5176
5177
void CalculateOverallCompCPUUtilization(TR::CompilationInfo *compInfo, uint64_t crtTime, J9VMThread *currentThread)
5178
{
5179
if (compInfo->getOverallCompCpuUtilization() >= 0) // No error so far
5180
{
5181
if (compInfo->getNumUsableCompilationThreads() < 8)
5182
{
5183
int32_t cpuUtilizationValues[7];
5184
DoCalculateOverallCompCPUUtilization(compInfo, crtTime, currentThread, cpuUtilizationValues);
5185
}
5186
else
5187
{
5188
PORT_ACCESS_FROM_JAVAVM(currentThread->javaVM);
5189
5190
int32_t *cpuUtilizationValues = static_cast<int32_t *>(j9mem_allocate_memory(compInfo->getNumUsableCompilationThreads() * sizeof(int32_t), J9MEM_CATEGORY_JIT));
5191
if (cpuUtilizationValues)
5192
{
5193
DoCalculateOverallCompCPUUtilization(compInfo, crtTime, currentThread, cpuUtilizationValues);
5194
j9mem_free_memory(cpuUtilizationValues);
5195
}
5196
}
5197
}
5198
}
5199
5200
/// Sets a exceedsCompCpuEntitlement flag according to whether the CPU should be throttled
5201
void CPUThrottleLogic(TR::CompilationInfo *compInfo, uint64_t crtTime)
5202
{
5203
const int32_t totalCompCPUUtilization = compInfo->getOverallCompCpuUtilization();
5204
// Decide whether we want to throttle compilation threads
5205
// and set the throttle flag if we exceed the valued specified by the user
5206
if (totalCompCPUUtilization >= 0)
5207
{
5208
TR_YesNoMaybe oldThrottleValue = compInfo->exceedsCompCpuEntitlement();
5209
// Implement some for of hysterisis; once in throttle mode the CPU utilization should
5210
// be 10 percentage points lower than the target to get out of throttling mode
5211
bool shouldThrottle = (oldThrottleValue != TR_no && TR::Options::_compThreadCPUEntitlement >= 15) ?
5212
totalCompCPUUtilization > TR::Options::_compThreadCPUEntitlement - 10 :
5213
totalCompCPUUtilization > TR::Options::_compThreadCPUEntitlement;
5214
// We want to avoid situations where we end up throttling and all compilation threads
5215
// get activated working at full capacity (until, half a second later we discover that we throttle again)
5216
// The solution is to go into a transient state; so from TR_yes we go into TR_maybe and from TR_maybe we go into TR_no
5217
compInfo->setExceedsCompCpuEntitlement(shouldThrottle ? TR_yes : oldThrottleValue == TR_yes ? TR_maybe : TR_no);
5218
// If the value changed we may want to print a message in the vlog
5219
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance) &&
5220
oldThrottleValue != compInfo->exceedsCompCpuEntitlement()) // did the value change?
5221
{
5222
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Changed throttling value for compilation threads to %s because compCPUUtil=%d",
5223
(uint32_t)crtTime,
5224
compInfo->exceedsCompCpuEntitlement() == TR_yes ? "YES" : compInfo->exceedsCompCpuEntitlement() == TR_maybe ? "MAYBE" : "NO",
5225
totalCompCPUUtilization);
5226
}
5227
}
5228
else
5229
{
5230
compInfo->setExceedsCompCpuEntitlement(TR_no); // Conservative decision is not to throttle in case of error
5231
// TODO: add an option to force throttling no matter what the compilation thread utilization looks like
5232
}
5233
}
5234
5235
/// When many classes are loaded per second (like in Websphere startup)
5236
/// we would like to decrease the initial level of compilation from warm to cold
5237
/// The following fragment of code uses a heuristic to detect when we are
5238
/// in a class loading phase and sets a global variable accordingly
5239
static void classLoadPhaseLogic(J9JITConfig * jitConfig, TR::CompilationInfo * compInfo, uint32_t diffTime)
5240
{
5241
//static uint64_t oldElapsedTime = 0;
5242
static int32_t oldNumLoadedClasses = 0;
5243
static int32_t oldNumUserLoadedClasses = 0;
5244
static int32_t numTicksCapped = 0; // will be capped at 2
5245
static int32_t classLoadRateForFirstInterval;
5246
static int32_t numCLPQuiesceIntervals = 0;
5247
5248
TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();
5249
int32_t prevNumLoadedClasses = oldNumLoadedClasses;
5250
int32_t prevNumUserLoadedClasses = oldNumUserLoadedClasses;
5251
uint64_t crtElapsedTime = persistentInfo->getElapsedTime();
5252
5253
TR::Options * cmdLineOptions = TR::Options::getCmdLineOptions();
5254
5255
if (cmdLineOptions->getOption(TR_ExperimentalClassLoadPhase))
5256
{
5257
// Let's experiment with a class loading phase algorithm that is less cpu and time dependent
5258
// If a sample occurs between a class loading preinitialize hook and a class load initialize hook then
5259
// we'll set the class load phase threshold to be true until 'n' more ticks have been seen,
5260
// where 'n' is TR::Options::_experimentalClassLoadPhaseInterval.
5261
//
5262
static int32_t classLoadPhaseCount;
5263
if (loadingClasses && TR::Options::_experimentalClassLoadPhaseInterval > 0)
5264
{
5265
persistentInfo->setClassLoadingPhase(true);
5266
classLoadPhaseCount = TR::Options::_experimentalClassLoadPhaseInterval;
5267
}
5268
else if (classLoadPhaseCount > 0)
5269
--classLoadPhaseCount;
5270
else if (persistentInfo->isClassLoadingPhase())
5271
persistentInfo->setClassLoadingPhase(false);
5272
5273
return;
5274
}
5275
5276
else
5277
{
5278
oldNumLoadedClasses = persistentInfo->getNumLoadedClasses();
5279
oldNumUserLoadedClasses = TR::Options::_numberOfUserClassesLoaded;
5280
5281
int32_t loadedClasses = persistentInfo->getNumLoadedClasses() - prevNumLoadedClasses;
5282
5283
// during WAS5 startup we have 300-500 classes loaded per second (uniprocessor P4/2.2Ghz)
5284
// caveat: this formula depends on the machine speed (also network issues)
5285
int classLoadRate = loadedClasses*1000/diffTime;
5286
if (numTicksCapped < 2)
5287
{
5288
if (numTicksCapped == 0)
5289
{
5290
// This is the first interval; memorize the classLoadRate for later
5291
classLoadRateForFirstInterval = classLoadRate;
5292
}
5293
else
5294
{
5295
// This is the second interval; use the classLoadRate to adjust the classLoadPhaseThreshold
5296
int32_t variance = TR::Options::_classLoadingPhaseVariance < 100 ? TR::Options::_classLoadingPhaseVariance : 0;
5297
int32_t newCLPThreshold = (int32_t)(0.01 *
5298
(TR::Options::_classLoadingPhaseThreshold * (100+variance) -
5299
2 * TR::Options::_classLoadingRateAverage * TR::Options::_classLoadingPhaseThreshold * variance/
5300
(TR::Options::_classLoadingRateAverage + classLoadRateForFirstInterval)));
5301
// Scale down even more if the user tells us we have only a fraction of a processor
5302
newCLPThreshold = newCLPThreshold * TR::Options::_availableCPUPercentage / 100;
5303
5304
double scalingFactor = (double)newCLPThreshold/(double)TR::Options::_classLoadingPhaseThreshold;
5305
5306
int32_t newSecondaryCLPThreshold = (int32_t)(scalingFactor*TR::Options::_secondaryClassLoadingPhaseThreshold);
5307
TR::Options::_classLoadingPhaseThreshold = newCLPThreshold;
5308
TR::Options::_secondaryClassLoadingPhaseThreshold = newSecondaryCLPThreshold;
5309
5310
// Scale other thresholds as well. Hmm, not sure this is the right thing to do.
5311
//TR::Options::_waitTimeToExitStartupMode = (int32_t) (TR::Options::_waitTimeToExitStartupMode/scalingFactor);
5312
5313
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCLP))
5314
{
5315
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"ScalingFactor=%.2f Changed CLPTHreshold to %d secondaryCLPThreshold to %d", scalingFactor, newCLPThreshold, newSecondaryCLPThreshold);
5316
}
5317
5318
// On some platforms, if application startup hints have NOT been used by now
5319
// turn off the selectiveNoServer feature
5320
if (TR::Options::getCmdLineOptions()->getOption(TR_TurnOffSelectiveNoOptServerIfNoStartupHint) &&
5321
!TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo) &&
5322
!TR::Options::getCmdLineOptions()->getOption(TR_DisableSelectiveNoOptServer))
5323
{
5324
TR::Options::getCmdLineOptions()->setOption(TR_DisableSelectiveNoOptServer); // Turn this feature off
5325
TR::Options::getAOTCmdLineOptions()->setOption(TR_DisableSelectiveNoOptServer); // Turn this feature off
5326
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
5327
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%u selectiveNoOptServer feature turned off", crtElapsedTime);
5328
}
5329
}
5330
numTicksCapped++;
5331
}
5332
bool classLoadPhase = false;
5333
// needed to figure out the first time we exit grace period
5334
if (crtElapsedTime >= (uint64_t)persistentInfo->getClassLoadingPhaseGracePeriod())
5335
{
5336
if (classLoadRate >= TR::Options::_classLoadingPhaseThreshold)
5337
{
5338
classLoadPhase = true;
5339
numCLPQuiesceIntervals = TR::Options::_numClassLoadPhaseQuiesceIntervals; // reload
5340
}
5341
else
5342
{
5343
if (numCLPQuiesceIntervals > 0)
5344
{
5345
if (classLoadRate >= TR::Options::_secondaryClassLoadingPhaseThreshold)
5346
{
5347
classLoadPhase = true;
5348
numCLPQuiesceIntervals--;
5349
}
5350
else
5351
{
5352
numCLPQuiesceIntervals = 0;
5353
}
5354
}
5355
}
5356
}
5357
// If TR_AssumeStartupPhaseUntilToldNotTo is seen, then we may override previous decision
5358
if (TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo))
5359
{
5360
if (TR::Options::getCmdLineOptions()->getOption(TR_UseStrictStartupHints))
5361
{
5362
// presence of the endOfStartup signal alone dictates CLP (and startup)
5363
classLoadPhase = !persistentInfo->getExternalStartupEndedSignal();
5364
}
5365
else
5366
{
5367
// If endOfStartup signal didn't come yet, assume CLP (and startup)
5368
// Otherwise, let the normal CLP algorithm work its course and decide startup
5369
if (!persistentInfo->getExternalStartupEndedSignal()) // endOfStartup didn't come yet
5370
classLoadPhase = true;
5371
}
5372
}
5373
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCLP))
5374
{
5375
if ((persistentInfo->isClassLoadingPhase() && !classLoadPhase) ||
5376
(!persistentInfo->isClassLoadingPhase() && classLoadPhase))
5377
{
5378
if (classLoadPhase)
5379
TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"Entering classLoadPhase");
5380
else
5381
TR_VerboseLog::writeLineLocked(TR_Vlog_JITSTATE,"Exiting classLoadPhase");
5382
}
5383
}
5384
persistentInfo->setClassLoadingPhase(classLoadPhase);
5385
5386
int32_t userLoadedClasses = TR::Options::_numberOfUserClassesLoaded - prevNumUserLoadedClasses;
5387
TR::Options::_userClassLoadingPhase = (userLoadedClasses*1024/diffTime >= TR::Options::_userClassLoadingPhaseThreshold);
5388
5389
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCLP))
5390
{
5391
TR_VerboseLog::writeLineLocked(TR_Vlog_MEMORY,"diffTime %d classes %d userClasses %d threshold %d secondaryThreshold %d",
5392
diffTime, loadedClasses, userLoadedClasses, TR::Options::_classLoadingPhaseThreshold,
5393
TR::Options::_secondaryClassLoadingPhaseThreshold);
5394
}
5395
}
5396
}
5397
5398
5399
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
5400
static void iProfilerActivationLogic(J9JITConfig * jitConfig, TR::CompilationInfo * compInfo)
5401
{
5402
//printf("%d\n", interpreterProfilingINTSamples);
5403
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling))
5404
{
5405
if (interpreterProfilingState == IPROFILING_STATE_OFF)
5406
{
5407
// Should we turn it ON?
5408
TR_J9VMBase *fej9 = (TR_J9VMBase *)(TR_J9VMBase::get(jitConfig, 0));
5409
TR_IProfiler *iProfiler = fej9->getIProfiler();
5410
TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();
5411
if (iProfiler
5412
&& iProfiler->getProfilerMemoryFootprint() < TR::Options::_iProfilerMemoryConsumptionLimit
5413
#if defined(J9VM_OPT_JITSERVER)
5414
&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER
5415
#endif
5416
)
5417
{
5418
// Turn on if classLoadPhase became active or
5419
// if many interpreted samples
5420
if (persistentInfo->isClassLoadingPhase() ||
5421
interpreterProfilingINTSamples > TR::Options::_iprofilerReactivateThreshold)
5422
{
5423
// Don't turn on during first startup phase
5424
if (!TR::Options::getCmdLineOptions()->getOption(TR_NoIProfilerDuringStartupPhase) ||
5425
jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP)
5426
{
5427
interpreterProfilingMonitoringWindow = 0;
5428
turnOnInterpreterProfiling(jitConfig->javaVM, compInfo);
5429
}
5430
}
5431
}
5432
}
5433
else // STATE != OFF
5434
{
5435
// Should we turn it OFF?
5436
if (TR::Options::getCmdLineOptions()->getOption(TR_UseOldIProfilerDeactivationLogic))
5437
{
5438
if (interpreterProfilingINTSamples > 0 && interpreterProfilingJITSamples > 0)
5439
{
5440
if (interpreterProfilingINTSamples <= TR::Options::_iprofilerReactivateThreshold &&
5441
interpreterProfilingINTSamples > 0) // WHY? we already know this
5442
interpreterProfilingMonitoringWindow ++;
5443
else // reset the window
5444
interpreterProfilingMonitoringWindow = 0;
5445
5446
if (interpreterProfilingMonitoringWindow > 60)
5447
turnOffInterpreterProfiling (jitConfig);
5448
}
5449
}
5450
else
5451
{
5452
if (interpreterProfilingINTSamples > 0 || interpreterProfilingJITSamples > 0)
5453
{
5454
if (interpreterProfilingINTSamples <= TR::Options::_iprofilerReactivateThreshold &&
5455
(((float)interpreterProfilingINTSamples) / ((float) (interpreterProfilingINTSamples + interpreterProfilingJITSamples))) < (((float)TR::Options::_iprofilerIntToTotalSampleRatio) / 100))
5456
interpreterProfilingMonitoringWindow ++;
5457
else // reset the window
5458
interpreterProfilingMonitoringWindow = 0;
5459
5460
if (interpreterProfilingMonitoringWindow > 60)
5461
turnOffInterpreterProfiling (jitConfig);
5462
}
5463
}
5464
}
5465
//printf("interpreter samples %d, jit samples %d, monitor window %d, profiler state = %d\n", interpreterProfilingINTSamples, interpreterProfilingJITSamples, interpreterProfilingMonitoringWindow, interpreterProfilingState);
5466
interpreterProfilingINTSamples = 0;
5467
interpreterProfilingJITSamples = 0;
5468
}
5469
}
5470
#endif // J9VM_INTERP_PROFILING_BYTECODES
5471
5472
static void initJitGCMapCheckAsyncHook(J9JavaVM * vm, IDATA handlerKey, J9JITConfig *jitConfig)
5473
{
5474
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
5475
compInfo->getPersistentInfo()->setGCMapCheckEventHandle(handlerKey);
5476
}
5477
5478
5479
//int32_t samplerThreadStateFrequencies[TR::CompilationInfo::SAMPLER_LAST_STATE+1] = {0, 2, 1000, 100000, INT_MAX, INT_MAX, -1};
5480
char* samplerThreadStateNames[TR::CompilationInfo::SAMPLER_LAST_STATE+1] =
5481
{
5482
"NOT_INITIALIZED",
5483
"DEFAULT",
5484
"IDLE",
5485
"DEEPIDLE",
5486
"SUSPENDED",
5487
"STOPPED",
5488
"INVALID",
5489
};
5490
5491
/// Method executed by various hooks on application thread
5492
/// when we should take the samplerThread out of DEEPIDLE/IDLE state
5493
/// This version does not acquire the vmThreadListMutex assuming that
5494
/// its caller has already done that
5495
void getOutOfIdleStatesUnlocked(TR::CompilationInfo::TR_SamplerStates expectedState, TR::CompilationInfo *compInfo, const char* reason)
5496
{
5497
if (compInfo->getSamplerState() != expectedState) // state may have changed when not checked under monitor
5498
return;
5499
J9JITConfig * jitConfig = compInfo->getJITConfig();
5500
TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();
5501
// Time as maintained by sampling thread will be inaccurate here because
5502
// sampling thread has slept for a while and didn't have the chance to update time
5503
// Thus, let's use j9time_current_time_millis() instead
5504
//persistentInfo->setLastTimeSamplerThreadEnteredIdle(persistentInfo->getElapsedTime());
5505
PORT_ACCESS_FROM_JITCONFIG(jitConfig);
5506
uint64_t crtTime = j9time_current_time_millis() - persistentInfo->getStartTime();
5507
5508
if (compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_DEEPIDLE)
5509
{
5510
compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_IDLE);
5511
jitConfig->samplingFrequency = TR::Options::getSamplingFrequencyInIdleMode();
5512
persistentInfo->setLastTimeSamplerThreadEnteredIdle(crtTime);
5513
}
5514
else if (compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_IDLE)
5515
{
5516
J9JavaVM * vm = jitConfig->javaVM;
5517
J9VMRuntimeStateListener *listener = &vm->vmRuntimeStateListener;
5518
compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_DEFAULT);
5519
jitConfig->samplingFrequency = TR::Options::getSamplingFrequency();
5520
persistentInfo->setLastTimeThreadsWereActive(crtTime); // make the sampler thread wait for another 5 sec before entering IDLE again
5521
uint32_t currentVMState = vm->internalVMFunctions->getVMRuntimeState(vm);
5522
5523
if (currentVMState == J9VM_RUNTIME_STATE_IDLE)
5524
{
5525
if (vm->internalVMFunctions->updateVMRuntimeState(vm, J9VM_RUNTIME_STATE_ACTIVE) &&
5526
(TR::Options::getVerboseOption(TR_VerbosePerformance)))
5527
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%u\tSampling thread interrupted and changed VM state to %u", (uint32_t)crtTime, J9VM_RUNTIME_STATE_ACTIVE);
5528
}
5529
}
5530
5531
// Interrupt the samplerThread
5532
j9thread_interrupt(jitConfig->samplerThread);
5533
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
5534
{
5535
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%u\tSampling thread interrupted and changed state to %s and frequency to %d ms due to %s",
5536
(uint32_t)crtTime, samplerThreadStateNames[compInfo->getSamplerState()],
5537
jitConfig->samplingFrequency, reason);
5538
}
5539
}
5540
5541
/// Method executed by various hooks on application thread
5542
/// when we should take the samplerThread out of DEEPIDLE state
5543
/// Side-effect: will acquire/release vmThreadListMutex; note that we should
5544
/// not use this version in GC hooks because a deadlock may happen
5545
///
5546
/// In Balanced, once a mutator thread hits AF it will (only) trigger GC, but will not act as main thread.
5547
/// However, it is still the one that will request (and wait while the request is completed) exclusive VM access.
5548
/// Once it acquires it will notify main GC thread (which is sleeping). Main GC wakes up and takes control
5549
/// driving GC till completion. The mutator thread will just wait on 'control mutex' for notification back
5550
/// from GC main thread that GC has completed. When resumed, the mutator thread will
5551
/// release the exclusive VM access and proceed with allocation, and program execution.
5552
/// It is main GC thread that will invoke the hooks (start/end), but it does not directly hold
5553
/// 'VM thread list' lock. Mutator thread does it.
5554
void getOutOfIdleStates(TR::CompilationInfo::TR_SamplerStates expectedState, TR::CompilationInfo *compInfo, const char* reason)
5555
{
5556
// First a cheap test without holding a monitor
5557
if (compInfo->getSamplerState() == expectedState)
5558
{
5559
J9JavaVM * vm = compInfo->getJITConfig()->javaVM;
5560
// Now acquire the monitor and do another test
5561
j9thread_monitor_enter(vm->vmThreadListMutex);
5562
getOutOfIdleStatesUnlocked(expectedState, compInfo, reason);
5563
j9thread_monitor_exit(vm->vmThreadListMutex);
5564
}
5565
}
5566
5567
/// This routine is executed with vm->vmThreadListMutex in hand
5568
void samplerThreadStateLogic(TR::CompilationInfo *compInfo, TR_FrontEnd *fe, int32_t numActiveThreads)
5569
{
5570
static bool foundThreadActiveDuringIdleMode = false;
5571
J9JITConfig * jitConfig = compInfo->getJITConfig();
5572
TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();
5573
uint64_t crtTime = persistentInfo->getElapsedTime();
5574
bool notifyVMThread = false;
5575
int32_t waitTimeInDeepIdleToNotifyVM = compInfo->getSamplingThreadWaitTimeInDeepIdleToNotifyVM();
5576
J9JavaVM * vm = jitConfig->javaVM;
5577
uint32_t currentVMState = vm->internalVMFunctions->getVMRuntimeState(vm);
5578
uint32_t newVMState = currentVMState;
5579
5580
if (numActiveThreads > 0)
5581
persistentInfo->setLastTimeThreadsWereActive(crtTime);
5582
5583
TR::CompilationInfo::TR_SamplerStates samplerState = compInfo->getSamplerState();
5584
TR::CompilationInfo::TR_SamplerStates newSamplerState = samplerState;
5585
5586
TR_ASSERT(samplerState != TR::CompilationInfo::SAMPLER_NOT_INITIALIZED, "samplerThreadStateLogic: sampler must be initialized");
5587
TR_ASSERT(samplerState != TR::CompilationInfo::SAMPLER_STOPPED, "once stopped, samplerThread cannot call samplerThreadLogic again");
5588
5589
// Application threads can set different states
5590
// 1) DisableJIT --> change state to SUSPENDED
5591
// 2) EnableJIT --> may change state to DEFAULT
5592
// 3) Hooks --> may change state from DEEPIDLE to IDLE
5593
5594
5595
// Option to stop the sampling thread after certain number of ticks
5596
//
5597
if (TR::Options::_samplingThreadExpirationTime >= 0 &&
5598
TR::Options::_samplingThreadExpirationTime*1000 < crtTime)
5599
{
5600
if (samplerState != TR::CompilationInfo::SAMPLER_SUSPENDED) // Nothing to do if sampler is already suspended
5601
{
5602
newSamplerState = TR::CompilationInfo::SAMPLER_SUSPENDED; // samplerThread will pick up the new frequency
5603
jitConfig->samplingFrequency = MAX_SAMPLING_FREQUENCY; // sampling frequency is signed int so set it to 2^31 - 1
5604
persistentInfo->setLastTimeSamplerThreadWasSuspended(crtTime);
5605
if (J9VM_RUNTIME_STATE_IDLE == currentVMState)// since sampler is being suspended, bring VM back to active
5606
newVMState = J9VM_RUNTIME_STATE_ACTIVE;
5607
}
5608
}
5609
else
5610
{
5611
switch (samplerState)
5612
{
5613
case TR::CompilationInfo::SAMPLER_DEFAULT:
5614
// We may go IDLE if no active threads for the last 5 seconds
5615
if (numActiveThreads == 0 &&
5616
crtTime - persistentInfo->getLastTimeThreadsWereActive() > TR::Options::_waitTimeToEnterIdleMode) // 5 seconds of inactivity
5617
{
5618
newSamplerState = TR::CompilationInfo::SAMPLER_IDLE;
5619
jitConfig->samplingFrequency = TR::Options::getSamplingFrequencyInIdleMode(); // sample every 1000 ms
5620
foundThreadActiveDuringIdleMode = false; // reset this flag when we enter idle mode
5621
persistentInfo->setLastTimeSamplerThreadEnteredIdle(crtTime);
5622
}
5623
break;
5624
5625
case TR::CompilationInfo::SAMPLER_IDLE: // we may go DEFAULT or DEEP_IDLE
5626
if (numActiveThreads > 1 || (numActiveThreads == 1 && foundThreadActiveDuringIdleMode))
5627
{
5628
// exit idle mode
5629
newSamplerState = TR::CompilationInfo::SAMPLER_DEFAULT;
5630
jitConfig->samplingFrequency = TR::Options::getCmdLineOptions()->getSamplingFrequency();
5631
if (J9VM_RUNTIME_STATE_IDLE == currentVMState)
5632
newVMState = J9VM_RUNTIME_STATE_ACTIVE;
5633
}
5634
else if (numActiveThreads == 0)
5635
{
5636
uint64_t timeInIdle = crtTime - persistentInfo->getLastTimeSamplerThreadEnteredIdle();
5637
// 50 seconds of IDLE puts us in DEEPIDLE
5638
int32_t waitTimeToEnterDeepIdle = TR::Options::_waitTimeToEnterDeepIdleMode;
5639
// However, if we came from DEEP_IDLE and we enter DEEP_IDLE again we may want to wait less
5640
if (compInfo->getPrevSamplerState() == TR::CompilationInfo::SAMPLER_DEEPIDLE)
5641
waitTimeToEnterDeepIdle >>= 2; // 4 times less (12.5 sec)
5642
5643
if (timeInIdle > waitTimeToEnterDeepIdle)
5644
{
5645
if (TR::Options::_samplingFrequencyInDeepIdleMode > 0) // setting frequency==0 is a way of disabling DEEPIDLE
5646
{
5647
// The JIT will enter DEEP_IDLE
5648
//
5649
// Decide whether we need to notify the VM/GC
5650
// We want to ignore repeated IDLE<-->DEEP_IDLE transitions
5651
if (compInfo->getPrevSamplerState() != TR::CompilationInfo::SAMPLER_DEEPIDLE)
5652
{
5653
persistentInfo->setLastTimeSamplerThreadEnteredDeepIdle(crtTime);
5654
if (waitTimeInDeepIdleToNotifyVM == 0)
5655
newVMState = J9VM_RUNTIME_STATE_IDLE;
5656
}
5657
else
5658
{
5659
if ((J9VM_RUNTIME_STATE_ACTIVE == currentVMState) &&
5660
(waitTimeInDeepIdleToNotifyVM != -1) &&
5661
(crtTime - persistentInfo->getLastTimeSamplerThreadEnteredDeepIdle() >= waitTimeInDeepIdleToNotifyVM))
5662
newVMState = J9VM_RUNTIME_STATE_IDLE;
5663
}
5664
// Enter DEEPIDLE
5665
newSamplerState = TR::CompilationInfo::SAMPLER_DEEPIDLE;
5666
jitConfig->samplingFrequency = TR::Options::getSamplingFrequencyInDeepIdleMode();
5667
}
5668
else
5669
{
5670
if ((J9VM_RUNTIME_STATE_ACTIVE == currentVMState) &&
5671
(waitTimeInDeepIdleToNotifyVM != -1) &&
5672
(timeInIdle >= (waitTimeToEnterDeepIdle + waitTimeInDeepIdleToNotifyVM)))
5673
newVMState = J9VM_RUNTIME_STATE_IDLE;
5674
}
5675
}
5676
foundThreadActiveDuringIdleMode = false;
5677
}
5678
else if (numActiveThreads == 1)
5679
{
5680
// This sample will postpone the moment when we can move to DEEPIDLE
5681
persistentInfo->setLastTimeSamplerThreadEnteredIdle(crtTime);
5682
// Not enough samples to takes out of idle, but maybe next time
5683
foundThreadActiveDuringIdleMode = true;
5684
}
5685
break;
5686
5687
case TR::CompilationInfo::SAMPLER_DEEPIDLE: // we may go IDLE or directly DEFAULT
5688
if (numActiveThreads > 2)
5689
{
5690
newSamplerState = TR::CompilationInfo::SAMPLER_DEFAULT;
5691
jitConfig->samplingFrequency = TR::Options::getCmdLineOptions()->getSamplingFrequency();
5692
if (J9VM_RUNTIME_STATE_IDLE == currentVMState)
5693
newVMState = J9VM_RUNTIME_STATE_ACTIVE;
5694
}
5695
else if (numActiveThreads == 1)
5696
{
5697
newSamplerState = TR::CompilationInfo::SAMPLER_IDLE;
5698
jitConfig->samplingFrequency = TR::Options::getSamplingFrequencyInIdleMode();
5699
persistentInfo->setLastTimeSamplerThreadEnteredIdle(crtTime);
5700
foundThreadActiveDuringIdleMode = true; // another sample in idle mode will take us out of idle
5701
}
5702
else
5703
{
5704
if ((J9VM_RUNTIME_STATE_ACTIVE == currentVMState) &&
5705
(waitTimeInDeepIdleToNotifyVM != -1) &&
5706
(crtTime - persistentInfo->getLastTimeSamplerThreadEnteredDeepIdle() >= waitTimeInDeepIdleToNotifyVM))
5707
newVMState = J9VM_RUNTIME_STATE_IDLE;
5708
}
5709
break;
5710
5711
case TR::CompilationInfo::SAMPLER_SUSPENDED: // DisableJIT may request a samplerThread suspension
5712
newSamplerState = TR::CompilationInfo::SAMPLER_SUSPENDED; // samplerThread will pick up the new frequency
5713
jitConfig->samplingFrequency = MAX_SAMPLING_FREQUENCY; // sampling frequency is signed int so set it to 2^31 - 1
5714
persistentInfo->setLastTimeSamplerThreadWasSuspended(crtTime);
5715
if (J9VM_RUNTIME_STATE_IDLE == currentVMState) // since sampler is being suspended, bring VM back to active
5716
newVMState = J9VM_RUNTIME_STATE_ACTIVE;
5717
break;
5718
5719
default:
5720
TR_ASSERT(false, "samplerThreadProc: invalid state at this point: %d\n", samplerState);
5721
// try correction
5722
compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_DEFAULT);
5723
jitConfig->samplingFrequency = TR::Options::getCmdLineOptions()->getSamplingFrequency();
5724
} // end switch
5725
}
5726
5727
5728
// notify VM thread about state change
5729
if (newVMState != currentVMState)
5730
{
5731
if (vm->internalVMFunctions->updateVMRuntimeState(vm, newVMState) &&
5732
(TR::Options::getVerboseOption(TR_VerbosePerformance)))
5733
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%u\tSampling thread changed VM state to %u", (uint32_t)crtTime, newVMState);
5734
}
5735
// Check whether state has changed
5736
if (samplerState != newSamplerState)
5737
{
5738
compInfo->setSamplerState(newSamplerState);
5739
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
5740
{
5741
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%u\tSampling thread changed state to %s and frequency to %d ms",
5742
(uint32_t)crtTime, samplerThreadStateNames[compInfo->getSamplerState()], jitConfig->samplingFrequency);
5743
}
5744
}
5745
// FIXME:
5746
// Debug ext for the new fields
5747
}
5748
5749
/// Change inlining aggressiveness based on 'time' since we last entered
5750
/// JIT startup phase. Inlining aggressiveness is a number between 100 and 0
5751
/// with 100 meaning 'be very aggressive' and 0 meaning 'be very conservative'
5752
/// 'time' is not wall clock time because the algorithm would be dependent on
5753
/// machine speed/capability and load. Instead 'time' can be expressed in
5754
/// terms of CPU cycles consumed by the JVM or number of samples taken
5755
/// by application threads. Both are a loose measure of how much work the
5756
/// JVM has done.
5757
void inlinerAggressivenessLogic(TR::CompilationInfo *compInfo)
5758
{
5759
uint64_t crtAbstractTime, abstractTimeStartPoint;
5760
TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();
5761
// Abstract time can be measured since we entered startup or since we exited startup
5762
// If we want the latter then we have to change getVmTotalCpuTimeWhenStartupStateEntered() to getVmTotalCpuTimeWhenStartupStateExited()
5763
if (TR::Options::getCmdLineOptions()->getOption(TR_UseVmTotalCpuTimeAsAbstractTime))
5764
{
5765
if (compInfo->getCpuUtil()->isFunctional())
5766
{
5767
crtAbstractTime = compInfo->getCpuUtil()->getVmTotalCpuTime()/1000000; // convert from ns to ms
5768
abstractTimeStartPoint = persistentInfo->getVmTotalCpuTimeWhenStartupStateEntered()/1000000;
5769
}
5770
else // if we cannot get JVM cpu utilization, then the options to tune the algorithm will contain wrong values
5771
{
5772
// Force the usage of the other metric
5773
TR::Options::getCmdLineOptions()->setOption(TR_UseVmTotalCpuTimeAsAbstractTime, false);
5774
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
5775
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "Changed from JVM time to JIT samples for abstract time measurement");
5776
// Set default values
5777
TR::Options::_abstractTimeGracePeriod = DEFAULT_ABSTRACT_TIME_SAMPLES_GRACE_PERIOD;
5778
TR::Options::_abstractTimeToReduceInliningAggressiveness = DEFAULT_ABSTRACT_TIME_SAMPLES_TO_REDUCE_INLINING_AGGRESSIVENESS;
5779
5780
crtAbstractTime = persistentInfo->getJitTotalSampleCount();
5781
abstractTimeStartPoint = persistentInfo->getJitSampleCountWhenStartupStateEntered();
5782
}
5783
}
5784
else // use samples as abstract time
5785
{
5786
crtAbstractTime = persistentInfo->getJitTotalSampleCount();
5787
abstractTimeStartPoint = persistentInfo->getJitSampleCountWhenStartupStateEntered();
5788
}
5789
5790
5791
uint64_t abstractTimeElapsed = crtAbstractTime - abstractTimeStartPoint;
5792
int32_t inliningAggressiveness;
5793
if (abstractTimeElapsed <= TR::Options::_abstractTimeGracePeriod)
5794
{
5795
inliningAggressiveness = 100;
5796
}
5797
else if (abstractTimeElapsed >= TR::Options::_abstractTimeGracePeriod + TR::Options::_abstractTimeToReduceInliningAggressiveness)
5798
{
5799
inliningAggressiveness = 0;
5800
}
5801
else
5802
{
5803
inliningAggressiveness = 100 - 100 * (abstractTimeElapsed - (uint64_t)TR::Options::_abstractTimeGracePeriod) / (uint64_t)TR::Options::_abstractTimeToReduceInliningAggressiveness;
5804
}
5805
// write the computed inliningAggressiveness somewhere easily accessible
5806
if (inliningAggressiveness != persistentInfo->getInliningAggressiveness())
5807
{
5808
persistentInfo->setInliningAggressiveness(inliningAggressiveness);
5809
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
5810
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "inliningAggressiveness changed to %d", inliningAggressiveness);
5811
}
5812
}
5813
5814
5815
5816
static int32_t J9THREAD_PROC samplerThreadProc(void * entryarg)
5817
{
5818
J9JITConfig * jitConfig = (J9JITConfig *) entryarg;
5819
J9JavaVM * vm = jitConfig->javaVM;
5820
UDATA samplingPeriod = std::max(static_cast<UDATA>(TR::Options::_minSamplingPeriod), jitConfig->samplingFrequency);
5821
uint64_t lastProcNumCheck = 0;
5822
bool idleMode = false;
5823
uint64_t lastMinuteCheck = 0; // for activities that need to be done rarely (every minute)
5824
// initialize the startTime and elapsedTime here
5825
PORT_ACCESS_FROM_JAVAVM(vm);
5826
5827
TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);
5828
TR::PersistentInfo *persistentInfo = compInfo->getPersistentInfo();
5829
5830
persistentInfo->setClassLoadingPhaseGracePeriod(2*TR::Options::_classLoadingPhaseInterval);
5831
persistentInfo->setStartTime(j9time_current_time_millis());
5832
persistentInfo->setElapsedTime(0);
5833
uint64_t oldSyncTime = 0; // ms
5834
uint64_t crtTime = 0; // cached version of the volatile obtained by persistentInfo->getElapsedTime()
5835
5836
J9VMThread *samplerThread = 0;
5837
int rc = vm->internalVMFunctions->internalAttachCurrentThread
5838
(vm, &samplerThread, NULL,
5839
J9_PRIVATE_FLAGS_DAEMON_THREAD | J9_PRIVATE_FLAGS_NO_OBJECT |
5840
J9_PRIVATE_FLAGS_SYSTEM_THREAD | J9_PRIVATE_FLAGS_ATTACHED_THREAD,
5841
jitConfig->samplerThread);
5842
5843
if (rc != JNI_OK)
5844
{
5845
// attach failed
5846
j9thread_monitor_enter(jitConfig->samplerMonitor);
5847
compInfo->setSamplingThreadLifetimeState(TR::CompilationInfo::SAMPLE_THR_FAILED_TO_ATTACH);
5848
j9thread_monitor_notify_all(jitConfig->samplerMonitor);
5849
j9thread_exit(jitConfig->samplerMonitor);
5850
return JNI_ERR; // not reachable
5851
}
5852
// Inform the waiting thread that attach was successful
5853
j9thread_monitor_enter(jitConfig->samplerMonitor);
5854
compInfo->setSamplerThread(samplerThread);
5855
compInfo->setSamplingThreadLifetimeState(TR::CompilationInfo::SAMPLE_THR_ATTACHED);
5856
j9thread_monitor_notify_all(jitConfig->samplerMonitor);
5857
j9thread_monitor_exit(jitConfig->samplerMonitor);
5858
5859
// Read some stats about SCC. This code could have stayed in aboutToBootstrap,
5860
// but here we execute it on a separate thread and hide its overhead
5861
5862
if (TR::Options::isAnyVerboseOptionSet())
5863
{
5864
OMRPORT_ACCESS_FROM_J9PORT(PORTLIB);
5865
char timestamp[32];
5866
bool incomplete;
5867
omrstr_ftime_ex(timestamp, sizeof(timestamp), "%b %d %H:%M:%S %Y", persistentInfo->getStartTime(), OMRSTR_FTIME_FLAG_LOCAL);
5868
TR_VerboseLog::CriticalSection vlogLock;
5869
TR_VerboseLog::writeLine(TR_Vlog_INFO, "StartTime: %s", timestamp);
5870
uint64_t phMemAvail = compInfo->computeAndCacheFreePhysicalMemory(incomplete);
5871
if (phMemAvail != OMRPORT_MEMINFO_NOT_AVAILABLE)
5872
TR_VerboseLog::writeLine(TR_Vlog_INFO, "Free Physical Memory: %lld MB %s", phMemAvail >> 20, incomplete?"estimated":"");
5873
else
5874
TR_VerboseLog::writeLine(TR_Vlog_INFO, "Free Physical Memory: Unavailable");
5875
#if defined(J9VM_OPT_SHARED_CLASSES) && defined(J9VM_INTERP_AOT_RUNTIME_SUPPORT)
5876
// When we read the SCC data we set isWarmSCC either to Yes or No. Otherwise it remains in maybe state.
5877
J9SharedClassJavacoreDataDescriptor* javacoreData = compInfo->getAddrOfJavacoreData();
5878
if (compInfo->isWarmSCC() != TR_maybe && TR::Options::getVerboseOption(TR_VerbosePerformance))
5879
{
5880
TR_VerboseLog::writeLine(TR_Vlog_INFO,"Shared Class Cache Information:");
5881
TR_VerboseLog::writeLine(TR_Vlog_INFO,"\tSCCname:%s SCCpath:%s", javacoreData->cacheName, javacoreData->cacheDir);
5882
TR_VerboseLog::writeLine(TR_Vlog_INFO,"\tSCC_stats_bytes: size=%u free=%u ROMClass=%u AOTCode=%u AOTData=%u JITHint=%u JITProfile=%u",
5883
javacoreData->cacheSize,
5884
javacoreData->freeBytes,
5885
javacoreData->romClassBytes,
5886
javacoreData->aotBytes,
5887
javacoreData->aotDataBytes,
5888
javacoreData->jitHintDataBytes,
5889
javacoreData->jitProfileDataBytes);
5890
TR_VerboseLog::writeLine(TR_Vlog_INFO,"\tSCC_stats_#: ROMClasses=%u AOTMethods=%u AOTDataEntries=%u AOTHints=%u AOTJitProfiles=%u",
5891
javacoreData->numROMClasses,
5892
javacoreData->numAOTMethods,
5893
javacoreData->numAotDataEntries,
5894
javacoreData->numJitHints,
5895
javacoreData->numJitProfiles);
5896
}
5897
#endif
5898
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseHWProfiler))
5899
{
5900
TR_VerboseLog::writeLine(TR_Vlog_INFO, "Runtime Instrumentation Information:");
5901
if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())
5902
{
5903
TR_VerboseLog::writeLine(TR_Vlog_INFO, "\tRuntime Instrumentation is Enabled");
5904
if (compInfo->getPersistentInfo()->isRuntimeInstrumentationRecompilationEnabled())
5905
{
5906
TR_VerboseLog::writeLine(TR_Vlog_INFO, "\tRuntime Instrumentation based Recompilation enabled");
5907
}
5908
}
5909
else
5910
{
5911
TR_VerboseLog::writeLine(TR_Vlog_INFO, "\tRuntime Instrumentation is not Enabled");
5912
}
5913
}
5914
5915
if (compInfo->isHypervisorPresent())
5916
{
5917
J9HypervisorVendorDetails vendor;
5918
IDATA res = j9hypervisor_get_hypervisor_info(&vendor);
5919
TR_VerboseLog::writeLine(TR_Vlog_INFO, "Running on hypervisor %s. CPU entitlement = %3.2f",
5920
res==0 ? vendor.hypervisorName : "", compInfo->getGuestCpuEntitlement());
5921
}
5922
else
5923
{
5924
TR_VerboseLog::writeLine(TR_Vlog_INFO, "CPU entitlement = %3.2f", compInfo->getJvmCpuEntitlement());
5925
}
5926
} // if (TR::Options::isAnyVerboseOptionSet())
5927
5928
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableScorchingSampleThresholdScalingBasedOnNumProc))
5929
{
5930
// We want to become more conservative with scorching compilations for large number of
5931
// processors because JIT profiling is very taxing due to cache coherence issues
5932
// For a low number of processors (smaller than lowerBoundNumProc) we want our default
5933
// scorchingSampleThreshold of 240. For a large number of processors (larger than
5934
// upperBoundNumProc we want a small scorching threshold, say 60 (conservativeScorchingSampleThreshold)
5935
// For a number of processors between lowerBoundNumProc and upperBoundNumProc we want
5936
// to decrease the scorchingSampleThreshold linearly
5937
if (TR::Compiler->target.numberOfProcessors() <= TR::Options::_lowerBoundNumProcForScaling ||
5938
TR::Options::_scorchingSampleThreshold <= TR::Options::_conservativeScorchingSampleThreshold)
5939
{
5940
// Common case. No change in scorchingSampleThreshold
5941
}
5942
else
5943
{
5944
if (TR::Compiler->target.numberOfProcessors() >= TR::Options::_upperBoundNumProcForScaling)
5945
{
5946
// We want a smaller value for R::Options::_scorchingSampleThreshold
5947
TR::Options::_scorchingSampleThreshold = TR::Options::_conservativeScorchingSampleThreshold;
5948
}
5949
else
5950
{
5951
TR::Options::_scorchingSampleThreshold = TR::Options::_conservativeScorchingSampleThreshold +
5952
(TR::Options::_upperBoundNumProcForScaling - TR::Compiler->target.numberOfProcessors())*
5953
(TR::Options::_scorchingSampleThreshold - TR::Options::_conservativeScorchingSampleThreshold) /
5954
(TR::Options::_upperBoundNumProcForScaling - TR::Options::_lowerBoundNumProcForScaling);
5955
// Note that above we cannot divide by 0 due to the way the if-then-else is structured
5956
}
5957
if (TR::Options::isAnyVerboseOptionSet())
5958
{
5959
float scorchingCpuTarget = TR::Options::_scorchingSampleThreshold <= TR::Options::_sampleInterval ? 100.0 :
5960
100.0 * TR::Options::_sampleInterval / TR::Options::_scorchingSampleThreshold;
5961
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "scorchingSampleThreshold changed to %d (%3.1f%%)",
5962
TR::Options::_scorchingSampleThreshold, scorchingCpuTarget);
5963
}
5964
}
5965
}
5966
5967
float loadFactorAdjustment = 100.0/(compInfo->getNumTargetCPUs()*TR::Options::_availableCPUPercentage);
5968
if (TR::Options::getCmdLineOptions()->getOption(TR_AssumeStartupPhaseUntilToldNotTo))
5969
{
5970
persistentInfo->setClassLoadingPhase(true); // start in CLP
5971
vm->internalVMFunctions->jvmPhaseChange(vm, J9VM_PHASE_STARTUP); // The VM state should be STARTUP
5972
}
5973
#ifdef J9VM_OPT_JAVA_OFFLOAD_SUPPORT
5974
if (vm->javaOffloadSwitchOnWithReasonFunc != 0)
5975
(*vm->javaOffloadSwitchOnWithReasonFunc)(samplerThread, J9_JNI_OFFLOAD_SWITCH_JIT_SAMPLER_THREAD);
5976
#endif
5977
5978
TR_J9VMBase *fe = TR_J9VMBase::get(jitConfig, 0);
5979
5980
j9thread_set_name(j9thread_self(), "JIT Sampler");
5981
while (!shutdownSamplerThread)
5982
{
5983
while (!shutdownSamplerThread && // watch for shutdown signals
5984
j9thread_sleep_interruptable((IDATA) samplingPeriod, 0) == 0) // Anything non-0 is an error condition so we shouldn't do the sampling //!= J9THREAD_INTERRUPTED)
5985
{
5986
J9VMThread * currentThread;
5987
5988
persistentInfo->updateElapsedTime(samplingPeriod);
5989
crtTime += samplingPeriod;
5990
5991
// periodic chores
5992
// FIXME: make a constant/macro for the period, and make it 100
5993
if (crtTime - oldSyncTime >= 100) // every 100 ms
5994
{
5995
// There is some imprecision regarding the way we maintain elapsed time
5996
// hence, we need to correct it periodically
5997
//
5998
crtTime = j9time_current_time_millis() - persistentInfo->getStartTime();
5999
persistentInfo->setElapsedTime(crtTime);
6000
oldSyncTime = crtTime;
6001
6002
TR_DebuggingCounters::transferSmallCountsToTotalCounts();
6003
6004
if (TR::Options::_compilationExpirationTime > 0 &&
6005
!persistentInfo->getDisableFurtherCompilation())
6006
{
6007
if (crtTime >= 1000*TR::Options::_compilationExpirationTime)
6008
{
6009
persistentInfo->setDisableFurtherCompilation(true) ;
6010
if (fe->isLogSamplingSet())
6011
{
6012
TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING,"Disable further compilation");
6013
}
6014
}
6015
}
6016
6017
if (compInfo) // don't need this
6018
{
6019
// Implement the watch-dog for the compilation thread
6020
// We must detect situations where compilation requests get stuck for
6021
// a long time in the compilation queue, because the priority of the
6022
// compilation thread is too low
6023
//
6024
if (compInfo->dynamicThreadPriority() &&
6025
compInfo->getCompilationLagUnlocked() == TR::CompilationInfo::LARGE_LAG)
6026
compInfo->changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 12);
6027
}
6028
6029
int32_t heartbeatInterval = TR::Options::getSamplingHeartbeatInterval();
6030
if (TR::Options::getVerboseOption(TR_VerboseHeartbeat) && heartbeatInterval > 0)
6031
{
6032
compInfo->_stats._heartbeatWindowCount++;
6033
if (compInfo->_stats._heartbeatWindowCount == heartbeatInterval)
6034
{
6035
samplingObservationsLogic(jitConfig, compInfo);
6036
compInfo->_stats._heartbeatWindowCount = 0;
6037
}
6038
}
6039
6040
// Default: Every minute
6041
if (crtTime - lastMinuteCheck >= (TR::Options::_virtualMemoryCheckFrequencySec * 1000))
6042
{
6043
lastMinuteCheck = crtTime;
6044
#if defined(TR_TARGET_32BIT) && (defined(WINDOWS) || defined(LINUX) || defined(J9ZOS390))
6045
// On 32 bit Windows, Linux, and 31 bit z/OS, monitor the virtual memory available to the user
6046
lowerCompilationLimitsOnLowVirtualMemory(compInfo, NULL);
6047
#endif
6048
6049
#if defined(J9VM_OPT_SHARED_CLASSES) && defined(J9VM_INTERP_AOT_RUNTIME_SUPPORT)
6050
// Emit SCC tracepoint
6051
if (TR::Options::sharedClassCache() && TrcEnabled_Trc_JIT_SCCInfo &&
6052
vm->sharedClassConfig && vm->sharedClassConfig->getJavacoreData)
6053
{
6054
J9SharedClassJavacoreDataDescriptor* scc = compInfo->getAddrOfJavacoreData();
6055
memset(scc, 0, sizeof(J9SharedClassJavacoreDataDescriptor));
6056
vm->sharedClassConfig->getJavacoreData(vm, scc); // need to rebuild javacore data or else it will be stale
6057
Trc_JIT_SCCInfo(samplerThread, scc->cacheName, scc->cacheDir, scc->cacheSize, scc->freeBytes, scc->softMaxBytes,
6058
scc->romClassBytes, scc->aotBytes, scc->aotDataBytes, scc->jitHintDataBytes, scc->jitProfileDataBytes,
6059
scc->numROMClasses, scc->numAOTMethods, fe->sharedCache()->getSharedCacheDisabledReason());
6060
}
6061
#endif
6062
} // Default: Every minute
6063
} // every 100 ms
6064
6065
//classLoadPhaseReanalyzed = classLoadPhaseLogic(jitConfig, compInfo); // moved down
6066
6067
// TODO: Does this need to be synchronized with the one that happens at shutdown?
6068
// TODO: If this has too much overhead, it can be added to the
6069
// "periodic chores" section so it's done less often. I've stuck it here
6070
// because I'm paranoid about the 32-bit counters overflowing.
6071
//
6072
TR::DebugCounterGroup *dynamicCounters = TR::CompilationInfo::get(jitConfig)->getPersistentInfo()->getDynamicCounters();
6073
if (dynamicCounters)
6074
dynamicCounters->accumulate();
6075
if ( TR::Options::getCmdLineOptions()->getDebugCounterWarmupSeconds() > persistentInfo->getLastDebugCounterResetSeconds()
6076
&& TR::Options::getCmdLineOptions()->getDebugCounterWarmupSeconds() <= crtTime/1000)
6077
{
6078
if (TR::Options::isAnyVerboseOptionSet())
6079
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "Reset debug counters at t=%dms", (int)crtTime);
6080
persistentInfo->setLastDebugCounterResetSeconds(crtTime/1000);
6081
if (dynamicCounters)
6082
dynamicCounters->resetAll();
6083
TR::DebugCounterGroup *staticCounters = TR::CompilationInfo::get(jitConfig)->getPersistentInfo()->getStaticCounters();
6084
if (staticCounters)
6085
staticCounters->resetAll();
6086
}
6087
6088
jitConfig->samplingTickCount++;
6089
uint32_t numActiveThreads = 0;
6090
6091
j9thread_monitor_enter(vm->vmThreadListMutex);
6092
currentThread = vm->mainThread;
6093
6094
do {
6095
#if defined(J9VM_INTERP_ATOMIC_FREE_JNI)
6096
if (!currentThread->inNative)
6097
#endif /* J9VM_INTERP_ATOMIC_FREE_JNI */
6098
{
6099
if (currentThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS)
6100
{
6101
vm->internalVMFunctions->J9SignalAsyncEvent(vm, currentThread, jitConfig->sampleInterruptHandlerKey);
6102
currentThread->stackOverflowMark = (UDATA *) J9_EVENT_SOM_VALUE;
6103
numActiveThreads++;
6104
}
6105
}
6106
} while ((currentThread = currentThread->linkNext) != vm->mainThread);
6107
6108
compInfo->_stats._sampleMessagesSent += numActiveThreads;
6109
compInfo->_intervalStats._samplesSentInInterval += numActiveThreads;
6110
compInfo->setNumAppThreadsActive(numActiveThreads, crtTime);
6111
6112
if (compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_IDLE ||
6113
compInfo->getSamplerState() == TR::CompilationInfo::SAMPLER_DEEPIDLE)
6114
compInfo->_stats._ticksInIdleMode++;
6115
6116
// number of processors might change
6117
if (crtTime > lastProcNumCheck + 300000) // every 5 mins
6118
{
6119
if (trPersistentMemory && TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJitMemory))
6120
trPersistentMemory->printMemStatsToVlog();
6121
6122
// time to reevaluate the number of processors
6123
compInfo->computeAndCacheCpuEntitlement();
6124
uint32_t tempProc = compInfo->getNumTargetCPUs(); // TODO is this needed?
6125
//compInfo->setNumTargetCPUs((tempProc = j9sysinfo_get_number_CPUs_by_type(J9PORT_CPU_TARGET)) > 0 ? tempProc : 1);
6126
6127
6128
loadFactorAdjustment = 100.0/(compInfo->getNumTargetCPUs()*TR::Options::_availableCPUPercentage);
6129
6130
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseJitMemory))
6131
{
6132
bool incomplete;
6133
TR_PersistentMemory *persistentMemory = compInfo->persistentMemory();
6134
TR_VerboseLog::CriticalSection vlogLock;
6135
uint64_t phMemAvail = compInfo->computeAndCacheFreePhysicalMemory(incomplete);
6136
if (phMemAvail != OMRPORT_MEMINFO_NOT_AVAILABLE)
6137
TR_VerboseLog::writeLine(TR_Vlog_INFO, "Free Physical Memory: %lld MB %s", phMemAvail >> 20, incomplete ? "estimated" : "");
6138
else
6139
TR_VerboseLog::writeLine(TR_Vlog_INFO, "Free Physical Memory: Unavailable");
6140
6141
//TR_VerboseLog::writeLine(TR_Vlog_MEMORY,"t=%6u JIT memory usage", (uint32_t)crtTime);
6142
//TR_VerboseLog::writeLine(TR_Vlog_MEMORY, "FIXME: Report JIT memory usage\n");
6143
// Show stats on assumptions
6144
// assumptionTableMutex is not used, so the numbers may be a little off
6145
TR_VerboseLog::writeLine(TR_Vlog_MEMORY,"\tStats on assumptions:");
6146
TR_RuntimeAssumptionTable * rat = persistentInfo->getRuntimeAssumptionTable();
6147
for (int32_t i=0; i < LastAssumptionKind; i++)
6148
TR_VerboseLog::writeLine(TR_Vlog_MEMORY,"\tAssumptionType=%d allocated=%d reclaimed=%d", i, rat->getAssumptionCount(i), rat->getReclaimedAssumptionCount(i));
6149
}
6150
#if defined(WINDOWS) && defined(TR_TARGET_32BIT)
6151
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseVMemAvailable))
6152
{
6153
J9MemoryInfo memInfo;
6154
if (j9sysinfo_get_memory_info(&memInfo) == 0 &&
6155
memInfo.availVirtual != J9PORT_MEMINFO_NOT_AVAILABLE)
6156
{
6157
TR_VerboseLog::writeLineLocked(TR_Vlog_MEMORY,"t=%6u VMemAv=%u MB", (uint32_t)crtTime, (uint32_t)(memInfo.availVirtual>>20));
6158
}
6159
}
6160
#endif
6161
lastProcNumCheck = crtTime;
6162
}
6163
uint32_t loadFactor = (uint32_t) ((numActiveThreads==0?1:numActiveThreads)*loadFactorAdjustment);
6164
persistentInfo->setLoadFactor(loadFactor);
6165
// if the loadfactor is 0, set a default of 1. This will allow us to
6166
// temporarily stop the sampling process by setting a very high samplingFrequency
6167
//
6168
if (loadFactor == 0)
6169
loadFactor = 1;
6170
6171
// The following may change the state of the samplerThread and the sampling frequency
6172
// Must be protected by vm->vmThreadListMutex
6173
samplerThreadStateLogic(compInfo, fe, numActiveThreads);
6174
6175
UDATA samplingFreq = jitConfig->samplingFrequency;
6176
// TODO: Should the sampling frequency types in TR::Options be changed to more closely match the J9JITConfig types?
6177
samplingPeriod = std::max(static_cast<UDATA>(TR::Options::_minSamplingPeriod), (samplingFreq == MAX_SAMPLING_FREQUENCY) ? samplingFreq : samplingFreq * loadFactor);
6178
6179
j9thread_monitor_exit(vm->vmThreadListMutex);
6180
6181
// Sample every 10 seconds
6182
static uint64_t lastTimeCpuUsageCircularBufferUpdated = 0;
6183
if ((crtTime - lastTimeCpuUsageCircularBufferUpdated) > (TR::Options::_cpuUsageCircularBufferUpdateFrequencySec * 1000))
6184
{
6185
lastTimeCpuUsageCircularBufferUpdated = crtTime;
6186
6187
if (compInfo->getCpuUtil()->isCpuUsageCircularBufferFunctional())
6188
compInfo->getCpuUtil()->updateCpuUsageCircularBuffer(jitConfig);
6189
}
6190
6191
// Determine if we need to turn GCR counting off. GCR counting is known to have high overhead.
6192
// If more than a certain number of GCR induced compilations is queued, turn off counting.
6193
if (persistentInfo->_countForRecompile) // No need to check if GCR is disabled
6194
{
6195
if (TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods) ||
6196
TR::Options::getJITCmdLineOptions()->getOption(TR_EnableMultipleGCRPeriods))
6197
{
6198
if (compInfo->getNumGCRRequestsQueued() > TR::Options::_GCRQueuedThresholdForCounting + GCR_HYSTERESIS)
6199
{
6200
persistentInfo->_countForRecompile = 0; // disable counting
6201
// write a message in the vlog
6202
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseJitState, TR_VerbosePerformance))
6203
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u GCR disabled; GCR queued=%d", (uint32_t)crtTime, compInfo->getNumGCRRequestsQueued());
6204
}
6205
}
6206
}
6207
6208
// sample every _classLoadingPhaseInterval (i.e. 500 ms)
6209
static uint64_t lastTimeClassLoadPhaseAnalyzed = 0;
6210
uint32_t diffTime = (uint32_t)(crtTime - lastTimeClassLoadPhaseAnalyzed);
6211
6212
if (diffTime >= (uint32_t)TR::Options::_classLoadingPhaseInterval) // time to re-analyze
6213
{
6214
lastTimeClassLoadPhaseAnalyzed = crtTime;
6215
6216
// update the JVM cpu utilization if needed
6217
if (compInfo->getCpuUtil()->isFunctional())
6218
compInfo->getCpuUtil()->updateCpuUtil(jitConfig);
6219
6220
if (CPUThrottleEnabled(compInfo, crtTime))
6221
{
6222
// Calculate CPU utilization and set throttle flag
6223
// This code needs to stay before jitStateLogic because the decision to throttle
6224
// application threads (taken in jitStateLogic) depends on the decision to throttle
6225
// the compilation threads
6226
CalculateOverallCompCPUUtilization(compInfo, crtTime, samplerThread);
6227
CPUThrottleLogic(compInfo, crtTime);
6228
}
6229
// Check if we need to calculate CPU utilization for debug purposes
6230
else if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompilationThreads, TR_VerboseCompilationThreadsDetails) || TrcEnabled_Trc_JIT_CompCPU)
6231
{
6232
CalculateOverallCompCPUUtilization(compInfo, crtTime, samplerThread);
6233
}
6234
6235
// Update information about global samples
6236
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableDynamicSamplingWindow))
6237
compInfo->getJitSampleInfoRef().update(crtTime, TR::Recompilation::globalSampleCount);
6238
6239
// determine whether we're in class-load phase
6240
classLoadPhaseLogic(jitConfig, compInfo, diffTime);
6241
// fprintf(stderr, "samplingPeriod=%u numProcs=%u numActiveThreads=%u samplingFrequency=%d\n", samplingPeriod, compInfo->getNumTargetCPUs(), numActiveThreads, jitConfig->samplingFrequency);
6242
6243
// compute jit state
6244
jitStateLogic(jitConfig, compInfo, diffTime); // Update JIT state before going to sleep
6245
6246
// detect high code cache occupancy
6247
TR::CodeCacheManager *manager = TR::CodeCacheManager::instance();
6248
size_t usedCacheSize = manager->getCurrTotalUsedInBytes();
6249
size_t threshold = manager->codeCacheConfig().highCodeCacheOccupancyThresholdInBytes();
6250
if ((usedCacheSize > threshold) && !highCodeCacheOccupancyThresholdReached)
6251
{
6252
highCodeCacheOccupancyThresholdReached = true;
6253
if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerbosePerformance))
6254
{
6255
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%6u JIT entered high code cache occupancy state", (uint32_t)crtTime);
6256
}
6257
}
6258
else if ((usedCacheSize <= threshold) && highCodeCacheOccupancyThresholdReached)
6259
{
6260
highCodeCacheOccupancyThresholdReached = false;
6261
if (TR::Options::getCmdLineOptions()->isAnyVerboseOptionSet(TR_VerbosePerformance))
6262
{
6263
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%6u JIT exited high code cache occupancy state", (uint32_t)crtTime);
6264
}
6265
}
6266
6267
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
6268
// iProfilerActivationLogic must stay after classLoadPhaseLogic and jitStateLogic
6269
iProfilerActivationLogic(jitConfig, compInfo);
6270
#endif // J9VM_INTERP_PROFILING_BYTECODES
6271
inlinerAggressivenessLogic(compInfo);
6272
} // if
6273
} // while
6274
6275
// This thread has been interrupted or shutdownSamplerThread flag was set
6276
// Sleep just a tiny bit just in case shutdownSamplerThread is set just prior going to sleep
6277
//
6278
samplingPeriod = TR::Options::_minSamplingPeriod; // sleep 10 ms and then take new decisions
6279
// The elapsed time is now different
6280
crtTime = j9time_current_time_millis()-persistentInfo->getStartTime();
6281
persistentInfo->setElapsedTime(crtTime);
6282
oldSyncTime = crtTime;
6283
}
6284
6285
// Sampling thread is destroyed in stage 17 (LIBRARIES_UNLOAD)
6286
// We better not be holding any monitors at this point
6287
vm->internalVMFunctions->DetachCurrentThread((JavaVM *) vm);
6288
6289
j9thread_monitor_enter(vm->vmThreadListMutex);
6290
compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_STOPPED);
6291
j9thread_monitor_exit(vm->vmThreadListMutex);
6292
6293
j9thread_monitor_enter(jitConfig->samplerMonitor);
6294
// Tell the application thread that samplerThread has finished executing
6295
compInfo->setSamplingThreadLifetimeState(TR::CompilationInfo::SAMPLE_THR_DESTROYED);
6296
j9thread_monitor_notify_all(jitConfig->samplerMonitor);
6297
6298
#ifdef J9VM_OPT_JAVA_OFFLOAD_SUPPORT
6299
if (vm->javaOffloadSwitchOffNoEnvWithReasonFunc != 0)
6300
(*vm->javaOffloadSwitchOffNoEnvWithReasonFunc)(vm, j9thread_self(), J9_JNI_OFFLOAD_SWITCH_JIT_SAMPLER_THREAD);
6301
#endif
6302
6303
j9thread_exit(jitConfig->samplerMonitor); /* exit the monitor and terminate the thread */
6304
6305
/* NO GUARANTEED EXECUTION BEYOND THIS POINT */
6306
6307
return 0;
6308
}
6309
6310
6311
void jitHookJNINativeRegistered(J9HookInterface **hookInterface, UDATA eventNum, void *eventData, void *userData)
6312
{
6313
J9VMJNINativeRegisteredEvent *event = (J9VMJNINativeRegisteredEvent *) eventData;
6314
J9VMThread *vmThread = event->currentThread;
6315
J9Method *method = event->nativeMethod;
6316
void *newAddress = event->nativeMethodAddress;
6317
bool somethingWasDone = false;
6318
6319
6320
// First check if a thunk has been compiled for this native
6321
// If so, go and patch the word in the preprologue
6322
J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;
6323
if (jitConfig == 0)
6324
return; // if a hook gets called after freeJitConfig then not much else we can do
6325
6326
TR_FrontEnd *vm = TR_J9VMBase::get(jitConfig, vmThread);
6327
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
6328
getOutOfIdleStates(TR::CompilationInfo::SAMPLER_DEEPIDLE, compInfo, "JNI registered");
6329
6330
uint8_t *thunkStartPC = (uint8_t *)TR::CompilationInfo::getPCIfCompiled(method);
6331
if (thunkStartPC)
6332
{
6333
// The address in the word immediately before the linkage info
6334
uintptr_t **addressSlot = (uintptr_t **)(thunkStartPC - (4 + sizeof(uintptr_t)));
6335
6336
// Write the address slot
6337
*addressSlot = (uintptr_t *) newAddress;
6338
6339
// Sync/Flush
6340
TR::CodeGenerator::syncCode((uint8_t*)addressSlot, sizeof(uintptr_t));
6341
6342
somethingWasDone = true;
6343
}
6344
6345
// Notify the assumptions table that the native has been registered
6346
{
6347
OMR::CriticalSection registerNatives(assumptionTableMutex);
6348
TR_RuntimeAssumptionTable *rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();
6349
OMR::RuntimeAssumption **headPtr = rat->getBucketPtr(RuntimeAssumptionOnRegisterNative, TR_RuntimeAssumptionTable::hashCode((uintptr_t)method));
6350
TR_PatchJNICallSite *cursor = (TR_PatchJNICallSite *)(*headPtr);
6351
while (cursor)
6352
{
6353
if (cursor->matches((uintptr_t)method))
6354
{
6355
cursor->compensate(vm, 0, newAddress);
6356
}
6357
cursor = (TR_PatchJNICallSite*)cursor->getNext();
6358
}
6359
}
6360
6361
if (somethingWasDone)
6362
compInfo->setAllCompilationsShouldBeInterrupted();
6363
}
6364
6365
6366
static UDATA jitReleaseCodeStackWalkFrame(J9VMThread *vmThread, J9StackWalkState *walkState)
6367
{
6368
J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;
6369
J9JITExceptionTable *metaData = walkState->jitInfo;
6370
6371
if (metaData)
6372
{
6373
int32_t numBlocks = 0;
6374
int32_t numLiveBlocks = 0;
6375
for (OMR::FaintCacheBlock *cursor = (OMR::FaintCacheBlock *)jitConfig->methodsToDelete;
6376
cursor; cursor = cursor->_next)
6377
{
6378
if (metaData == cursor->_metaData)
6379
{
6380
cursor->_isStillLive = true;
6381
//fprintf(stderr, " --ccr-- still live %p\n", cursor->metaData->startPC);
6382
}
6383
if (cursor->_isStillLive)
6384
numLiveBlocks++;
6385
numBlocks++;
6386
}
6387
6388
// All the remaining blocks are still live - there is nothing
6389
// to collect. Abort the rest of the stack walk now.
6390
//
6391
if (numBlocks == numLiveBlocks)
6392
return J9_STACKWALK_STOP_ITERATING;
6393
}
6394
6395
return J9_STACKWALK_KEEP_ITERATING;
6396
}
6397
6398
static void jitReleaseCodeStackWalk(OMR_VMThread *omrVMThread, condYieldFromGCFunctionPtr condYield = NULL)
6399
6400
{
6401
J9VMThread *vmThread = (J9VMThread *)omrVMThread->_language_vmthread;
6402
J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;
6403
if (!jitConfig)
6404
return; // not much we can do if the hook is called after freeJitConfig
6405
6406
if (!jitConfig->methodsToDelete)
6407
return; // nothing to do
6408
6409
6410
bool yieldHappened = false;
6411
bool doStackWalkForThread = true;
6412
6413
bool isRealTimeGC = TR::Options::getCmdLineOptions()->realTimeGC();
6414
do
6415
{
6416
J9VMThread *thread = vmThread;
6417
yieldHappened = false;
6418
do
6419
{
6420
if (isRealTimeGC && !TR::Options::getCmdLineOptions()->getOption(TR_DisableIncrementalCCR))
6421
doStackWalkForThread = (thread->dropFlags & 0x1) ? false : true;
6422
6423
if (doStackWalkForThread)
6424
{
6425
J9StackWalkState walkState;
6426
walkState.flags = J9_STACKWALK_ITERATE_HIDDEN_JIT_FRAMES | J9_STACKWALK_ITERATE_FRAMES | J9_STACKWALK_SKIP_INLINES;
6427
walkState.skipCount = 0;
6428
walkState.frameWalkFunction = jitReleaseCodeStackWalkFrame;
6429
walkState.walkThread = thread;
6430
vmThread->javaVM->walkStackFrames(vmThread, &walkState);
6431
6432
if (isRealTimeGC && !TR::Options::getCmdLineOptions()->getOption(TR_DisableIncrementalCCR))
6433
{
6434
thread->dropFlags |= 0x1;
6435
yieldHappened = condYield(omrVMThread, J9_GC_METRONOME_UTILIZATION_COMPONENT_JIT);
6436
}
6437
}
6438
6439
if (!yieldHappened)
6440
thread = thread->linkNext;
6441
}
6442
while ((thread != vmThread) && !yieldHappened);
6443
}
6444
while (yieldHappened);
6445
6446
6447
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
6448
TR_RuntimeAssumptionTable * rat = compInfo->getPersistentInfo()->getRuntimeAssumptionTable();
6449
// Now walk all the faint blocks, and collect the ones that are not still live
6450
//
6451
OMR::FaintCacheBlock *cursor = (OMR::FaintCacheBlock *)jitConfig->methodsToDelete;
6452
OMR::FaintCacheBlock *prev = 0;
6453
6454
uintptr_t rangeStartPC = 0;
6455
uintptr_t rangeEndPC = 0;
6456
uintptr_t rangeColdStartPC = 0;
6457
uintptr_t rangeColdEndPC = 0;
6458
6459
uintptr_t rangeStartMD = 0;
6460
uintptr_t rangeEndMD = 0;
6461
6462
bool firstRange = true;
6463
bool coldRangeUninitialized = true;
6464
6465
bool hasMethodOverrideAssumptions = false;
6466
bool hasClassExtendAssumptions = false;
6467
bool hasClassUnloadAssumptions = false;
6468
bool hasClassRedefinitionAssumptions = false;
6469
6470
cursor = (OMR::FaintCacheBlock *)jitConfig->methodsToDelete;
6471
prev = 0;
6472
int32_t condYieldCounter = 0;
6473
6474
// cmvc 192753
6475
// It is not safe to exit this function until all faint records have been processed.
6476
// If we do the following can happen: (1) method A get compiled and recompiled creating a faint record
6477
// (2) Method A gets unloaded and both bodies get reclaimed. If the faint block for A is not
6478
// processed before the end of the GC cycle, a compilation for method B can reuse the exact
6479
// same spot where method A used to be. When we finally process the faint record for A we
6480
// will reclaim space belonging to B
6481
while (cursor/*&& (condYieldCounter < 2)*/)
6482
{
6483
if (!cursor->_isStillLive)
6484
{
6485
J9JITExceptionTable *metaData = cursor->_metaData;
6486
6487
// Remove From List
6488
if (prev)
6489
prev->_next = cursor->_next;
6490
else
6491
jitConfig->methodsToDelete = (void*) cursor->_next;
6492
6493
// Free storage for cursor and the code cache - CAREFUL!! iterating on cursor
6494
//
6495
OMR::FaintCacheBlock *next = cursor->_next;
6496
jitReleaseCodeCollectMetaData(jitConfig, vmThread, metaData, cursor);
6497
cursor = next;
6498
if (isRealTimeGC && !TR::Options::getCmdLineOptions()->getOption(TR_DisableIncrementalCCR))
6499
condYieldCounter += condYield(omrVMThread, J9_GC_METRONOME_UTILIZATION_COMPONENT_JIT);
6500
6501
continue;
6502
}
6503
6504
prev = cursor;
6505
cursor = cursor->_next;
6506
}
6507
6508
/*
6509
* After we have determined what can be reclaimed for the current pass,
6510
* we must clear the _isStillLive flag or we will never again consider
6511
* the faint blocks as candidates for reclaimation.
6512
*/
6513
for (cursor = (OMR::FaintCacheBlock *)jitConfig->methodsToDelete; cursor; cursor = cursor->_next)
6514
{
6515
cursor->_isStillLive = false;
6516
}
6517
6518
if (isRealTimeGC && !TR::Options::getCmdLineOptions()->getOption(TR_DisableIncrementalCCR))
6519
{ //clear flags
6520
J9VMThread *thr = vmThread;
6521
do
6522
{
6523
thr->dropFlags &=0x0;
6524
thr = thr->linkNext;
6525
}
6526
while (thr != vmThread);
6527
}
6528
6529
6530
}
6531
6532
static void jitHookReleaseCodeGlobalGCEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
6533
{
6534
MM_GlobalGCEndEvent *event = (MM_GlobalGCEndEvent *)eventData;
6535
J9VMThread *vmThread = (J9VMThread*)event->currentThread->_language_vmthread;
6536
jitReleaseCodeStackWalk(vmThread->omrVMThread);
6537
jitReclaimMarkedAssumptions(true);
6538
}
6539
6540
static void jitHookReleaseCodeGCCycleEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
6541
{
6542
MM_GCCycleEndEvent *event = (MM_GCCycleEndEvent *)eventData;
6543
OMR_VMThread *omrVMThread = event->omrVMThread;
6544
condYieldFromGCFunctionPtr condYield = NULL;
6545
if (TR::Options::getCmdLineOptions()->realTimeGC())
6546
condYield = event->condYieldFromGCFunction;
6547
6548
jitReleaseCodeStackWalk(omrVMThread,condYield);
6549
jitReclaimMarkedAssumptions(true);
6550
}
6551
6552
static void jitHookReleaseCodeLocalGCEnd(J9HookInterface **hook, UDATA eventNum, void *eventData, void *userData)
6553
{
6554
MM_LocalGCEndEvent *event = (MM_LocalGCEndEvent *)eventData;
6555
jitReleaseCodeStackWalk(event->currentThread);
6556
jitReclaimMarkedAssumptions(true);
6557
}
6558
6559
6560
/// setupHooks is used in ABOUT_TO_BOOTSTRAP stage (13)
6561
int32_t setUpHooks(J9JavaVM * javaVM, J9JITConfig * jitConfig, TR_FrontEnd * vm)
6562
{
6563
TR::CompilationInfo *compInfo = getCompilationInfo(jitConfig);
6564
#if defined(J9VM_OPT_JITSERVER)
6565
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
6566
{
6567
javaVM->internalVMFunctions->jvmPhaseChange(javaVM, J9VM_PHASE_NOT_STARTUP);
6568
return 0;
6569
}
6570
#endif
6571
6572
TR_J9VMBase *vmj9 = (TR_J9VMBase *)vm;
6573
6574
J9HookInterface * * vmHooks = javaVM->internalVMFunctions->getVMHookInterface(javaVM);
6575
J9HookInterface * * gcHooks = javaVM->memoryManagerFunctions->j9gc_get_hook_interface(javaVM);
6576
J9HookInterface * * gcOmrHooks = javaVM->memoryManagerFunctions->j9gc_get_omr_hook_interface(javaVM->omrVM);
6577
6578
PORT_ACCESS_FROM_JAVAVM(javaVM);
6579
6580
if (TR::Options::getCmdLineOptions()->getOption(TR_noJitDuringBootstrap) ||
6581
TR::Options::getCmdLineOptions()->getOption(TR_noJitUntilMain) ||
6582
TR::Options::getCmdLineOptions()->getOption(TR_jitAllAtMain))
6583
{
6584
jitConfig->runtimeFlags |= J9JIT_DEFER_JIT;
6585
6586
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_LOOKUP_JNI_ID, jitHookAboutToRunMain, OMR_GET_CALLSITE(), NULL))
6587
{
6588
j9tty_printf(PORTLIB, "Error: Unable to install J9HOOK_VM_LOOKUP_JNI_ID hook\n");
6589
return -1;
6590
}
6591
}
6592
else
6593
{
6594
#ifdef J9VM_JIT_SUPPORTS_DIRECT_JNI
6595
initializeDirectJNI(javaVM);
6596
#endif
6597
}
6598
6599
// sync the two places for sampling frequency
6600
jitConfig->samplingFrequency = TR::Options::getSamplingFrequency();
6601
6602
if(TR::Options::getCmdLineOptions()->getOption(TR_RTGCMapCheck))
6603
initJitGCMapCheckAsyncHook(javaVM, javaVM->internalVMFunctions->J9RegisterAsyncEvent(javaVM, jitGCMapCheck, NULL), jitConfig);
6604
6605
jitConfig->samplerMonitor = NULL; // initialize this field just in case
6606
compInfo->setSamplingThreadLifetimeState(TR::CompilationInfo::SAMPLE_THR_NOT_CREATED); // just in case
6607
if (jitConfig->samplingFrequency
6608
&& !vmj9->isAOT_DEPRECATED_DO_NOT_USE()
6609
#if defined(J9VM_OPT_JITSERVER)
6610
&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER
6611
#endif
6612
)
6613
{
6614
if ((jitConfig->sampleInterruptHandlerKey = javaVM->internalVMFunctions->J9RegisterAsyncEvent(javaVM, jitMethodSampleInterrupt, NULL)) < 0)
6615
{
6616
j9tty_printf(PORTLIB, "Error: Unable to install method sample handler\n");
6617
return -1;
6618
}
6619
6620
j9thread_monitor_init_with_name(&(jitConfig->samplerMonitor), 0, "JIT sampling thread");
6621
6622
if (jitConfig->samplerMonitor)
6623
{
6624
UDATA priority;
6625
6626
priority = J9THREAD_PRIORITY_MAX;
6627
6628
compInfo->setSamplingThreadWaitTimeInDeepIdleToNotifyVM();
6629
// Frequency has been set above; now set the state because when the sampler
6630
// thread is started it must see the new state
6631
// If the sampler thread cannot be started we must change the state back
6632
compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_DEFAULT);
6633
6634
const UDATA defaultOSStackSize = javaVM->defaultOSStackSize; //256KB stack size
6635
6636
if(javaVM->internalVMFunctions->createThreadWithCategory(&jitConfig->samplerThread,
6637
defaultOSStackSize,
6638
priority,
6639
0,
6640
&samplerThreadProc,
6641
jitConfig,
6642
J9THREAD_CATEGORY_SYSTEM_JIT_THREAD))
6643
{
6644
// cannot create the sampling thread; will continue without
6645
j9thread_monitor_destroy(jitConfig->samplerMonitor);
6646
jitConfig->samplerMonitor = 0;
6647
compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_NOT_INITIALIZED);
6648
}
6649
else
6650
{
6651
// wait here until the samplingThread attaches to the VM
6652
j9thread_monitor_enter(jitConfig->samplerMonitor);
6653
while (compInfo->getSamplingThreadLifetimeState() == TR::CompilationInfo::SAMPLE_THR_NOT_CREATED)
6654
j9thread_monitor_wait(jitConfig->samplerMonitor);
6655
j9thread_monitor_exit(jitConfig->samplerMonitor);
6656
6657
// At this point the sampling thread either attached successfully and changed the
6658
// state to SAMPLE_THR_ATTACHED, or failed to attach and exited after changing
6659
// the state to SAMPLE_THR_FAILED_TO_ATTACH
6660
if (compInfo->getSamplingThreadLifetimeState() == TR::CompilationInfo::SAMPLE_THR_FAILED_TO_ATTACH) // no monitor needed for this access
6661
{
6662
j9thread_monitor_destroy(jitConfig->samplerMonitor);
6663
jitConfig->samplerMonitor = 0;
6664
jitConfig->samplerThread = 0;
6665
compInfo->setSamplerState(TR::CompilationInfo::SAMPLER_NOT_INITIALIZED);
6666
}
6667
}
6668
}
6669
6670
if (!jitConfig->samplerMonitor)
6671
{
6672
j9tty_printf(PORTLIB, "\nJIT: Method sample thread failed to start -- disabling sampling.\n");
6673
}
6674
}
6675
// If we cannot start the sampling thread or don't want to, then enter NON_STARTUP mode directly
6676
if (!jitConfig->samplerMonitor)
6677
javaVM->internalVMFunctions->jvmPhaseChange(javaVM, J9VM_PHASE_NOT_STARTUP);
6678
6679
if (jitConfig->runtimeFlags & J9JIT_TOSS_CODE)
6680
{
6681
// JIT_TOSS_CODE is broken. This routine isn't called if it's set...
6682
j9tty_printf(PORTLIB, "JIT: not installing counting send targets.\n");
6683
}
6684
else
6685
{
6686
// Do not register the hook that sets method invocation counts in JITServer server mode
6687
// This ensures that interpreter will not send methods for compilation
6688
#if defined(J9VM_OPT_JITSERVER)
6689
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER)
6690
#endif
6691
{
6692
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_INITIALIZE_SEND_TARGET, jitHookInitializeSendTarget, OMR_GET_CALLSITE(), NULL))
6693
{
6694
j9tty_printf(PORTLIB, "Error: Unable to install send target hook\n");
6695
return -1;
6696
}
6697
}
6698
#if defined (J9VM_INTERP_PROFILING_BYTECODES)
6699
TR_IProfiler *iProfiler = vmj9->getIProfiler();
6700
6701
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableInterpreterProfiling) &&
6702
iProfiler && (iProfiler->getProfilerMemoryFootprint() < TR::Options::_iProfilerMemoryConsumptionLimit))
6703
{
6704
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableIProfilerThread))
6705
{
6706
iProfiler->startIProfilerThread(javaVM);
6707
}
6708
if (TR::Options::getCmdLineOptions()->getOption(TR_NoIProfilerDuringStartupPhase)
6709
#if defined(J9VM_OPT_JITSERVER)
6710
|| compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER
6711
#endif
6712
)
6713
{
6714
interpreterProfilingState = IPROFILING_STATE_OFF;
6715
}
6716
else // start Iprofiler right away
6717
{
6718
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL, jitHookBytecodeProfiling, OMR_GET_CALLSITE(), NULL))
6719
{
6720
j9tty_printf(PORTLIB, "Error: Unable to install J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL listener\n");
6721
return -1;
6722
}
6723
interpreterProfilingState = IPROFILING_STATE_ON;
6724
}
6725
6726
interpreterProfilingWasOnAtStartup = true;
6727
6728
if (TR::Options::getCmdLineOptions()->getOption(TR_VerboseInterpreterProfiling))
6729
j9tty_printf(PORTLIB, "Succesfully installed J9HOOK_VM_PROFILING_BYTECODE_BUFFER_FULL listener\n");
6730
}
6731
#endif
6732
if (compInfo->getPersistentInfo()->isRuntimeInstrumentationEnabled())
6733
{
6734
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableHWProfilerThread))
6735
{
6736
TR_HWProfiler *hwProfiler = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->hwProfiler;
6737
hwProfiler->startHWProfilerThread(javaVM);
6738
}
6739
}
6740
6741
if (TR::Options::getCmdLineOptions()->getOption(TR_EnableJProfiling) && !TR::Options::getCmdLineOptions()->getOption(TR_DisableJProfilerThread))
6742
{
6743
TR_JProfilerThread *jProfiler = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->jProfiler;
6744
jProfiler->start(javaVM);
6745
}
6746
}
6747
6748
if ((*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_LOCAL_GC_START, jitHookLocalGCStart, OMR_GET_CALLSITE(), NULL) ||
6749
(*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_LOCAL_GC_END, jitHookLocalGCEnd, OMR_GET_CALLSITE(), NULL) ||
6750
(*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_GLOBAL_GC_START, jitHookGlobalGCStart, OMR_GET_CALLSITE(), NULL) ||
6751
(*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_GLOBAL_GC_END, jitHookGlobalGCEnd, OMR_GET_CALLSITE(), NULL))
6752
{
6753
j9tty_printf(PORTLIB, "Error: Unable to register gc hook\n");
6754
return -1;
6755
}
6756
6757
if (!vmj9->isAOT_DEPRECATED_DO_NOT_USE())
6758
{
6759
6760
IDATA unableToRegisterHooks = 0;
6761
6762
if (TR::Options::getCmdLineOptions()->realTimeGC())
6763
{
6764
if (!TR::Options::getCmdLineOptions()->getOption(TR_NoClassGC))
6765
unableToRegisterHooks = (*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_GC_CYCLE_END, jitHookReleaseCodeGCCycleEnd, OMR_GET_CALLSITE(), NULL);
6766
}
6767
else
6768
{
6769
unableToRegisterHooks =
6770
((*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_GLOBAL_GC_END, jitHookReleaseCodeGlobalGCEnd, OMR_GET_CALLSITE(), NULL) ||
6771
(*gcOmrHooks)->J9HookRegisterWithCallSite(gcOmrHooks, J9HOOK_MM_OMR_LOCAL_GC_END, jitHookReleaseCodeLocalGCEnd, OMR_GET_CALLSITE(), NULL));
6772
}
6773
6774
if (unableToRegisterHooks)
6775
{
6776
j9tty_printf(PORTLIB, "Error: Unable to register gc hook\n");
6777
return -1;
6778
}
6779
6780
}
6781
6782
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_INTERNAL_CLASS_LOAD, jitHookClassLoad, OMR_GET_CALLSITE(), NULL) ||
6783
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASS_PREINITIALIZE, jitHookClassPreinitialize, OMR_GET_CALLSITE(), NULL) ||
6784
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASS_INITIALIZE, jitHookClassInitialize, OMR_GET_CALLSITE(), NULL))
6785
{
6786
j9tty_printf(PORTLIB, "Error: Unable to register class event hook\n");
6787
return -1;
6788
}
6789
6790
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
6791
if (!vmj9->isAOT_DEPRECATED_DO_NOT_USE())
6792
{
6793
#if defined(AOTRT_DLL)
6794
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_CLASS_UNLOAD, rtHookClassUnload, NULL);
6795
(*vmHooks)->J9HookUnregister(vmHooks, J9HOOK_VM_CLASS_LOADER_UNLOAD, rtHookClassLoaderUnload, NULL);
6796
#endif
6797
if ( (*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASS_UNLOAD, jitHookClassUnload, OMR_GET_CALLSITE(), NULL) ||
6798
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASSES_UNLOAD, jitHookClassesUnload, OMR_GET_CALLSITE(), NULL) ||
6799
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASS_LOADER_UNLOAD, jitHookClassLoaderUnload, OMR_GET_CALLSITE(), NULL) ||
6800
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_ANON_CLASSES_UNLOAD, jitHookAnonClassesUnload, OMR_GET_CALLSITE(), NULL) ||
6801
#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
6802
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_CLASS_LOADERS_UNLOAD, jitHookClassLoadersUnload, OMR_GET_CALLSITE(), NULL) ||
6803
#endif
6804
(*gcHooks)->J9HookRegisterWithCallSite(gcHooks, J9HOOK_MM_INTERRUPT_COMPILATION, jitHookInterruptCompilation, OMR_GET_CALLSITE(), NULL) ||
6805
(*gcHooks)->J9HookRegisterWithCallSite(gcHooks, J9HOOK_MM_CLASS_UNLOADING_END, jitHookClassesUnloadEnd, OMR_GET_CALLSITE(), NULL))
6806
{
6807
j9tty_printf(PORTLIB, "Error: Unable to register class event hook\n");
6808
return -1;
6809
}
6810
6811
}
6812
#endif
6813
6814
j9thread_monitor_enter(javaVM->vmThreadListMutex);
6815
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_CREATED, jitHookThreadCreate, OMR_GET_CALLSITE(), NULL) ||
6816
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_END, jitHookThreadEnd, OMR_GET_CALLSITE(), NULL) ||
6817
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_CRASH, jitHookThreadCrash, OMR_GET_CALLSITE(), NULL) ||
6818
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_DESTROY, jitHookThreadDestroy, OMR_GET_CALLSITE(), NULL) ||
6819
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_THREAD_STARTED, jitHookThreadStart, OMR_GET_CALLSITE(), NULL))
6820
{
6821
j9tty_printf(PORTLIB, "Error: Unable to register thread hook\n");
6822
return -1;
6823
}
6824
else
6825
{
6826
// FIXME: we should really move the hooking these earlier so that the compilation thread
6827
// which is created earlier at JIT_INITIALIZED stage also gets the hooks.
6828
//
6829
// catch up with the existing threads
6830
J9VMThread *currThread = javaVM->mainThread;
6831
if (currThread)
6832
{
6833
do
6834
{
6835
initThreadAfterCreation(currThread);
6836
}
6837
while ((currThread = currThread->linkNext) != javaVM->mainThread);
6838
}
6839
}
6840
j9thread_monitor_exit(javaVM->vmThreadListMutex);
6841
6842
#if defined(J9VM_OPT_CRIU_SUPPORT)
6843
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_PREPARING_FOR_CHECKPOINT, jitHookPrepareCheckpoint, OMR_GET_CALLSITE(), NULL) ||
6844
(*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_PREPARING_FOR_RESTORE, jitHookPrepareRestore, OMR_GET_CALLSITE(), NULL))
6845
{
6846
j9tty_printf(PORTLIB, "Error: Unable to register CRIU hook\n");
6847
return -1;
6848
}
6849
#endif /* defined(J9VM_OPT_CRIU_SUPPORT) */
6850
6851
if (!vmj9->isAOT_DEPRECATED_DO_NOT_USE()
6852
#if defined(J9VM_OPT_JITSERVER)
6853
&& compInfo->getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER
6854
#endif
6855
)
6856
{
6857
if ((*vmHooks)->J9HookRegisterWithCallSite(vmHooks, J9HOOK_VM_JNI_NATIVE_REGISTERED, jitHookJNINativeRegistered, OMR_GET_CALLSITE(), NULL))
6858
{
6859
j9tty_printf(PORTLIB, "Error: Unable to register RegisterNatives hook\n");
6860
return -1;
6861
}
6862
}
6863
return 0;
6864
}
6865
6866
#if defined(J9VM_OPT_JITSERVER)
6867
int32_t startJITServer(J9JITConfig *jitConfig)
6868
{
6869
J9JavaVM *javaVM = jitConfig->javaVM;
6870
TR_Listener *listener = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->listener;
6871
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
6872
PORT_ACCESS_FROM_JAVAVM(javaVM);
6873
6874
TR_ASSERT(compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER, "startJITServer cannot be called in non-server mode\n");
6875
6876
listener->startListenerThread(javaVM);
6877
6878
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
6879
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "Started JITServer listener thread: %p ", listener->getListenerThread());
6880
6881
if (jitConfig->samplingFrequency != 0)
6882
{
6883
JITServerStatisticsThread *statsThreadObj = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->statisticsThreadObject;
6884
// statsThreadObj is guaranteed to be non-null because JITServer will not start if statisticsThreadObject cannot be created
6885
statsThreadObj->startStatisticsThread(javaVM);
6886
// Verify that statistics thread was started
6887
if (!statsThreadObj->getStatisticsThread())
6888
{
6889
j9tty_printf(PORTLIB, "Error: Unable to start the statistics thread\n");
6890
return -1;
6891
// If we decide to start even without a statistics thread, we must
6892
// free `statsThreadObj` and set the corresponding jitConfig field to NULL
6893
}
6894
}
6895
return 0;
6896
}
6897
6898
int32_t waitJITServerTermination(J9JITConfig *jitConfig)
6899
{
6900
J9JavaVM *javaVM = jitConfig->javaVM;
6901
TR_Listener *listener = ((TR_JitPrivateConfig*)(jitConfig->privateConfig))->listener;
6902
TR::CompilationInfo * compInfo = TR::CompilationInfo::get(jitConfig);
6903
int32_t rc = 0;
6904
6905
TR_ASSERT(compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER, "waitJITServerTermination cannot be called in non-server mode\n");
6906
6907
rc = listener->waitForListenerThreadExit(javaVM);
6908
return rc;
6909
}
6910
#endif /* J9VM_OPT_JITSERVER */
6911
6912
} /* extern "C" */
6913
6914