Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/control/CompilationThread.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
#define J9_EXTERNAL_TO_VM
24
25
#if SOLARIS || AIXPPC || LINUX || OSX
26
#include <strings.h>
27
#define J9OS_STRNCMP strncasecmp
28
#else
29
#define J9OS_STRNCMP strncmp
30
#endif
31
32
#include "control/CompilationThread.hpp"
33
34
#include <exception>
35
#include <limits.h>
36
#include <stdlib.h>
37
#include <time.h>
38
#include "j9.h"
39
#include "j9cfg.h"
40
#include "j9modron.h"
41
#include "j9protos.h"
42
#include "vmaccess.h"
43
#include "objhelp.h"
44
#include "codegen/CodeGenerator.hpp"
45
#include "codegen/Instruction.hpp"
46
#include "codegen/PrivateLinkage.hpp"
47
#include "compile/CompilationTypes.hpp"
48
#include "compile/ResolvedMethod.hpp"
49
#include "control/JitDump.hpp"
50
#include "control/Recompilation.hpp"
51
#include "control/RecompilationInfo.hpp"
52
#include "control/MethodToBeCompiled.hpp"
53
#include "control/OptimizationPlan.hpp"
54
#include "env/CompilerEnv.hpp"
55
#include "env/IO.hpp"
56
#include "env/PersistentInfo.hpp"
57
#include "env/StackMemoryRegion.hpp"
58
#include "env/jittypes.h"
59
#include "env/ClassTableCriticalSection.hpp"
60
#include "env/PersistentCHTable.hpp"
61
#include "env/VMAccessCriticalSection.hpp"
62
#include "env/VerboseLog.hpp"
63
#include "compile/CompilationException.hpp"
64
#include "runtime/CodeCacheExceptions.hpp"
65
#include "exceptions/JITShutDown.hpp"
66
#include "exceptions/PersistenceFailure.hpp"
67
#include "exceptions/LowPhysicalMemory.hpp"
68
#include "exceptions/RuntimeFailure.hpp"
69
#include "exceptions/AOTFailure.hpp"
70
#include "exceptions/FSDFailure.hpp"
71
#include "exceptions/DataCacheError.hpp"
72
#include "il/Node.hpp"
73
#include "il/Node_inlines.hpp"
74
#include "ilgen/IlGenRequest.hpp"
75
#include "ilgen/IlGeneratorMethodDetails_inlines.hpp"
76
#include "infra/CriticalSection.hpp"
77
#include "infra/MonitorTable.hpp"
78
#include "infra/Monitor.hpp"
79
#include "infra/String.hpp"
80
#include "ras/InternalFunctions.hpp"
81
#include "runtime/asmprotos.h"
82
#include "runtime/CodeCache.hpp"
83
#include "runtime/CodeCacheManager.hpp"
84
#include "runtime/J9VMAccess.hpp"
85
#include "runtime/RelocationRuntime.hpp"
86
#include "runtime/J9Profiler.hpp"
87
#include "control/CompilationRuntime.hpp"
88
#include "env/j9method.h"
89
#include "env/J9SharedCache.hpp"
90
#include "env/VMJ9.h"
91
#include "env/annotations/AnnotationBase.hpp"
92
#include "runtime/MethodMetaData.h"
93
#include "env/J9JitMemory.hpp"
94
#include "env/J9SegmentCache.hpp"
95
#include "env/SystemSegmentProvider.hpp"
96
#include "env/DebugSegmentProvider.hpp"
97
#if defined(J9VM_OPT_JITSERVER)
98
#include "control/JITClientCompilationThread.hpp"
99
#include "control/JITServerCompilationThread.hpp"
100
#include "control/JITServerHelpers.hpp"
101
#include "runtime/JITClientSession.hpp"
102
#include "runtime/JITServerAOTDeserializer.hpp"
103
#include "net/ClientStream.hpp"
104
#include "net/ServerStream.hpp"
105
#include "omrformatconsts.h"
106
#endif /* defined(J9VM_OPT_JITSERVER) */
107
#ifdef COMPRESS_AOT_DATA
108
#include "shcdatatypes.h" // For CompiledMethodWrapper
109
#ifdef J9ZOS390
110
// inflateInit checks the version of the zlib with which data was deflated.
111
// Reason we need to avoid conversion here is because, we are statically linking
112
// system zlib which would have encoded String literals in some version which is not
113
// same as the version we are converting out string literals in. This leads to issue
114
// where we fail inflating data with version mismatch.
115
#pragma convlit(suspend)
116
#include <zlib.h>
117
#pragma convlit(resume)
118
#else
119
#include "zlib.h"
120
#endif
121
#endif
122
#if defined(J9VM_OPT_SHARED_CLASSES)
123
#include "j9jitnls.h"
124
#endif
125
126
OMR::CodeCacheMethodHeader *getCodeCacheMethodHeader(char *p, int searchLimit, J9JITExceptionTable* metaData);
127
extern "C" {
128
int32_t getCount(J9ROMMethod *romMethod, TR::Options *optionsJIT, TR::Options *optionsAOT);
129
int32_t encodeCount(int32_t count);
130
}
131
static void printCompFailureInfo(TR::Compilation * comp, const char * reason);
132
133
#include "env/ut_j9jit.h"
134
135
#if defined(TR_HOST_S390)
136
#include <sys/time.h>
137
#endif
138
139
#if defined(AIXPPC)
140
#include <unistd.h>
141
#endif
142
143
#if defined(J9VM_INTERP_PROFILING_BYTECODES)
144
#include "runtime/IProfiler.hpp"
145
#endif
146
147
IDATA J9THREAD_PROC compilationThreadProc(void *jitconfig);
148
IDATA J9THREAD_PROC protectedCompilationThreadProc(J9PortLibrary *portLib, TR::CompilationInfoPerThread*compInfoPT/*void *vmthread*/);
149
150
extern TR::OptionSet *findOptionSet(J9Method *, bool);
151
152
#define VM_STATE_COMPILING 64
153
#define MAX_NUM_CRASHES 4
154
#define COMPRESSION_FAILED -1
155
#define DECOMPRESSION_FAILED -1
156
#define DECOMPRESSION_SUCCEEDED 0
157
158
#if defined(WINDOWS)
159
void setThreadAffinity(unsigned _int64 handle, unsigned long mask)
160
{
161
if (SetThreadAffinityMask((HANDLE)handle, mask)==0)
162
{
163
#ifdef DEBUG
164
fprintf(stderr, "cannot set affinity mask was %x\n", mask);
165
#endif
166
}
167
}
168
#endif
169
170
TR_RelocationRuntime*
171
TR::CompilationInfoPerThreadBase::reloRuntime()
172
{
173
#if defined(J9VM_OPT_JITSERVER)
174
if (_methodBeingCompiled->isAotLoad() ||
175
_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::NONE ||
176
(_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT && TR::Options::sharedClassCache())) // Enable local AOT compilations at client
177
return static_cast<TR_RelocationRuntime*>(&_sharedCacheReloRuntime);
178
return static_cast<TR_RelocationRuntime*>(&_remoteCompileReloRuntime);
179
#else
180
return static_cast<TR_RelocationRuntime*>(&_sharedCacheReloRuntime);
181
#endif /* defined(J9VM_OPT_JITSERVER) */
182
}
183
184
void
185
TR::CompilationInfoPerThreadBase::setCompilation(TR::Compilation *compiler)
186
{
187
#if defined(DEBUG) || defined(PROD_WITH_ASSUMES)
188
TR::Compilation *tlsCompiler = TR::comp();
189
// Exclude PPC LE from the following assert due to xlc compiler bug
190
TR_ASSERT(
191
tlsCompiler == compiler || (TR::Compiler->target.cpu.isPower() && TR::Compiler->target.cpu.isLittleEndian()),
192
"TLS compilation object @ " POINTER_PRINTF_FORMAT " does not match provided compilation object @ " POINTER_PRINTF_FORMAT,
193
tlsCompiler,
194
compiler);
195
#endif
196
_compiler = compiler;
197
}
198
199
#if defined(J9VM_OPT_JITSERVER)
200
thread_local TR::CompilationInfoPerThread *TR::compInfoPT;
201
#endif /* defined(J9VM_OPT_JITSERVER) */
202
203
static uintptr_t
204
jitSignalHandler(struct J9PortLibrary *portLibrary, uint32_t gpType, void *gpInfo, void *handler_arg)
205
{
206
static int32_t numCrashes = 0;
207
bool recoverable = true;
208
J9VMThread *vmThread = (J9VMThread *)handler_arg;
209
210
// Try to find the compilation object
211
TR::Compilation * comp = 0;
212
TR_MethodToBeCompiled *methodToBeCompiled = NULL;
213
J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;
214
TR::CompilationInfo *compInfo = TR::CompilationInfo::get(jitConfig);
215
TR::CompilationInfoPerThread *compInfoPT = compInfo->getCompInfoForThread(vmThread);
216
if (compInfoPT)
217
{
218
comp = compInfoPT->getCompilation();
219
methodToBeCompiled = compInfoPT->getMethodBeingCompiled();
220
}
221
222
const char *sig = (comp && comp->signature() ? comp->signature() : "<unknown>");
223
224
TR::MonitorTable *table = TR::MonitorTable::get();
225
226
if (!table ||
227
!comp ||
228
(table && !table->isThreadInSafeMonitorState(vmThread)))
229
recoverable = false;
230
231
static char *alwaysCrash = feGetEnv("TR_NoCrashHandling");
232
if (alwaysCrash)
233
recoverable = false;
234
235
// If we have been seeing lots of crashes, bail out, and do not attempt to recover
236
//
237
if (numCrashes >= MAX_NUM_CRASHES)
238
recoverable = false;
239
240
#if defined(DEBUG) || defined(PROD_WITH_ASSUMES)
241
static char *autoRecover = feGetEnv("TR_CrashHandling");
242
if (!autoRecover)
243
recoverable = false;
244
fprintf(stderr, "JIT: crashed while compiling %s (recoverable %d)\n", sig, recoverable);
245
#endif
246
247
// For now: disable recovery
248
//
249
recoverable = false;
250
251
// Possible return values here are
252
// J9PORT_SIG_EXCEPTION_CONTINUE_SEARCH -- will cause a crash-dump
253
// J9PORT_SIG_EXCEPTION_CONTINUE_EXECUTION -- will cause a secondary crash (DO NOT USE THIS)
254
// J9PORT_SIG_EXCEPTION_RETURN -- abort current compilation gracefully
255
if (recoverable)
256
{
257
numCrashes++;
258
Trc_JIT_recoverableCrash(vmThread, sig);
259
return J9PORT_SIG_EXCEPTION_RETURN;
260
}
261
Trc_JIT_fatalCrash(vmThread, sig);
262
263
TR_Debug::printStackBacktrace();
264
265
return J9PORT_SIG_EXCEPTION_CONTINUE_SEARCH;
266
}
267
#ifdef COMPRESS_AOT_DATA
268
#ifdef J9ZOS390
269
#pragma convlit(suspend)
270
#endif
271
/*
272
* \brief
273
* Inflates the data buffer using zlib into output buffer
274
*
275
* \param
276
* buffer Input buffer that is going to be inflated
277
*
278
* \param
279
* numberOfBytes Size of the data in the input buffer to inflate
280
*
281
* \param
282
* outBuffer Output buffer to hold the deflated data
283
*
284
* \param
285
* unCompressedSize Size of the original data
286
*
287
* \return
288
* Returns DECOMPRESSION_FAILED if it can not inflate the buffer
289
*
290
*/
291
static
292
int inflateBuffer(U_8 *buffer, int numberOfBytes, U_8 *outBuffer, int unCompressedSize)
293
{
294
Bytef *in = (Bytef*)buffer;
295
Bytef *out = (Bytef*)outBuffer;
296
z_stream _stream;
297
_stream.zalloc = Z_NULL;
298
_stream.zfree = Z_NULL;
299
_stream.opaque = Z_NULL;
300
_stream.avail_in = 0;
301
_stream.next_in = Z_NULL;
302
int ret = inflateInit(&_stream);
303
if (ret != Z_OK)
304
return DECOMPRESSION_FAILED;
305
_stream.avail_out = unCompressedSize;
306
_stream.next_out = out;
307
_stream.next_in = in;
308
_stream.avail_in = numberOfBytes;
309
ret = inflate(&_stream, Z_NO_FLUSH);
310
/**
311
* ZLIB returns Z_STREAM_END if the buffer stream to be inflated is finished.
312
* In this case it returns DECOMPRESSION_FAILED.
313
* Caller of this routine can then decide if they want to retry deflating
314
* Using larger output buffer.
315
*/
316
if (ret != Z_STREAM_END)
317
{
318
TR_ASSERT(0, "Fails while inflating buffer");
319
ret = DECOMPRESSION_FAILED;
320
}
321
else
322
{
323
ret = DECOMPRESSION_SUCCEEDED;
324
}
325
inflateEnd(&_stream);
326
return ret;
327
}
328
329
/*
330
* \brief
331
* Deflates the data buffer using zlib into output buffer
332
*
333
* \param
334
* buffer Input buffer that is going to be deflated
335
*
336
* \param
337
* numberOfBytes Size of the data in the input buffer to deflate
338
*
339
* \param
340
* outBuffer Output buffer to hold the deflated data
341
*
342
* \param
343
* level Level of compression
344
*
345
* \return
346
* If successful, returns Size of data in the deflated bufer
347
* else returns COMPRESSION_FAILED
348
*
349
*/
350
static
351
int deflateBuffer(const U_8 *buffer, int numberOfBytes, U_8 *outBuffer, int level)
352
{
353
z_stream _stream;
354
_stream.zalloc = Z_NULL;
355
_stream.zfree = Z_NULL;
356
_stream.opaque = Z_NULL;
357
int ret=deflateInit(&_stream, level);
358
if (ret != Z_OK)
359
return COMPRESSION_FAILED;
360
// Start deflating
361
_stream.avail_in = numberOfBytes;
362
_stream.next_in = (Bytef*) buffer;
363
_stream.avail_out = numberOfBytes;
364
_stream.next_out = (Bytef*) outBuffer;
365
ret = deflate(&_stream, Z_FINISH);
366
/**
367
* ZLIB returns Z_STREAM_END if the buffer stream to be deflated is finished.
368
* That Return COMPRESSION_FAILED in case we are ending up inflating the data.
369
* Caller of this routine can then decide if they want to retry deflating
370
* Using larger output buffer.
371
*/
372
if ( ret != Z_STREAM_END )
373
{
374
TR_ASSERT(0, "Deflated data is larger than original data.");
375
deflateEnd(&_stream);
376
return COMPRESSION_FAILED;
377
}
378
379
int compressedSize = numberOfBytes - _stream.avail_out;
380
deflateEnd(&_stream);
381
return compressedSize;
382
}
383
#ifdef J9ZOS390
384
#pragma convlit(resume)
385
#endif
386
#endif
387
inline void
388
TR::CompilationInfo::incrementMethodQueueSize()
389
{
390
_numQueuedMethods++;
391
// Keep track of maxQueueSize for information purposes
392
if (_numQueuedMethods > _maxQueueSize)
393
_maxQueueSize = _numQueuedMethods;
394
}
395
396
397
int32_t TR::CompilationInfo::VERY_SMALL_QUEUE = 2;
398
int32_t TR::CompilationInfo::SMALL_QUEUE = 4;
399
int32_t TR::CompilationInfo::MEDIUM_LARGE_QUEUE = 30;
400
int32_t TR::CompilationInfo::LARGE_QUEUE = 40;
401
int32_t TR::CompilationInfo::VERY_LARGE_QUEUE = 55;
402
403
TR::CompilationInfo * TR::CompilationInfo::_compilationRuntime = NULL;
404
405
TR_MethodToBeCompiled *
406
TR::CompilationInfo::getCompilationQueueEntry()
407
{
408
TR_MethodToBeCompiled *unusedEntry = NULL;
409
410
// Search for an empty entry in the methodPool. It is possible
411
// to have entries in the pool which are not fully free'd yet.
412
// The compile request is completed, and hence the entry is in the pool.
413
// Once in the pool, the numThreadsWaiting can only decrease.
414
for (TR_MethodToBeCompiled *cur = _methodPool, *prev = NULL; cur; prev = cur, cur = cur->_next)
415
{
416
if (cur->_numThreadsWaiting == 0)
417
{
418
unusedEntry = cur;
419
if (prev)
420
prev->_next = cur->_next;
421
else
422
_methodPool = cur->_next;
423
--_methodPoolSize;
424
break;
425
}
426
}
427
428
if (!unusedEntry)
429
{
430
unusedEntry = TR_MethodToBeCompiled::allocate(_jitConfig);
431
if (unusedEntry)
432
unusedEntry->_freeTag = ENTRY_IN_POOL_FREE;
433
}
434
435
return unusedEntry;
436
437
}
438
439
TR::CompilationInfoPerThread *
440
TR::CompilationInfo::findFirstLowPriorityCompilationInProgress(CompilationPriority priority) // needs compilationQueueMonitor in hand
441
{
442
TR::CompilationInfoPerThread *lowPriorityCompInProgress = NULL;
443
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
444
{
445
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
446
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
447
if (curCompThreadInfoPT->getMethodBeingCompiled() &&
448
curCompThreadInfoPT->getMethodBeingCompiled()->_priority < priority)
449
{
450
lowPriorityCompInProgress = curCompThreadInfoPT;
451
break;
452
}
453
} // end for
454
return lowPriorityCompInProgress;
455
}
456
457
int32_t TR::CompilationInfo::computeDynamicDumbInlinerBytecodeSizeCutoff(TR::Options *options)
458
{
459
// Q_SZ==0 ==> dynamicCutoff=1600
460
// Q_SZ==32 ==> dynamicCutoff=200
461
// dynamicCutoff = 1600 - (1600-200)*Q_SZ/32
462
int32_t cutoff = options->getDumbInlinerBytecodeSizeMaxCutoff() -
463
(((options->getDumbInlinerBytecodeSizeMaxCutoff() - options->getDumbInlinerBytecodeSizeMinCutoff())*
464
getMethodQueueSize()) >> 5);
465
if (cutoff < options->getDumbInlinerBytecodeSizeMinCutoff())
466
cutoff = options->getDumbInlinerBytecodeSizeMinCutoff();
467
return cutoff;
468
}
469
470
// Examine if we need to activate a new thread
471
// Must have compilation queue monitor in hand when calling this routine
472
TR_YesNoMaybe TR::CompilationInfo::shouldActivateNewCompThread()
473
{
474
// If further compilations have been disabled we could be in a dire situation, for example virtual memory could be
475
// really low, there could be failures when attempting to allocate persistent memory, a compilation thread could
476
// have crashed, etc. In such situations we never want to activate a new compilation driven by this API.
477
if (getPersistentInfo()->getDisableFurtherCompilation())
478
return TR_no;
479
480
// We must have at least one compilation thread active
481
if (getNumCompThreadsActive() <= 0)
482
return TR_yes;
483
int32_t numCompThreadsSuspended = getNumUsableCompilationThreads() - getNumCompThreadsActive();
484
TR_ASSERT(numCompThreadsSuspended >= 0, "Accounting error for suspendedCompThreads usable=%d active=%d\n", getNumUsableCompilationThreads(), getNumCompThreadsActive());
485
// Cannot activate if there is nothing to activate
486
if (numCompThreadsSuspended <= 0)
487
return TR_no;
488
// Do not activate new threads if we are ramping down
489
if (getRampDownMCT())
490
return TR_no;
491
492
#ifdef J9VM_OPT_JITSERVER
493
// Always activate in JITServer server mode
494
if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
495
{
496
return TR_yes;
497
}
498
else if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT &&
499
getCompThreadActivationPolicy() <= JITServer::CompThreadActivationPolicy::MAINTAIN)
500
{
501
return TR_no;
502
}
503
#endif
504
505
// Do not activate if we already exceed the CPU enablement for compilation threads
506
if (exceedsCompCpuEntitlement() != TR_no)
507
{
508
// The (- 50) below implements 'rounding', so one compilation thread is considered
509
// enough for an enablement of [0 - 150]%
510
if ((getNumCompThreadsActive() + 1) * 100 >= (TR::Options::_compThreadCPUEntitlement + 50))
511
return TR_no;
512
}
513
// Do not activate if we are low on physical memory
514
bool incompleteInfo;
515
uint64_t freePhysicalMemorySizeB = computeAndCacheFreePhysicalMemory(incompleteInfo);
516
if (freePhysicalMemorySizeB != OMRPORT_MEMINFO_NOT_AVAILABLE &&
517
freePhysicalMemorySizeB <= (uint64_t)TR::Options::getSafeReservePhysicalMemoryValue() + TR::Options::getScratchSpaceLowerBound())
518
return TR_no;
519
// Do not activate a new thread during graceperiod if AOT is used and first run because
520
// we may have too many warm compilations at warm. However, there is no such risk for quickstart
521
// Another exception: activate if second run in AOT mode
522
523
bool isSecondAOTRun = !TR::Options::getAOTCmdLineOptions()->getOption(TR_NoAotSecondRunDetection) &&
524
!(numMethodsFoundInSharedCache() < TR::Options::_aotMethodThreshold ||
525
_statNumAotedMethods > TR::Options::_aotMethodCompilesThreshold);
526
if (TR::Options::sharedClassCache() &&
527
!TR::Options::getCmdLineOptions()->isQuickstartDetected() &&
528
!isSecondAOTRun &&
529
getPersistentInfo()->getElapsedTime() < (uint64_t)getPersistentInfo()->getClassLoadingPhaseGracePeriod())
530
return TR_no;
531
532
// Activate if the compilation backlog is large.
533
// If there is no comp thread starvation or if the number of comp threads was
534
// determined based on the number of CPUs, then the upper bound of comp threads is _numTargetCPUs-1
535
// However, if the compilation threads are starved (on Linux) we may want
536
// to activate additional comp threads irrespective of the CPU entitlement
537
if (TR::Options::_useCPUsToDetermineMaxNumberOfCompThreadsToActivate)
538
{
539
#if defined (J9VM_OPT_JITSERVER)
540
if (getCompThreadActivationPolicy() == JITServer::CompThreadActivationPolicy::SUBDUE)
541
{
542
// If the server reached low memory and then recovered to normal,
543
// subdue activation of new compilation threads on the client
544
if (_queueWeight > _compThreadActivationThresholdsonStarvation[getNumCompThreadsActive()] << 1)
545
return TR_yes;
546
return TR_no;
547
}
548
#endif /* defined(J9VM_OPT_JITSERVER) */
549
if (getNumCompThreadsActive() < getNumTargetCPUs() - 1)
550
{
551
if (_queueWeight > _compThreadActivationThresholds[getNumCompThreadsActive()])
552
return TR_yes;
553
}
554
#if defined(J9VM_OPT_JITSERVER)
555
else if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT && JITServerHelpers::isServerAvailable())
556
{
557
558
// For JITClient let's be more agressive with compilation thread activation
559
// because the latencies are larger. Beyond 'numProc-1' we will use the
560
// 'starvation activation schedule', but accelerated (divide those thresholds by 2)
561
// NOTE: compilation thread activation policy is AGGRESSIVE if we reached this point
562
if (_queueWeight > (_compThreadActivationThresholdsonStarvation[getNumCompThreadsActive()] >> 1))
563
return TR_yes;
564
}
565
#endif /* defined(J9VM_OPT_JITSERVER) */
566
else if (_starvationDetected)
567
{
568
// comp thread starvation; may activate threads beyond 'numCpu-1'
569
if (_queueWeight > _compThreadActivationThresholdsonStarvation[getNumCompThreadsActive()])
570
return TR_yes;
571
}
572
}
573
else // number of compilation threads indicated by the user
574
{
575
if (_queueWeight > _compThreadActivationThresholds[getNumCompThreadsActive()])
576
return TR_yes;
577
}
578
579
// Allow the caller to add additional tests if required
580
return TR_maybe;
581
}
582
583
bool TR::CompilationInfo::importantMethodForStartup(J9Method *method)
584
{
585
if (getMethodBytecodeSize(method) < TR::Options::_startupMethodDontDowngradeThreshold) // filter by size as well
586
{
587
// During startup java/lang/String* java/util/zip/* and java/util/Hash* methods are rather important
588
J9ROMClass *romClazz = J9_CLASS_FROM_METHOD(method)->romClass;
589
J9UTF8 * className = J9ROMCLASS_CLASSNAME(romClazz);
590
if (TR::Compiler->target.numberOfProcessors() <= 2)
591
{
592
if (J9UTF8_LENGTH(className) == 16 && 0==memcmp(utf8Data(className), "java/lang/String", 16))
593
return true;
594
}
595
else if (J9UTF8_LENGTH(className) >= 14)
596
{
597
if (0==memcmp(utf8Data(className), "java/lang/Stri", 14) ||
598
0==memcmp(utf8Data(className), "java/util/zip/", 14) ||
599
0==memcmp(utf8Data(className), "java/util/Hash", 14))
600
{
601
return true;
602
}
603
}
604
}
605
return false;
606
}
607
608
609
bool TR::CompilationInfo::shouldDowngradeCompReq(TR_MethodToBeCompiled *entry)
610
{
611
bool doDowngrade = false;
612
TR::IlGeneratorMethodDetails& methodDetails = entry->getMethodDetails();
613
J9Method *method = methodDetails.getMethod();
614
#ifdef J9VM_OPT_JITSERVER
615
TR_ASSERT(getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER, "shouldDowngradeCompReq should not be used by JITServer");
616
#endif
617
if (!isCompiled(method) &&
618
entry->_optimizationPlan->getOptLevel() == warm && // only warm compilations are subject to downgrades
619
!methodDetails.isMethodInProgress() &&
620
!methodDetails.isJitDumpMethod() &&
621
!TR::Options::getCmdLineOptions()->getOption(TR_DontDowngradeToCold))
622
{
623
TR::PersistentInfo *persistentInfo = getPersistentInfo();
624
TR_J9VMBase *fe = TR_J9VMBase::get(_jitConfig, NULL);
625
const J9ROMMethod * romMethod = methodDetails.getRomMethod(fe);
626
627
// Don't downgrade if method is JSR292 because inlining in those is vital. See CMVC 200145
628
// However, during start-up phase, allow such downgrades if SCC has been specified on the command line
629
// (the check for J9SHR_RUNTIMEFLAG_ENABLE_CACHE_NON_BOOT_CLASSES prevents the downgrading when
630
// the default SCC is used)
631
if (((_J9ROMMETHOD_J9MODIFIER_IS_SET(romMethod, J9AccMethodHasMethodHandleInvokes)) || fe->isThunkArchetype(method)) &&
632
(_jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP ||
633
!TR::Options::sharedClassCache() ||
634
!J9_ARE_ALL_BITS_SET(jitConfig->javaVM->sharedClassConfig->runtimeFlags, J9SHR_RUNTIMEFLAG_ENABLE_CACHE_NON_BOOT_CLASSES)
635
)
636
)
637
{
638
doDowngrade = false;
639
}
640
// perform JNI at cold
641
else if (entry->isJNINative() ||
642
// downgrade AOT loads that failed
643
(entry->_methodIsInSharedCache == TR_yes && entry->_doNotUseAotCodeFromSharedCache && entry->_compilationAttemptsLeft < MAX_COMPILE_ATTEMPTS))
644
{
645
doDowngrade = true;
646
}
647
// downgrade during IDLE
648
else if ((persistentInfo->getJitState() == IDLE_STATE && entry->_jitStateWhenQueued == IDLE_STATE) &&
649
// but not if the machine uses very little CPU and we want to exploit idle
650
!(TR::Options::getCmdLineOptions()->getOption(TR_UseIdleTime) &&
651
getCpuUtil() && getCpuUtil()->isFunctional() &&
652
getCpuUtil()->getCpuUsage() < 10 &&
653
persistentInfo->getElapsedTime() < 600000) // Downgrade after 10 minutes to conserve CPU in idle mode
654
)
655
{
656
doDowngrade = true;
657
}
658
else
659
{
660
// We may skip downgrading during grace period
661
if (TR::Options::getCmdLineOptions()->getOption(TR_DontDowgradeToColdDuringGracePeriod) &&
662
persistentInfo->getElapsedTime() < (uint64_t)persistentInfo->getClassLoadingPhaseGracePeriod())
663
{
664
}
665
else
666
{
667
// Downgrade during CLP when queue grows too large
668
if ((persistentInfo->isClassLoadingPhase() && getNumQueuedFirstTimeCompilations() > TR::Options::_qsziThresholdToDowngradeDuringCLP) ||
669
// Downgrade if compilation queue is too large
670
(TR::Options::getCmdLineOptions()->getOption(TR_EnableDowngradeOnHugeQSZ) &&
671
getMethodQueueSize() >= TR::Options::_qszThresholdToDowngradeOptLevel) ||
672
// Downgrade if compilation queue grows too much during startup
673
(_jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP &&
674
getMethodQueueSize() >= TR::Options::_qszThresholdToDowngradeOptLevelDuringStartup) ||
675
// Downgrade if AOT and startup,
676
(TR::Options::getCmdLineOptions()->sharedClassCache() &&
677
#if defined(TR_TARGET_POWER) // temporary hack until PPC AOT bug is found
678
_jitConfig->javaVM->phase == J9VM_PHASE_STARTUP &&
679
#else
680
_jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP &&
681
#endif
682
!TR::Options::getCmdLineOptions()->getOption(TR_DisableDowngradeToColdOnVMPhaseStartup))
683
)
684
{
685
doDowngrade = true;
686
}
687
// Downgrade if RI based recompilation is enabled
688
else if (persistentInfo->isRuntimeInstrumentationRecompilationEnabled() && // RI and RI Recompilation is functional
689
!getHWProfiler()->isExpired())
690
{
691
#if !defined(J9ZOS390) // disable for zOS because we don't want to increase CPU time
692
if (!importantMethodForStartup(method)) // Do not downgrade important methods
693
#endif
694
{
695
if (TR::Options::getCmdLineOptions()->getOption(TR_UseRIOnlyForLargeQSZ))
696
{
697
TR_HWProfiler *hwProfiler = getHWProfiler();
698
// Check Q_SZ and downgrade if the backlog is rather large (>_qszMaxThresholdToRIDowngrade)
699
// If we entered this mode, keep downgrading until Q_SZ drops under _qszMinThresholdToRIDowngrade
700
int32_t qsz = getMethodQueueSize(); // cache it to avoid inconsistency because it can change
701
if (qsz > TR::Options::_qszMaxThresholdToRIDowngrade)
702
{
703
// Change the threshold to a smaller value to implement hysteresis
704
// Race conditions are not important here
705
if (hwProfiler->getQSzThresholdToDowngrade() != TR::Options::_qszMinThresholdToRIDowngrade)
706
hwProfiler->setQSzThresholdToDowngrade(TR::Options::_qszMinThresholdToRIDowngrade);
707
}
708
else if (qsz < TR::Options::_qszMinThresholdToRIDowngrade)
709
{
710
// Change the threshold to a bigger value to implement hysteresis
711
if (hwProfiler->getQSzThresholdToDowngrade() != TR::Options::_qszMaxThresholdToRIDowngrade)
712
hwProfiler->setQSzThresholdToDowngrade(TR::Options::_qszMaxThresholdToRIDowngrade);
713
}
714
if (qsz > hwProfiler->getQSzThresholdToDowngrade())
715
{
716
doDowngrade = true;
717
TR_HWProfiler::_STATS_NumCompDowngradesDueToRI++;
718
}
719
}
720
else if (getHWProfiler()->getProcessBufferState() >= 0 || // Downgrade when RI is on
721
!TR::Options::getCmdLineOptions()->getOption(TR_DontDowngradeWhenRIIsTemporarilyOff))
722
{
723
doDowngrade = true;
724
// Statistics for how many compilations we downgrade due to RI
725
TR_HWProfiler::_STATS_NumCompDowngradesDueToRI++;
726
}
727
}
728
}
729
}
730
// Always downgrade J9VMInternals because they are expensive
731
if (!doDowngrade)
732
{
733
J9UTF8 * className = J9ROMCLASS_CLASSNAME(methodDetails.getRomClass());
734
if (J9UTF8_LENGTH(className) == 23 && !memcmp(utf8Data(className), "java/lang/J9VMInternals", 23))
735
{
736
doDowngrade = true;
737
}
738
}
739
740
// Count methods downgraded while RI buffer processing was off
741
if (doDowngrade && getPersistentInfo()->isRuntimeInstrumentationEnabled() &&
742
getHWProfiler()->getProcessBufferState() < 0)
743
{
744
getHWProfiler()->incNumDowngradesSinceTurnedOff();
745
}
746
}
747
}
748
return doDowngrade;
749
}
750
751
752
bool
753
TR::CompilationInfo::createCompilationInfo(J9JITConfig * jitConfig)
754
{
755
TR_ASSERT(!_compilationRuntime, "The global compilation info has already been allocated");
756
try
757
{
758
TR::RawAllocator rawAllocator(jitConfig->javaVM);
759
void * alloc = rawAllocator.allocate(sizeof(TR::CompilationInfo));
760
/* FIXME: Replace this with the appropriate initializers in the constructor */
761
/* Note: there are embedded objects in TR::CompilationInfo that rely on the fact
762
that we do memset this object to 0 */
763
memset(alloc, 0, sizeof(TR::CompilationInfo));
764
_compilationRuntime = new (alloc) TR::CompilationInfo(jitConfig);
765
766
#ifdef DEBUG
767
if (debug("traceThreadCompile"))
768
_compilationRuntime->_traceCompiling = true;
769
#endif
770
}
771
catch (const std::exception &e)
772
{
773
return false;
774
}
775
return true;
776
}
777
778
void
779
TR::CompilationInfo::freeAllCompilationThreads()
780
{
781
if (_compThreadActivationThresholds)
782
{
783
jitPersistentFree(_compThreadActivationThresholds);
784
}
785
786
if (_compThreadSuspensionThresholds)
787
{
788
jitPersistentFree(_compThreadSuspensionThresholds);
789
}
790
791
if (_compThreadActivationThresholdsonStarvation)
792
{
793
jitPersistentFree(_compThreadActivationThresholdsonStarvation);
794
}
795
796
if (_arrayOfCompilationInfoPerThread)
797
{
798
for (int32_t i=0; i < getNumTotalCompilationThreads(); ++i)
799
{
800
if (_arrayOfCompilationInfoPerThread[i])
801
_arrayOfCompilationInfoPerThread[i]->freeAllResources();
802
}
803
804
jitPersistentFree(_arrayOfCompilationInfoPerThread);
805
}
806
}
807
808
void TR::CompilationInfo::freeAllResources()
809
{
810
if (_interpSamplTrackingInfo)
811
{
812
jitPersistentFree(_interpSamplTrackingInfo);
813
}
814
815
freeAllCompilationThreads();
816
}
817
818
void TR::CompilationInfo::freeCompilationInfo(J9JITConfig *jitConfig)
819
{
820
TR_ASSERT(_compilationRuntime, "The global compilation info has already been freed.");
821
TR::CompilationInfo * compilationRuntime = _compilationRuntime;
822
_compilationRuntime = NULL;
823
824
compilationRuntime->freeAllResources();
825
826
TR::RawAllocator rawAllocator(jitConfig->javaVM);
827
compilationRuntime->~CompilationInfo();
828
rawAllocator.deallocate(compilationRuntime);
829
}
830
831
void TR::CompilationInfoPerThread::freeAllResources()
832
{
833
if (_rtLogFile)
834
{
835
j9jit_fclose(_rtLogFile);
836
}
837
838
#if defined(J9VM_OPT_JITSERVER)
839
if (_classesThatShouldNotBeNewlyExtended)
840
{
841
TR_Memory::jitPersistentFree(_classesThatShouldNotBeNewlyExtended);
842
}
843
#endif /* defined(J9VM_OPT_JITSERVER) */
844
}
845
846
#if defined(J9VM_OPT_JITSERVER)
847
J9ROMClass *
848
TR::CompilationInfoPerThread::getRemoteROMClassIfCached(J9Class *clazz)
849
{
850
return JITServerHelpers::getRemoteROMClassIfCached(getClientData(), clazz);
851
}
852
853
J9ROMClass *
854
TR::CompilationInfoPerThread::getAndCacheRemoteROMClass(J9Class *clazz)
855
{
856
auto romClass = getRemoteROMClassIfCached(clazz);
857
if (romClass == NULL)
858
{
859
JITServerHelpers::ClassInfoTuple classInfoTuple;
860
romClass = JITServerHelpers::getRemoteROMClass(clazz, getStream(), getClientData()->persistentMemory(), classInfoTuple);
861
romClass = JITServerHelpers::cacheRemoteROMClassOrFreeIt(getClientData(), clazz, romClass, classInfoTuple);
862
TR_ASSERT_FATAL(romClass, "ROM class of J9Class=%p must be cached at this point", clazz);
863
}
864
return romClass;
865
}
866
#endif /* defined(J9VM_OPT_JITSERVER) */
867
868
void
869
TR::CompilationInfoPerThread::waitForGCCycleMonitor(bool threadHasVMAccess)
870
{
871
#if defined (J9VM_GC_REALTIME)
872
J9JavaVM *vm = _jitConfig->javaVM;
873
PORT_ACCESS_FROM_JAVAVM(vm);
874
j9thread_monitor_enter(vm->omrVM->_gcCycleOnMonitor);
875
while (vm->omrVM->_gcCycleOn)
876
{
877
uint64_t waitTime = 0;
878
_compInfo.debugPrint(_compilationThread, "GC cycle is on, waiting for the cycle to finish\n");
879
880
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseGCcycle))
881
{
882
waitTime = j9time_hires_clock(); // may not be good for SMP
883
TR_VerboseLog::writeLineLocked(TR_Vlog_GCCYCLE,"CompilationThread will wait for GC cycle to finish");
884
}
885
886
// Before waiting on the monitor we need to release VM access (but only if the thread has it)
887
//
888
if (threadHasVMAccess)
889
{
890
_compInfo.debugPrint(_compilationThread, "\tcompilation thread releasing VM access\n");
891
releaseVMAccess(_compilationThread);
892
_compInfo.debugPrint(_compilationThread, "-VMacc\n");
893
}
894
895
j9thread_monitor_wait(vm->omrVM->_gcCycleOnMonitor);
896
_compInfo.debugPrint(_compilationThread, "GC cycle is finished, resuming compilation\n");
897
898
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseGCcycle))
899
{
900
// measure the time we spent waiting
901
waitTime = j9time_hires_delta(waitTime, j9time_hires_clock(), J9PORT_TIME_DELTA_IN_MILLISECONDS);
902
TR_VerboseLog::writeLineLocked(TR_Vlog_GCCYCLE,"CompilationThread woke up (GC cycle finished); Waiting time = %u msec", (uint32_t)waitTime);
903
}
904
905
// Acquire VM access
906
//
907
if (threadHasVMAccess)
908
{
909
j9thread_monitor_exit(vm->omrVM->_gcCycleOnMonitor);
910
acquireVMAccessNoSuspend(_compilationThread);
911
_compInfo.debugPrint(_compilationThread, "+VMacc\n");
912
j9thread_monitor_enter(vm->omrVM->_gcCycleOnMonitor);
913
}
914
} // end while
915
j9thread_monitor_exit(vm->omrVM->_gcCycleOnMonitor);
916
#endif
917
}
918
919
extern char *compilationErrorNames[]; // defined in rossa.cpp
920
921
void
922
TR::CompilationInfoPerThreadBase::setCompilationThreadState(CompilationThreadState v)
923
{
924
TR_ASSERT(
925
_compInfo.getCompilationMonitor()->owned_by_self(),
926
"Modifying compilation thread state without ownership of the compilation queue monitor"
927
);
928
_previousCompilationThreadState = _compilationThreadState;
929
_compilationThreadState = v;
930
}
931
932
void
933
TR::CompilationInfoPerThread::setCompilationThreadState(CompilationThreadState v)
934
{
935
TR::CompilationInfoPerThreadBase::setCompilationThreadState(v);
936
}
937
938
bool
939
TR::CompilationInfoPerThreadBase::compilationThreadIsActive()
940
{
941
bool compThreadIsActive =
942
_compilationThreadState == COMPTHREAD_ACTIVE
943
|| _compilationThreadState == COMPTHREAD_SIGNAL_WAIT
944
|| _compilationThreadState == COMPTHREAD_WAITING;
945
return compThreadIsActive;
946
}
947
948
TR::FILE *TR::CompilationInfoPerThreadBase::_perfFile = NULL; // used on Linux for perl tool support
949
950
// Must not be called from different threads in parallel
951
TR::CompilationInfoPerThreadBase::CompilationInfoPerThreadBase(TR::CompilationInfo &compInfo, J9JITConfig *jitConfig, int32_t id, bool onSeparateThread) :
952
_compInfo(compInfo),
953
_jitConfig(jitConfig),
954
_sharedCacheReloRuntime(jitConfig),
955
#if defined(J9VM_OPT_JITSERVER)
956
_remoteCompileReloRuntime(jitConfig),
957
#endif /* defined(J9VM_OPT_JITSERVER) */
958
_compThreadId(id),
959
_onSeparateThread(onSeparateThread),
960
_vm(NULL),
961
_methodBeingCompiled(NULL),
962
_compiler(NULL),
963
_metadata(NULL),
964
_reservedDataCache(NULL),
965
_timeWhenCompStarted(),
966
_numJITCompilations(),
967
_qszWhenCompStarted(),
968
_compilationCanBeInterrupted(false),
969
_uninterruptableOperationDepth(0),
970
_compilationThreadState(COMPTHREAD_UNINITIALIZED),
971
_compilationShouldBeInterrupted(false),
972
#if defined(J9VM_OPT_JITSERVER)
973
_cachedClientDataPtr(NULL),
974
_clientStream(NULL),
975
_perClientPersistentMemory(NULL),
976
#endif /* defined(J9VM_OPT_JITSERVER) */
977
_addToJProfilingQueue(false)
978
{
979
// At this point, compilation threads have not been fully started yet. getNumTotalCompilationThreads()
980
// would not return a correct value. Need to use TR::Options::_numUsableCompilationThreads
981
TR_ASSERT_FATAL(_compThreadId < (TR::Options::_numUsableCompilationThreads + TR::CompilationInfo::MAX_DIAGNOSTIC_COMP_THREADS),
982
"Cannot have a compId %d greater than %u", _compThreadId, (TR::Options::_numUsableCompilationThreads + TR::CompilationInfo::MAX_DIAGNOSTIC_COMP_THREADS));
983
}
984
985
TR::CompilationInfoPerThread::CompilationInfoPerThread(TR::CompilationInfo &compInfo, J9JITConfig *jitConfig, int32_t id, bool isDiagnosticThread)
986
: TR::CompilationInfoPerThreadBase(compInfo, jitConfig, id, true),
987
_compThreadCPU(_compInfo.persistentMemory()->getPersistentInfo(), jitConfig, 490000000, id)
988
{
989
PORT_ACCESS_FROM_JITCONFIG(jitConfig);
990
_initializationSucceeded = false;
991
_osThread = 0;
992
_compilationThread = 0;
993
_compThreadPriority = J9THREAD_PRIORITY_USER_MAX;
994
_compThreadMonitor = TR::Monitor::create("JIT-CompThreadMonitor-??");
995
_lastCompilationDuration = 0;
996
997
// name the thread
998
//
999
// NOTE:
1000
// increasing MAX_*_COMP_THREADS over three digits requires an
1001
// increase in the length of _activeThreadName and _suspendedThreadName
1002
1003
// constant thread name formats
1004
static const char activeDiagnosticThreadName[] = "JIT Diagnostic Compilation Thread-%03d";
1005
static const char suspendedDiagnosticThreadName[] = "JIT Diagnostic Compilation Thread-%03d Suspended";
1006
static const char activeThreadName[] = "JIT Compilation Thread-%03d";
1007
static const char suspendedThreadName[] = "JIT Compilation Thread-%03d Suspended";
1008
1009
const char * selectedActiveThreadName;
1010
const char * selectedSuspendedThreadName;
1011
int activeThreadNameLength;
1012
int suspendedThreadNameLength;
1013
1014
// determine the correct name to use, and its length
1015
//
1016
// NOTE:
1017
// using sizeof(...) - 1 because the characters "%3d" will be replaced by three digits;
1018
// the null character however *is* counted by sizeof
1019
if (isDiagnosticThread)
1020
{
1021
selectedActiveThreadName = activeDiagnosticThreadName;
1022
selectedSuspendedThreadName = suspendedDiagnosticThreadName;
1023
activeThreadNameLength = sizeof(activeDiagnosticThreadName) - 1;
1024
suspendedThreadNameLength = sizeof(suspendedDiagnosticThreadName) - 1;
1025
_isDiagnosticThread = true;
1026
}
1027
else
1028
{
1029
selectedActiveThreadName = activeThreadName;
1030
selectedSuspendedThreadName = suspendedThreadName;
1031
activeThreadNameLength = sizeof(activeThreadName) - 1;
1032
suspendedThreadNameLength = sizeof(suspendedThreadName) - 1;
1033
_isDiagnosticThread = false;
1034
}
1035
1036
_activeThreadName = (char *) j9mem_allocate_memory(activeThreadNameLength, J9MEM_CATEGORY_JIT);
1037
_suspendedThreadName = (char *) j9mem_allocate_memory(suspendedThreadNameLength, J9MEM_CATEGORY_JIT);
1038
1039
if (_activeThreadName && _suspendedThreadName)
1040
{
1041
// NOTE:
1042
// the (char *) casts are done because on Z, sprintf expects
1043
// a (char *) instead of a (const char *)
1044
sprintf(_activeThreadName, (char *) selectedActiveThreadName, getCompThreadId());
1045
sprintf(_suspendedThreadName, (char *) selectedSuspendedThreadName, getCompThreadId());
1046
1047
_initializationSucceeded = true;
1048
}
1049
1050
_numJITCompilations = 0;
1051
_lastTimeThreadWasSuspended = 0;
1052
_lastTimeThreadWentToSleep = 0;
1053
1054
char *rtLogFileName = ((TR_JitPrivateConfig*)jitConfig->privateConfig)->rtLogFileName;
1055
if (rtLogFileName)
1056
{
1057
char fn[1024];
1058
1059
bool truncated = TR::snprintfTrunc(fn, sizeof(fn), "%s.%i", rtLogFileName, getCompThreadId());
1060
1061
if (!truncated)
1062
{
1063
_rtLogFile = fileOpen(TR::Options::getAOTCmdLineOptions(), jitConfig, fn, "wb", true);
1064
}
1065
else
1066
{
1067
fprintf(stderr, "Did not attempt to open comp thread rtlog %s because filename was truncated\n", fn);
1068
_rtLogFile = NULL;
1069
}
1070
}
1071
else
1072
{
1073
_rtLogFile = NULL;
1074
}
1075
1076
#if defined(J9VM_OPT_JITSERVER)
1077
_serverVM = NULL;
1078
_sharedCacheServerVM = NULL;
1079
1080
if (compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
1081
{
1082
_classesThatShouldNotBeNewlyExtended = new (PERSISTENT_NEW) PersistentUnorderedSet<TR_OpaqueClassBlock*>(
1083
PersistentUnorderedSet<TR_OpaqueClassBlock*>::allocator_type(TR::Compiler->persistentAllocator()));
1084
}
1085
else
1086
{
1087
_classesThatShouldNotBeNewlyExtended = NULL;
1088
}
1089
#endif /* defined(J9VM_OPT_JITSERVER) */
1090
}
1091
1092
TR::CompilationInfo::CompilationInfo(J9JITConfig *jitConfig) :
1093
#if defined(J9VM_OPT_JITSERVER)
1094
_sslKeys(decltype(_sslKeys)::allocator_type(TR::Compiler->persistentAllocator())),
1095
_sslCerts(decltype(_sslCerts)::allocator_type(TR::Compiler->persistentAllocator())),
1096
_classesCachedAtServer(decltype(_classesCachedAtServer)::allocator_type(TR::Compiler->persistentAllocator())),
1097
#endif /* defined(J9VM_OPT_JITSERVER) */
1098
_persistentMemory(pointer_cast<TR_PersistentMemory *>(jitConfig->scratchSegment)),
1099
_sharedCacheReloRuntime(jitConfig),
1100
_samplingThreadWaitTimeInDeepIdleToNotifyVM(-1),
1101
_numDiagnosticThreads(0),
1102
_numCompThreads(0),
1103
_arrayOfCompilationInfoPerThread(NULL)
1104
{
1105
// The object is zero-initialized before this method is called
1106
//
1107
::jitConfig = jitConfig;
1108
_jitConfig = jitConfig;
1109
1110
// For normal case with compilation on application thread this
1111
// initialization will be done later after we are sure that
1112
// the options have been processed
1113
1114
_vmStateOfCrashedThread = 0;
1115
1116
_cachedFreePhysicalMemoryB = 0;
1117
_cachedIncompleteFreePhysicalMemory = false;
1118
OMRPORT_ACCESS_FROM_J9PORT(jitConfig->javaVM->portLibrary);
1119
_cgroupMemorySubsystemEnabled = (OMR_CGROUP_SUBSYSTEM_MEMORY == omrsysinfo_cgroup_are_subsystems_enabled(OMR_CGROUP_SUBSYSTEM_MEMORY));
1120
_suspendThreadDueToLowPhysicalMemory = false;
1121
1122
// Initialize the compilation monitor
1123
//
1124
_compilationMonitor = TR::Monitor::create("JIT-CompilationQueueMonitor");
1125
_schedulingMonitor = TR::Monitor::create("JIT-SchedulingMonitor");
1126
#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
1127
_dltMonitor = TR::Monitor::create("JIT-DLTmonitor");
1128
#endif
1129
_iprofilerBufferArrivalMonitor = TR::Monitor::create("JIT-IProfilerBufferArrivalMonitor");
1130
_classUnloadMonitor = TR::MonitorTable::get()->getClassUnloadMonitor(); // by this time this variable is initialized
1131
// TODO: hang these monitors to something persistent
1132
_j9MonitorTable = TR::MonitorTable::get();
1133
1134
_gpuInitMonitor = TR::Monitor::create("JIT-GpuInitializationMonitor");
1135
_persistentMemory->getPersistentInfo()->setGpuInitializationMonitor(_gpuInitMonitor);
1136
1137
_iprofilerMaxCount = TR::Options::_maxIprofilingCountInStartupMode;
1138
1139
PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);
1140
_cpuUtil = 0; // Field will be set in onLoadInternal after option processing
1141
static char *verySmallQueue = feGetEnv("VERY_SMALL_QUEUE");
1142
if (verySmallQueue)
1143
{
1144
int temp = atoi(verySmallQueue);
1145
if (temp)
1146
VERY_SMALL_QUEUE = temp;
1147
}
1148
static char *smallQueue = feGetEnv("SMALL_QUEUE");
1149
if (smallQueue)
1150
{
1151
int temp = atoi(smallQueue);
1152
if (temp)
1153
SMALL_QUEUE = temp;
1154
}
1155
static char *mediumLargeQueue = feGetEnv("MEDIUM_LARGE_QUEUE");
1156
if (mediumLargeQueue)
1157
{
1158
int temp = atoi(mediumLargeQueue);
1159
if (temp)
1160
MEDIUM_LARGE_QUEUE = temp;
1161
}
1162
static char *largeQueue = feGetEnv("LARGE_QUEUE");
1163
if (largeQueue)
1164
{
1165
int temp = atoi(largeQueue);
1166
if (temp)
1167
LARGE_QUEUE = temp;
1168
}
1169
static char *veryLargeQueue = feGetEnv("VERY_LARGE_QUEUE");
1170
if (veryLargeQueue)
1171
{
1172
int temp = atoi(veryLargeQueue);
1173
if (temp)
1174
VERY_LARGE_QUEUE = temp;
1175
}
1176
statCompErrors.init("CompilationErrors", compilationErrorNames, 0);
1177
1178
setSamplerState(TR::CompilationInfo::SAMPLER_NOT_INITIALIZED);
1179
1180
setIsWarmSCC(TR_maybe);
1181
_cpuEntitlement.init(jitConfig);
1182
_lowPriorityCompilationScheduler.setCompInfo(this);
1183
_JProfilingQueue.setCompInfo(this);
1184
_interpSamplTrackingInfo = new (PERSISTENT_NEW) TR_InterpreterSamplingTracking(this);
1185
#if defined(J9VM_OPT_JITSERVER)
1186
_clientSessionHT = NULL; // This will be set later when options are processed
1187
_unloadedClassesTempList = NULL;
1188
_illegalFinalFieldModificationList = NULL;
1189
_newlyExtendedClasses = NULL;
1190
_sequencingMonitor = TR::Monitor::create("JIT-SequencingMonitor");
1191
_classesCachedAtServerMonitor = TR::Monitor::create("JIT-ClassesCachedAtServerMonitor");
1192
_compReqSeqNo = 0;
1193
_chTableUpdateFlags = 0;
1194
_localGCCounter = 0;
1195
_activationPolicy = JITServer::CompThreadActivationPolicy::AGGRESSIVE;
1196
_sharedROMClassCache = NULL;
1197
_JITServerAOTCacheMap = NULL;
1198
_JITServerAOTDeserializer = NULL;
1199
#endif /* defined(J9VM_OPT_JITSERVER) */
1200
}
1201
1202
TR::CompilationInfoPerThreadBase *TR::CompilationInfo::getCompInfoWithID(int32_t ID)
1203
{
1204
for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)
1205
{
1206
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
1207
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
1208
1209
if (curCompThreadInfoPT->getCompThreadId() == ID)
1210
return curCompThreadInfoPT;
1211
}
1212
1213
return NULL;
1214
}
1215
1216
// Must hold compilation queue monitor when calling this method
1217
//
1218
TR::CompilationInfoPerThread *TR::CompilationInfo::getFirstSuspendedCompilationThread() // MCT
1219
{
1220
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
1221
{
1222
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
1223
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
1224
1225
CompilationThreadState currentState = curCompThreadInfoPT->getCompilationThreadState();
1226
if (currentState == COMPTHREAD_SUSPENDED ||
1227
currentState == COMPTHREAD_SIGNAL_SUSPEND)
1228
return curCompThreadInfoPT;
1229
}
1230
1231
return NULL;
1232
}
1233
1234
TR::Compilation *TR::CompilationInfo::getCompilationWithID(int32_t ID)
1235
{
1236
TR::CompilationInfoPerThreadBase *ciptb = getCompInfoWithID(ID);
1237
return ciptb ? ciptb->getCompilation() : NULL;
1238
}
1239
1240
void TR::CompilationInfo::setAllCompilationsShouldBeInterrupted()
1241
{
1242
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
1243
{
1244
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
1245
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
1246
1247
curCompThreadInfoPT->setCompilationShouldBeInterrupted(GC_COMP_INTERRUPT);
1248
}
1249
1250
_lastCompilationsShouldBeInterruptedTime = getPersistentInfo()->getElapsedTime(); // RAS
1251
}
1252
1253
bool TR::CompilationInfo::asynchronousCompilation()
1254
{
1255
static bool answer = (!TR::Options::getJITCmdLineOptions()->getOption(TR_DisableAsyncCompilation) &&
1256
TR::Options::getJITCmdLineOptions()->getInitialBCount() &&
1257
TR::Options::getJITCmdLineOptions()->getInitialCount() &&
1258
TR::Options::getAOTCmdLineOptions()->getInitialSCount() &&
1259
TR::Options::getAOTCmdLineOptions()->getInitialBCount() &&
1260
TR::Options::getAOTCmdLineOptions()->getInitialCount()
1261
);
1262
return answer;
1263
}
1264
1265
TR_YesNoMaybe TR::CompilationInfo::detectCompThreadStarvation()
1266
{
1267
// If compilation queue is small, then we don't care about comp thread starvation
1268
if (getOverallQueueWeight() < TR::Options::_queueWeightThresholdForStarvation)
1269
return TR_no;
1270
// If compilation threads already consume too much CPU, do not throttle application threads
1271
if (exceedsCompCpuEntitlement() != TR_no)
1272
return TR_no;
1273
// If the state is IDLE we cannot starve the compilation threads
1274
//if (getPersistentInfo()->getJitState() == IDLE_STATE)
1275
// return TR_no;
1276
1277
// If there are idle cycles on the CPU set where this JVM can run
1278
// then the compilation threads should be able to use those cycles
1279
// The following is just an approximation because we look at idle
1280
// cyles on the entire machine
1281
if (getCpuUtil()->isFunctional() &&
1282
getCpuUtil()->getAvgCpuIdle() > 5 && // This is for the entire machine
1283
getCpuUtil()->getVmCpuUsage() + 10 < getJvmCpuEntitlement()) // at least 10% unutilized by this JVM
1284
return TR_no;
1285
1286
// Large queue and small CPU utilization for the compilation thread
1287
// is a sign of compilation thread starvation
1288
// TODO: augment the logic with CPU utilization and number of CPUs allowed to use
1289
1290
// Find compilation threads that are not suspended and look at their CPU utilization
1291
// NOTE: normally we need to acquire the compQMonitor when looking at comp thread state
1292
// Here we allow a small imprecision because it's just a heuristic
1293
// We count on the fact that threads never get deleted
1294
int32_t totalCompCpuUtil = 0;
1295
int32_t numActive = 0;
1296
TR_YesNoMaybe answer = TR_maybe;
1297
bool compCpuFunctional = true;
1298
for (int32_t compId = 0; compId < _numCompThreads; compId++)
1299
{
1300
// We must look at all active threads because we want to avoid the
1301
// case where they compete with each other (4 comp threads on a single processor)
1302
//
1303
TR::CompilationInfoPerThread *compInfoPT = _arrayOfCompilationInfoPerThread[compId];
1304
TR_ASSERT(compInfoPT, "compInfoPT must exist because we don't destroy compilation threads");
1305
if (compInfoPT->compilationThreadIsActive())
1306
{
1307
numActive++;
1308
int32_t compCpuUtil = compInfoPT->getCompThreadCPU().getThreadLastCpuUtil();
1309
if (compCpuUtil >= 0) // when not functional or too soon to tell the answer is negative
1310
{
1311
totalCompCpuUtil += compCpuUtil;
1312
if (compCpuUtil >= TR::Options::_cpuUtilThresholdForStarvation) // 25%
1313
answer = TR_no; // Good utilization for at least one thread; no reason to make app threads sleep
1314
}
1315
else
1316
{
1317
compCpuFunctional = false;
1318
}
1319
}
1320
}
1321
_totalCompThreadCpuUtilWhenStarvationComputed = totalCompCpuUtil; // RAS
1322
_numActiveCompThreadsWhenStarvationComputed = numActive; // RAS
1323
1324
1325
if (answer == TR_maybe && compCpuFunctional) // Didn't reach a conclusion yet
1326
{
1327
if (getCpuUtil()->isFunctional())
1328
{
1329
// If the CPU utilization of all the active compilation threads is at least
1330
// half of the JVM utilization of the JVM, then compilation threads are not starved
1331
if ((totalCompCpuUtil << 1) >= getCpuUtil()->getVmCpuUsage())
1332
{
1333
answer = TR_no;
1334
}
1335
else // If all compilation threads are using less than 75% CPU then we declare starvation
1336
{
1337
if (totalCompCpuUtil < 75)
1338
answer = TR_yes;
1339
}
1340
}
1341
}
1342
return answer;
1343
}
1344
1345
// This should be called only if detectCompThreadStarvation returns TR_yes
1346
int32_t TR::CompilationInfo::computeAppSleepNano() const
1347
{
1348
int32_t QW = getOverallQueueWeight();
1349
if (QW < TR::Options::_queueWeightThresholdForAppThreadYield)
1350
return 0;
1351
1352
// I don't like to throttle application threads if I can still activate comp threads.
1353
int32_t numCompThreadsSuspended = getNumUsableCompilationThreads() - getNumCompThreadsActive();
1354
if (numCompThreadsSuspended > 0)
1355
return 0;
1356
1357
if (QW < 4*TR::Options::_queueWeightThresholdForAppThreadYield)
1358
return (250000*(QW/TR::Options::_queueWeightThresholdForAppThreadYield));
1359
else return 1000000;
1360
}
1361
1362
void TR::CompilationInfo::vlogAcquire()
1363
{
1364
if (!_vlogMonitor)
1365
_vlogMonitor = TR::Monitor::create("JIT-VerboseLogMonitor");
1366
1367
if (_vlogMonitor)
1368
_vlogMonitor->enter();
1369
}
1370
1371
void TR::CompilationInfo::vlogRelease()
1372
{
1373
if (_vlogMonitor)
1374
_vlogMonitor->exit();
1375
}
1376
1377
void TR::CompilationInfo::rtlogAcquire()
1378
{
1379
if (!_rtlogMonitor)
1380
_rtlogMonitor = TR::Monitor::create("JIT-RunTimeLogMonitor");
1381
1382
if (_rtlogMonitor)
1383
_rtlogMonitor->enter();
1384
}
1385
1386
void TR::CompilationInfo::rtlogRelease()
1387
{
1388
if (_rtlogMonitor)
1389
_rtlogMonitor->exit();
1390
}
1391
1392
void TR::CompilationInfo::acquireCompMonitor(J9VMThread *vmThread) // used when we know we have a compilation monitor
1393
{
1394
getCompilationMonitor()->enter();
1395
}
1396
1397
void TR::CompilationInfo::releaseCompMonitor(J9VMThread *vmThread) // used when we know we have a compilation monitor
1398
{
1399
getCompilationMonitor()->exit();
1400
}
1401
1402
void TR::CompilationInfo::waitOnCompMonitor(J9VMThread *vmThread)
1403
{
1404
getCompilationMonitor()->wait();
1405
}
1406
1407
intptr_t TR::CompilationInfo::waitOnCompMonitorTimed(J9VMThread *vmThread, int64_t millis, int32_t nanos)
1408
{
1409
intptr_t retCode;
1410
retCode = getCompilationMonitor()->wait_timed(millis, nanos);
1411
return retCode;
1412
}
1413
1414
void TR::CompilationInfo::acquireCompilationLock()
1415
{
1416
if (_compilationMonitor)
1417
{
1418
acquireCompMonitor(0);
1419
debugPrint("\t\texternal user acquiring compilation monitor\n");
1420
}
1421
}
1422
1423
void TR::CompilationInfo::releaseCompilationLock()
1424
{
1425
if (_compilationMonitor)
1426
{
1427
debugPrint("\t\texternal user releasing compilatoin monitor\n");
1428
releaseCompMonitor(0);
1429
}
1430
}
1431
1432
TR::Monitor * TR::CompilationInfo::createLogMonitor()
1433
{
1434
_logMonitor = TR::Monitor::create("JIT-LogMonitor");
1435
return _logMonitor;
1436
}
1437
1438
void TR::CompilationInfo::acquireLogMonitor()
1439
{
1440
if (_logMonitor)
1441
{
1442
_logMonitor->enter();
1443
}
1444
}
1445
1446
void TR::CompilationInfo::releaseLogMonitor()
1447
{
1448
if ( _logMonitor)
1449
{
1450
_logMonitor->exit();
1451
}
1452
}
1453
1454
uint32_t
1455
TR::CompilationInfo::getMethodBytecodeSize(const J9ROMMethod * romMethod)
1456
{
1457
return (romMethod->bytecodeSizeHigh << 16) + romMethod->bytecodeSizeLow;
1458
}
1459
1460
#if defined(J9VM_OPT_JITSERVER)
1461
JITServer::ServerStream *
1462
TR::CompilationInfo::getStream()
1463
{
1464
return (TR::compInfoPT) ? TR::compInfoPT->getStream() : NULL;
1465
}
1466
#endif /* defined(J9VM_OPT_JITSERVER) */
1467
1468
uint32_t
1469
TR::CompilationInfo::getMethodBytecodeSize(J9Method* method)
1470
{
1471
#if defined(J9VM_OPT_JITSERVER)
1472
if (auto stream = TR::CompilationInfo::getStream())
1473
{
1474
{
1475
ClientSessionData *clientSessionData = TR::compInfoPT->getClientData();
1476
OMR::CriticalSection getRemoteROMClass(clientSessionData->getROMMapMonitor());
1477
auto it = clientSessionData->getJ9MethodMap().find(method);
1478
if (it != clientSessionData->getJ9MethodMap().end())
1479
{
1480
return getMethodBytecodeSize(it->second._romMethod);
1481
}
1482
}
1483
stream->write(JITServer::MessageType::CompInfo_getMethodBytecodeSize, method);
1484
return std::get<0>(stream->read<uint32_t>());
1485
}
1486
#endif /* defined(J9VM_OPT_JITSERVER) */
1487
return getMethodBytecodeSize(J9_ROM_METHOD_FROM_RAM_METHOD(method));
1488
}
1489
1490
bool
1491
TR::CompilationInfo::isJSR292(const J9ROMMethod *romMethod)
1492
{
1493
return (_J9ROMMETHOD_J9MODIFIER_IS_SET(romMethod, J9AccMethodHasMethodHandleInvokes));
1494
}
1495
1496
bool
1497
TR::CompilationInfo::isJSR292(J9Method *j9method)
1498
{
1499
#if defined(J9VM_OPT_JITSERVER)
1500
if (auto stream = TR::CompilationInfo::getStream())
1501
{
1502
{
1503
ClientSessionData *clientSessionData = TR::compInfoPT->getClientData();
1504
OMR::CriticalSection getRemoteROMClass(clientSessionData->getROMMapMonitor());
1505
auto it = clientSessionData->getJ9MethodMap().find(j9method);
1506
if (it != clientSessionData->getJ9MethodMap().end())
1507
{
1508
return isJSR292(it->second._romMethod);
1509
}
1510
}
1511
stream->write(JITServer::MessageType::CompInfo_isJSR292, j9method);
1512
return std::get<0>(stream->read<bool>());
1513
}
1514
#endif /* defined(J9VM_OPT_JITSERVER) */
1515
return isJSR292(J9_ROM_METHOD_FROM_RAM_METHOD(j9method));
1516
}
1517
1518
#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))
1519
void
1520
TR::CompilationInfo::disableAOTCompilations()
1521
{
1522
TR::Options::getAOTCmdLineOptions()->setOption(TR_NoStoreAOT, true);
1523
TR_DataCacheManager::getManager()->startupOver();
1524
}
1525
#endif
1526
1527
// Print the entire qualified name of the given method to the vlog
1528
// Caller must acquire vlog mutex
1529
//
1530
void TR::CompilationInfo::printMethodNameToVlog(J9Method *method)
1531
{
1532
J9UTF8 *className;
1533
J9UTF8 *name;
1534
J9UTF8 *signature;
1535
getClassNameSignatureFromMethod(method, className, name, signature);
1536
TR_VerboseLog::write("%.*s.%.*s%.*s", J9UTF8_LENGTH(className), (char *) J9UTF8_DATA(className),
1537
J9UTF8_LENGTH(name), (char *) J9UTF8_DATA(name),
1538
J9UTF8_LENGTH(signature), (char *) J9UTF8_DATA(signature));
1539
}
1540
1541
void TR::CompilationInfo::printMethodNameToVlog(const J9ROMClass* romClass, const J9ROMMethod* romMethod)
1542
{
1543
J9UTF8 * className = J9ROMCLASS_CLASSNAME(romClass);
1544
J9UTF8 * name = J9ROMMETHOD_NAME(romMethod);
1545
J9UTF8 * signature = J9ROMMETHOD_SIGNATURE(romMethod);
1546
TR_VerboseLog::write("%.*s.%.*s%.*s", J9UTF8_LENGTH(className), (char *)J9UTF8_DATA(className),
1547
J9UTF8_LENGTH(name), (char *)J9UTF8_DATA(name),
1548
J9UTF8_LENGTH(signature), (char *)J9UTF8_DATA(signature));
1549
}
1550
1551
//----------------------- Must hide these in TR::CompilationInfo ------
1552
#include "env/CpuUtilization.hpp"
1553
#include "infra/Statistics.hpp"
1554
#undef STATS
1555
#ifdef STATS
1556
TR_Stats statBudgetEpoch("Budget len at begining of epoch");
1557
TR_Stats statBudgetSmallLag("Budget/comp when smallLag");
1558
TR_Stats statBudgetMediumLag("Budget/comp when mediumLag");
1559
TR_Stats statEpochLength("Epoch lengh (ms)");
1560
char *eventNames[]={"SyncReq", "SmallLag", "LargeLag", "Medium-NoBudget", "Medium-highBudget", "Medium-LowBudget", "Medium-Idle"};
1561
TR_StatsEvents<7> statEvents("Scenarios", eventNames, 0);
1562
char *priorityName[]={"High","Normal"};
1563
TR_StatsEvents<2> statLowPriority("Medium-lowBudget-priority",priorityName,0);
1564
TR_Stats statLowBudget("Medium-lowBudget-budget");
1565
TR_Stats statQueueSize("Size of Compilation queue");
1566
TR_Stats statOverhead("Overhead of dynamicThreadPriority in cycles");
1567
#endif
1568
1569
1570
//---------------------- getCompilationLag --------------------------------
1571
// Looks at 2 things: size of method queue and the waiting time for the
1572
// current request to be processed.
1573
// Returns a compDelay code: LARGE_LAG, MEDIUM_LAG, SMALL_LAG
1574
//--------------------------------------------------------------------------
1575
int32_t TR::CompilationInfo::getCompilationLag()
1576
{
1577
if (getMethodQueueSize() > TR::CompilationInfo::LARGE_QUEUE)
1578
return TR::CompilationInfo::LARGE_LAG;
1579
1580
if (getMethodQueueSize() < TR::CompilationInfo::SMALL_QUEUE)
1581
return TR::CompilationInfo::SMALL_LAG;
1582
1583
return TR::CompilationInfo::MEDIUM_LAG;
1584
}
1585
1586
//------------------------ changeCompThreadPriority ------------------
1587
int32_t TR::CompilationInfoPerThread::changeCompThreadPriority(int32_t newPriority, int32_t locationCode)
1588
{
1589
// once in a while test that _compThreadPriority is OK;
1590
// we need this because the code is not thread safe
1591
1592
static uint32_t numInvocations = 0;
1593
if (((++numInvocations) & 0xf) == 0)
1594
{
1595
_compThreadPriority = j9thread_get_priority(getOsThread());
1596
}
1597
int32_t oldPriority = _compThreadPriority;
1598
// FIXME: minimize multithreading issues
1599
if (oldPriority != newPriority)
1600
{
1601
j9thread_set_priority(getOsThread(), newPriority);
1602
_compThreadPriority = newPriority;
1603
_compInfo._statNumPriorityChanges++;
1604
#ifdef STATS
1605
fprintf(stderr, "Changed priority to %d, location=%d\n", newPriority, locationCode);
1606
#endif
1607
}
1608
1609
return oldPriority;
1610
}
1611
1612
//------------------------ dynamicThreadPriority -------------------
1613
bool TR::CompilationInfo::dynamicThreadPriority()
1614
{
1615
static bool answer = TR::Options::getCmdLineOptions()->getOption(TR_DynamicThreadPriority) &&
1616
asynchronousCompilation() && TR::Compiler->target.numberOfProcessors() < 4;
1617
return answer;
1618
}
1619
1620
1621
// Needs compilation monitor in hand
1622
//----------------------------- enqueueCompReqToLPQ ------------------------
1623
void TR_LowPriorityCompQueue::enqueueCompReqToLPQ(TR_MethodToBeCompiled *compReq)
1624
{
1625
// add at the end of queue
1626
if (_lastLPQentry)
1627
_lastLPQentry->_next = compReq;
1628
else
1629
_firstLPQentry = compReq;
1630
1631
_lastLPQentry = compReq;
1632
_sizeLPQ++; // increase the size of LPQ
1633
increaseLPQWeightBy(compReq->_weight);
1634
}
1635
1636
//---------------------------- createLowPriorityCompReqAndQueueIt ---------------------
1637
bool TR_LowPriorityCompQueue::createLowPriorityCompReqAndQueueIt(TR::IlGeneratorMethodDetails &details, void *startPC, uint8_t reason)
1638
{
1639
TR_OptimizationPlan *plan = TR_OptimizationPlan::alloc(warm); // TODO: pick first opt level
1640
if (!plan)
1641
return false; // OOM
1642
1643
TR_MethodToBeCompiled * compReq = _compInfo->getCompilationQueueEntry();
1644
if (!compReq)
1645
{
1646
TR_OptimizationPlan::freeOptimizationPlan(plan);
1647
return false; // OOM
1648
}
1649
compReq->initialize(details, 0, CP_ASYNC_ABOVE_MIN, plan);
1650
compReq->_reqFromSecondaryQueue = reason;
1651
compReq->_jitStateWhenQueued = _compInfo->getPersistentInfo()->getJitState();
1652
compReq->_oldStartPC = startPC;
1653
compReq->_async = true; // app threads are not waiting for it
1654
1655
1656
1657
// Determine entry weight
1658
J9Method *j9method = details.getMethod();
1659
J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(j9method);
1660
compReq->_weight = (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod)) ? TR::CompilationInfo::WARM_LOOPY_WEIGHT : TR::CompilationInfo::WARM_LOOPLESS_WEIGHT;
1661
// add at the end of queue
1662
enqueueCompReqToLPQ(compReq);
1663
incStatsReqQueuedToLPQ(reason);
1664
return true;
1665
}
1666
1667
//------------------------ addFirstTimeReqToLPQ ---------------------
1668
bool TR_LowPriorityCompQueue::addFirstTimeCompReqToLPQ(J9Method *j9method, uint8_t reason)
1669
{
1670
if (TR::CompilationInfo::isCompiled(j9method))
1671
return false;
1672
TR::IlGeneratorMethodDetails details(j9method);
1673
return createLowPriorityCompReqAndQueueIt(details, NULL, reason);
1674
}
1675
1676
1677
//------------------------ addUpgradeReqToLPQ ----------------------
1678
// This method is used when the JIT performs a low optimized compilation
1679
// and then schedules a low priority upgrade compilation for the same method
1680
//------------------------------------------------------------------
1681
bool TR_LowPriorityCompQueue::addUpgradeReqToLPQ(TR_MethodToBeCompiled *compReq, uint8_t reason)
1682
{
1683
TR_ASSERT(!compReq->getMethodDetails().isNewInstanceThunk(), "classForNewInstance is sync req");
1684
// filter out DLT compilations and fixed opt level situations
1685
if (compReq->isDLTCompile() || !TR::Options::getCmdLineOptions()->allowRecompilation())
1686
return false;
1687
return createLowPriorityCompReqAndQueueIt(compReq->getMethodDetails(), compReq->_newStartPC, reason);
1688
}
1689
1690
bool TR::CompilationInfo::canProcessLowPriorityRequest()
1691
{
1692
// To avoid overhead cycling through all the threads, we should first
1693
// check if there is anything in that low priority queue
1694
//
1695
if (!getLowPriorityCompQueue().hasLowPriorityRequest()) // access _firstLPQentry without monitor in hand
1696
return false;
1697
1698
// If the main compilation queue has requests, we should serve those first
1699
if (getMethodQueueSize() != 0)
1700
return false;
1701
1702
#if defined(J9VM_OPT_JITSERVER)
1703
// If the first LPQ entry is REASON_SERVER_UNAVAILABLE, only attempt compilation if server is available by now
1704
if (getLowPriorityCompQueue().getFirstLPQRequest()->_reqFromSecondaryQueue == TR_MethodToBeCompiled::REASON_SERVER_UNAVAILABLE)
1705
return JITServerHelpers::isServerAvailable();
1706
#endif
1707
1708
// To process a request from the low priority queue we need to have
1709
// (1) no other compilation in progress (not required if TR_ConcurrentLPQ is enabled)
1710
// (2) some idle CPU
1711
// (3) current JVM not taking its entire share of CPU entitlement
1712
//
1713
if (TR::Options::getCmdLineOptions()->getOption(TR_ConcurrentLPQ) &&
1714
_jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP) // ConcurrentLPQ is too damaging to startup
1715
{
1716
if ((getCpuUtil() && getCpuUtil()->isFunctional() &&
1717
getCpuUtil()->getAvgCpuIdle() > idleThreshold() && // enough idle time
1718
getJvmCpuEntitlement() - getCpuUtil()->getVmCpuUsage() >= 200)) // at least 2 cpus should be not utilized
1719
return true;
1720
// Fall through the next case where we allow LPQ if the JVM leaves 50% of a CPU
1721
// unutilized, but there should be nothing in the main queue
1722
}
1723
1724
// Cycle through all the compilation threads
1725
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
1726
{
1727
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
1728
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
1729
1730
if (curCompThreadInfoPT->getMethodBeingCompiled())
1731
return false;
1732
}
1733
return (getCpuUtil() && getCpuUtil()->isFunctional() &&
1734
getCpuUtil()->getAvgCpuIdle() > idleThreshold() && // enough idle time
1735
getJvmCpuEntitlement() - getCpuUtil()->getVmCpuUsage() > 50); // at least half a processor should be empty
1736
}
1737
1738
int64_t
1739
TR::CompilationInfo::getCpuTimeSpentInCompilation()
1740
{
1741
I_64 totalTime = 0;
1742
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
1743
{
1744
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
1745
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
1746
1747
totalTime += j9thread_get_cpu_time(curCompThreadInfoPT->getOsThread());
1748
}
1749
1750
return totalTime;
1751
}
1752
1753
int32_t
1754
TR::CompilationInfo::changeCompThreadPriority(int32_t priority, int32_t locationCode)
1755
{
1756
fprintf(stderr, "Look at this code again\n");
1757
return 0;
1758
}
1759
1760
1761
1762
1763
//--------------------- SmoothCompilation ------------------
1764
// How to improve: move all this computation outside the monitor
1765
// Do not lower the priority when inside the monitor
1766
// Minimize the number of priority changes by histerezis
1767
//
1768
// TODO: Does any of the calls in here require VM access?
1769
//----------------------------------------------------------
1770
bool
1771
TR::CompilationInfo::SmoothCompilation(TR_MethodToBeCompiled *entry, int32_t *optLevelAdjustment)
1772
{
1773
bool shouldAddRequestToUpgradeQueue = false;
1774
1775
if (shouldDowngradeCompReq(entry))
1776
{
1777
*optLevelAdjustment = -1; // decrease opt level
1778
_statNumDowngradeInterpretedMethod++;
1779
if (TR::Options::getCmdLineOptions()->getOption(TR_UseLowPriorityQueueDuringCLP) && !entry->isJNINative())
1780
shouldAddRequestToUpgradeQueue = true;
1781
}
1782
else
1783
{
1784
*optLevelAdjustment = 0; // unchanged opt level (default)
1785
}
1786
1787
if (shouldAddRequestToUpgradeQueue && entry->getMethodDetails().isNewInstanceThunk())
1788
shouldAddRequestToUpgradeQueue = false;
1789
return shouldAddRequestToUpgradeQueue;
1790
}
1791
1792
int32_t TR::CompilationInfo::getCompBudget() const
1793
{
1794
return _compilationBudget * (int32_t)TR::Compiler->target.numberOfProcessors();
1795
}
1796
1797
void
1798
TR::CompilationInfo::decNumGCRReqestsQueued(TR_MethodToBeCompiled *entry)
1799
{
1800
if (entry->_GCRrequest) _numGCRQueued--;
1801
}
1802
1803
void
1804
TR::CompilationInfo::incNumGCRRequestsQueued(TR_MethodToBeCompiled *entry)
1805
{
1806
entry->_GCRrequest = true; _numGCRQueued++;
1807
}
1808
1809
void
1810
TR::CompilationInfo::decNumInvReqestsQueued(TR_MethodToBeCompiled *entry)
1811
{
1812
if (entry->_entryIsCountedAsInvRequest)
1813
{
1814
_numInvRequestsInCompQueue--;
1815
TR_ASSERT(_numInvRequestsInCompQueue >= 0, "_numInvRequestsInCompQueue is negative : %d", _numInvRequestsInCompQueue);
1816
}
1817
}
1818
1819
void
1820
TR::CompilationInfo::incNumInvRequestsQueued(TR_MethodToBeCompiled *entry)
1821
{
1822
entry->_entryIsCountedAsInvRequest = true; _numInvRequestsInCompQueue++;
1823
}
1824
1825
void
1826
TR::CompilationInfo::updateCompQueueAccountingOnDequeue(TR_MethodToBeCompiled *entry)
1827
{
1828
_numQueuedMethods--; // one less method in the queue
1829
decNumGCRReqestsQueued(entry);
1830
decNumInvReqestsQueued(entry);
1831
if (entry->getMethodDetails().isOrdinaryMethod() && entry->_oldStartPC==0)
1832
{
1833
_numQueuedFirstTimeCompilations--;
1834
TR_ASSERT(_numQueuedFirstTimeCompilations >= 0, "_numQueuedFirstTimeCompilations is negative : %d", _numQueuedFirstTimeCompilations);
1835
}
1836
// Note: queue weight is handled separately because a method that is currently being
1837
// compiled is considered as bringing some weight to the processing backlog
1838
}
1839
1840
1841
//----------------------- useOptLevelAdjustment ---------------------
1842
// This scheme will be used only on multiprocessors because it is
1843
// based on compilation request queue size. On uniprocessors this
1844
// queue is always very small because, as soon as a request is put in
1845
// the queue, the compilation thread (working at MAX priority) will
1846
// occupy the CPU until compilation finishes
1847
//-------------------------------------------------------------------
1848
bool TR::CompilationInfo::useOptLevelAdjustment()
1849
{
1850
static bool answer = TR::Options::getCmdLineOptions()->getOption(TR_UseOptLevelAdjustment) &&
1851
asynchronousCompilation() &&
1852
TR::Options::getCmdLineOptions()->allowRecompilation();
1853
return answer;
1854
}
1855
1856
1857
// Must have compilation monitor in hand when calling this function
1858
void TR::CompilationInfo::invalidateRequestsForNativeMethods(J9Class * clazz, J9VMThread * vmThread)
1859
{
1860
bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks);
1861
if (verbose)
1862
TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "invalidateRequestsForNativeMethods class=%p vmThread=%p", clazz, vmThread);
1863
1864
// Cycle through all the compilation threads
1865
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
1866
{
1867
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
1868
TR_MethodToBeCompiled *methodBeingCompiled = curCompThreadInfoPT->getMethodBeingCompiled();
1869
// Mark the method being compiled that it has been unloaded.
1870
// If it is already marked, then there is nothing to do.
1871
//
1872
if (methodBeingCompiled && !methodBeingCompiled->_unloadedMethod)
1873
{
1874
J9Method *method = methodBeingCompiled->getMethodDetails().getMethod();
1875
if (method)
1876
{
1877
J9Class *classOfMethod = J9_CLASS_FROM_METHOD(method);
1878
if (classOfMethod == clazz && TR::CompilationInfo::isJNINative(method))
1879
{
1880
// fail this compilation
1881
if (methodBeingCompiled->_priority < CP_SYNC_MIN) // ASYNC compilation, typical case
1882
{
1883
TR_ASSERT(methodBeingCompiled->_numThreadsWaiting == 0, "Async compilations should not have threads waiting");
1884
methodBeingCompiled->_newStartPC = 0;
1885
}
1886
else
1887
{
1888
methodBeingCompiled->acquireSlotMonitor(vmThread); // get queue-slot monitor
1889
methodBeingCompiled->_newStartPC = 0;
1890
methodBeingCompiled->getMonitor()->notifyAll(); // notify the waiting thread
1891
methodBeingCompiled->releaseSlotMonitor(vmThread); // release queue-slot monitor
1892
}
1893
methodBeingCompiled->_unloadedMethod = true;
1894
if (verbose)
1895
TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "Have marked as unloaded the JNI thunk compilation for method %p", method);
1896
}
1897
}
1898
}
1899
} // end for
1900
1901
// if compiling on app thread, there is no compilation queue
1902
TR_MethodToBeCompiled *cur = _methodQueue;
1903
TR_MethodToBeCompiled *prev = NULL;
1904
while (cur)
1905
{
1906
TR_MethodToBeCompiled *next = cur->_next;
1907
J9Method *method = cur->getMethodDetails().getMethod();
1908
if (method &&
1909
J9_CLASS_FROM_METHOD(method) == clazz &&
1910
TR::CompilationInfo::isJNINative(method))
1911
{
1912
if (verbose)
1913
TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "Invalidating JNI thunk compile request for method %p class %p", method, J9_CLASS_FROM_METHOD(method));
1914
if (cur->_priority >= CP_SYNC_MIN)
1915
{
1916
// squash this compilation request but inform waiting threads
1917
cur->acquireSlotMonitor(vmThread); // get queue-slot monitor
1918
cur->_newStartPC = 0;
1919
cur->getMonitor()->notifyAll(); // notify the waiting thread
1920
cur->releaseSlotMonitor(vmThread); // release queue-slot monitor
1921
}
1922
else
1923
{
1924
TR_ASSERT(cur->_numThreadsWaiting == 0, "Async compilations should not have threads waiting");
1925
}
1926
1927
// detach from queue
1928
if (prev)
1929
prev->_next = cur->_next;
1930
else
1931
_methodQueue = cur->_next;
1932
updateCompQueueAccountingOnDequeue(cur);
1933
// decrease the queue weight
1934
decreaseQueueWeightBy(cur->_weight);
1935
// put back into the pool
1936
recycleCompilationEntry(cur);
1937
}
1938
else
1939
{
1940
prev = cur;
1941
}
1942
cur = next;
1943
}
1944
// LPQ does not need to be checked because JNI thunk requests cannot be put in LPQ
1945
}
1946
1947
void TR::CompilationInfo::invalidateRequestsForUnloadedMethods(TR_OpaqueClassBlock * clazz, J9VMThread * vmThread, bool hotCodeReplacement)
1948
{
1949
TR_J9VMBase * fe = TR_J9VMBase::get(_jitConfig, vmThread);
1950
J9Class *unloadedClass = clazz ? TR::Compiler->cls.convertClassOffsetToClassPtr(clazz) : NULL;
1951
bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks);
1952
if (verbose)
1953
TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "invalidateRequestsForUnloadedMethods class=%p vmThread=%p hotCodeReplacement=%d", clazz, vmThread, hotCodeReplacement);
1954
1955
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
1956
{
1957
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
1958
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
1959
1960
TR_MethodToBeCompiled *methodBeingCompiled = curCompThreadInfoPT->getMethodBeingCompiled();
1961
// Mark the method being compiled that it has been unloaded.
1962
// If it is already marked, then there is nothing to do.
1963
//
1964
if (methodBeingCompiled && !methodBeingCompiled->_unloadedMethod)
1965
{
1966
TR::IlGeneratorMethodDetails &details = methodBeingCompiled->getMethodDetails();
1967
J9Method *method = details.getMethod();
1968
TR_ASSERT(method, "_method can be NULL only at shutdown time");
1969
if ((!unloadedClass && hotCodeReplacement) || // replacement in FSD mode
1970
J9_CLASS_FROM_METHOD(method) == unloadedClass ||
1971
(details.isNewInstanceThunk() &&
1972
static_cast<J9::NewInstanceThunkDetails &>(details).isThunkFor(unloadedClass)))
1973
{
1974
if (!hotCodeReplacement)
1975
{
1976
TR_ASSERT(methodBeingCompiled->_priority < CP_SYNC_MIN,
1977
"Unloading cannot happen for SYNC requests");
1978
}
1979
else
1980
{
1981
TR_ASSERT(methodBeingCompiled->_numThreadsWaiting == 0 || methodBeingCompiled->_priority >= CP_SYNC_MIN,
1982
"threads can be waiting only for sync compilations");
1983
if (methodBeingCompiled->_priority >= CP_SYNC_MIN)
1984
{
1985
// fail this compilation
1986
methodBeingCompiled->acquireSlotMonitor(vmThread); // get queue-slot monitor
1987
methodBeingCompiled->_newStartPC = 0;
1988
methodBeingCompiled->getMonitor()->notifyAll(); // notify the waiting thread
1989
methodBeingCompiled->releaseSlotMonitor(vmThread); // release queue-slot monitor
1990
}
1991
}
1992
methodBeingCompiled->_unloadedMethod = true;
1993
}
1994
}
1995
} // end for
1996
// if compiling on app thread, there is no compilation queue
1997
TR_MethodToBeCompiled *cur = _methodQueue;
1998
TR_MethodToBeCompiled *prev = NULL;
1999
bool verboseDetails = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHookDetails);
2000
while (cur)
2001
{
2002
TR_MethodToBeCompiled *next = cur->_next;
2003
TR::IlGeneratorMethodDetails &details = cur->getMethodDetails();
2004
J9Method *method = details.getMethod();
2005
//TR_ASSERT(details.getMethod(), "method can be NULL only at shutdown time");
2006
// ^^^ bad assume: shutdown and class unload CAN happen at the same time.
2007
if (method)
2008
{
2009
J9Class *methodClass = J9_CLASS_FROM_METHOD(method);
2010
if (verboseDetails)
2011
TR_VerboseLog::writeLineLocked(TR_Vlog_HD,"Looking at compile request for method %p class %p", method, methodClass);
2012
if ((!unloadedClass && hotCodeReplacement) || // replacement in FSD mode
2013
methodClass == unloadedClass ||
2014
(details.isNewInstanceThunk() &&
2015
static_cast<J9::NewInstanceThunkDetails &>(details).isThunkFor(unloadedClass)))
2016
{
2017
if (verbose)
2018
TR_VerboseLog::writeLineLocked(TR_Vlog_HK,"Invalidating compile request for method %p class %p", method, methodClass);
2019
if (!hotCodeReplacement)
2020
{
2021
TR_ASSERT(cur->_priority < CP_SYNC_MIN,
2022
"Unloading cannot happen for SYNC requests");
2023
}
2024
else
2025
{
2026
TR_ASSERT(cur->_numThreadsWaiting == 0 || cur->_priority >= CP_SYNC_MIN,
2027
"threads can be waiting only for sync compilations");
2028
// if this method is synchronous we need to signal the waiting thread
2029
if (cur->_priority >= CP_SYNC_MIN)
2030
{
2031
// fail this compilation
2032
cur->acquireSlotMonitor(vmThread); // get queue-slot monitor
2033
cur->_newStartPC = 0;
2034
cur->getMonitor()->notifyAll(); // notify the waiting thread
2035
cur->releaseSlotMonitor(vmThread); // release queue-slot monitor
2036
}
2037
}
2038
// detach from queue
2039
if (prev)
2040
prev->_next = cur->_next;
2041
else
2042
_methodQueue = cur->_next;
2043
updateCompQueueAccountingOnDequeue(cur);
2044
// decrease the queue weight
2045
decreaseQueueWeightBy(cur->_weight);
2046
// put back into the pool
2047
recycleCompilationEntry(cur);
2048
}
2049
else
2050
{
2051
prev = cur;
2052
}
2053
}
2054
else
2055
{
2056
prev = cur;
2057
}
2058
cur = next;
2059
}
2060
2061
// process the low priority queue as well
2062
getLowPriorityCompQueue().invalidateRequestsForUnloadedMethods(unloadedClass);
2063
// and JProfiling queue ...
2064
getJProfilingCompQueue().invalidateRequestsForUnloadedMethods(unloadedClass);
2065
}
2066
2067
// Helper to determine if compilation needs to be aborted due to class unloading
2068
// or hot code replacement
2069
// Side-effects: may change entry->_compErrorCode
2070
bool TR::CompilationInfo::shouldAbortCompilation(TR_MethodToBeCompiled *entry, TR::PersistentInfo *persistentInfo)
2071
{
2072
if (entry->isOutOfProcessCompReq())
2073
return false; // will abort at the client
2074
2075
if (entry->_unloadedMethod) // method was unloaded while we were trying to compile it
2076
{
2077
TR_ASSERT(entry->_compErrCode == compilationInterrupted, "Received error code %u, expect compilationInterrupted when the method was unloaded", entry->_compErrCode);
2078
entry->_compErrCode = compilationNotNeeded; // change error code
2079
return true;
2080
}
2081
if ((TR::Options::getCmdLineOptions()->getOption(TR_EnableHCR) || TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug)))
2082
{
2083
TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();
2084
J9Class *clazz = details.getClass();
2085
if (clazz && J9_IS_CLASS_OBSOLETE(clazz))
2086
{
2087
TR_ASSERT(0, "Should never have compiled replaced method %p", details.getMethod());
2088
entry->_compErrCode = compilationKilledByClassReplacement;
2089
return true;
2090
}
2091
}
2092
return false;
2093
}
2094
2095
// This method has side-effects, It modifies the optimization plan and persistentMethodInfo
2096
// This method is executed with compilationMonitor in hand
2097
//
2098
bool TR::CompilationInfo::shouldRetryCompilation(TR_MethodToBeCompiled *entry, TR::Compilation *comp)
2099
{
2100
// The JITServer should not retry compilations on it's own,
2101
// it should let the client make that decision
2102
if (entry->isOutOfProcessCompReq())
2103
return false;
2104
2105
bool tryCompilingAgain = false;
2106
TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();
2107
J9Method *method = details.getMethod();
2108
2109
// when the compilation fails we might retry
2110
//
2111
if (entry->_compErrCode != compilationOK)
2112
{
2113
if (entry->_compilationAttemptsLeft > 0)
2114
{
2115
2116
TR_PersistentJittedBodyInfo *bodyInfo;
2117
switch (entry->_compErrCode)
2118
{
2119
case compilationAotValidateFieldFailure:
2120
case compilationAotStaticFieldReloFailure:
2121
case compilationAotClassReloFailure:
2122
case compilationAotThunkReloFailure:
2123
case compilationAotHasInvokehandle:
2124
case compilationAotHasInvokeVarHandle:
2125
case compilationAotPatchedCPConstant:
2126
case compilationAotHasInvokeSpecialInterface:
2127
case compilationAotValidateMethodExitFailure:
2128
case compilationAotValidateMethodEnterFailure:
2129
case compilationAotClassChainPersistenceFailure:
2130
case compilationAotValidateStringCompressionFailure:
2131
case compilationSymbolValidationManagerFailure:
2132
case compilationAOTNoSupportForAOTFailure:
2133
case compilationAOTValidateTMFailure:
2134
case compilationAOTRelocationRecordGenerationFailure:
2135
case compilationAotValidateExceptionHookFailure:
2136
case compilationAotBlockFrequencyReloFailure:
2137
case compilationAotRecompQueuedFlagReloFailure:
2138
case compilationAOTValidateOSRFailure:
2139
// switch to JIT for these cases (we don't want to relocate again)
2140
entry->_doNotUseAotCodeFromSharedCache = true;
2141
tryCompilingAgain = true;
2142
break;
2143
//case compilationAotRelocationFailure:
2144
case compilationAotTrampolineReloFailure:
2145
case compilationAotPicTrampolineReloFailure:
2146
case compilationAotCacheFullReloFailure:
2147
// for the last one, switch to JIT
2148
if (entry->_compilationAttemptsLeft == 1)
2149
entry->_doNotUseAotCodeFromSharedCache = true;
2150
tryCompilingAgain = true;
2151
break;
2152
#if defined(J9VM_OPT_JITSERVER)
2153
case compilationStreamFailure:
2154
// if -XX:+JITServerRequireServer is used, we would like the client to fail when server crashes
2155
if (entry->_compInfoPT->getCompilationInfo()->getPersistentInfo()->getRequireJITServer())
2156
{
2157
TR_ASSERT_FATAL(false, "Option -XX:+JITServerRequireServer is used, terminate the JITClient due to unavailable JITServer.");
2158
}
2159
case compilationStreamMessageTypeMismatch:
2160
case compilationStreamVersionIncompatible:
2161
case compilationStreamLostMessage:
2162
case aotCacheDeserializationFailure:
2163
#endif
2164
case compilationInterrupted:
2165
case compilationCodeReservationFailure:
2166
case compilationRecoverableTrampolineFailure:
2167
case compilationIllegalCodeCacheSwitch:
2168
case compilationRecoverableCodeCacheError:
2169
tryCompilingAgain = true;
2170
break;
2171
case compilationExcessiveComplexity:
2172
case compilationHeapLimitExceeded:
2173
case compilationLowPhysicalMemory:
2174
case compilationInternalPointerExceedLimit:
2175
case compilationVirtualAddressExhaustion:
2176
if (comp->getOption(TR_Timing))
2177
{
2178
comp->phaseTimer().DumpSummary(*comp);
2179
}
2180
2181
if (comp->getOption(TR_LexicalMemProfiler))
2182
{
2183
comp->phaseMemProfiler().DumpSummary(*comp);
2184
}
2185
2186
if (!((TR_J9VMBase *)comp->fej9())->isAOT_DEPRECATED_DO_NOT_USE())
2187
{
2188
TR_J9SharedCache *sc = (TR_J9SharedCache *) (((TR_J9VMBase *)comp->fej9())->sharedCache());
2189
if (sc)
2190
{
2191
switch (entry->_optimizationPlan->getOptLevel())
2192
{
2193
case cold:
2194
case warm:
2195
sc->addHint(method, TR_HintFailedWarm);
2196
break;
2197
case hot:
2198
sc->addHint(method, TR_HintFailedHot);
2199
break;
2200
case scorching:
2201
case veryHot:
2202
sc->addHint(method, TR_HintFailedScorching);
2203
break;
2204
default:
2205
break;
2206
}
2207
}
2208
}
2209
2210
bodyInfo = 0;
2211
if (comp->allowRecompilation() && entry->_optimizationPlan && entry->_optimizationPlan->getOptLevel() > minHotness)
2212
{
2213
// Compile only if the method is interpreted or if it's compiled with
2214
// profiling information.
2215
if (entry->_oldStartPC == 0) // interpreter method
2216
{
2217
tryCompilingAgain = true;
2218
}
2219
else // Does the existing body contain profiling info?
2220
{
2221
bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(entry->_oldStartPC);
2222
if (bodyInfo->getIsProfilingBody())
2223
tryCompilingAgain = true;
2224
// if existing body is invalidated, retry the compilation
2225
else if (bodyInfo->getIsInvalidated())
2226
tryCompilingAgain = true;
2227
// if the existing body uses pre-existence, retry the compilation
2228
// otherwise we will revert to interpreted when failing this compilation
2229
else if (bodyInfo->getUsesPreexistence())
2230
tryCompilingAgain = true;
2231
}
2232
}
2233
2234
if (tryCompilingAgain)
2235
{
2236
TR_Hotness hotness = entry->_optimizationPlan->getOptLevel();
2237
TR_Hotness newHotness;
2238
if (hotness == veryHot)
2239
newHotness = warm; // skip over hot and go down two levels
2240
else if (hotness <= scorching)
2241
newHotness = (TR_Hotness)(hotness - 1);
2242
else // Why would we use hotness greater than scorching
2243
newHotness = noOpt;
2244
entry->_optimizationPlan->setOptLevel(newHotness);
2245
entry->_optimizationPlan->setInsertInstrumentation(false); // prevent profiling
2246
entry->_optimizationPlan->setUseSampling(false); // disable recompilation of this method
2247
entry->_optimizationPlan->setDisableEDO(true); // disable EDO to prevent recompilation triggered from native code
2248
entry->_optimizationPlan->setDisableGCR(true); // disable GCR to prevent recompilation triggered from native code
2249
}
2250
break;
2251
case compilationCHTableCommitFailure:
2252
tryCompilingAgain = true;
2253
// if we have only one more trial left, disable optimizations based on CHTable
2254
if (entry->_compilationAttemptsLeft == 1)
2255
entry->_optimizationPlan->setDisableCHOpts();
2256
break;
2257
case compilationNeededAtHigherLevel:
2258
if (comp->allowRecompilation() && (comp->getNextOptLevel()!=unknownHotness))
2259
{
2260
tryCompilingAgain = true;
2261
TR_Hotness newHotness = comp->getNextOptLevel();
2262
entry->_optimizationPlan->setOptLevel(newHotness);
2263
}
2264
break;
2265
2266
case compilationMaxCallerIndexExceeded:
2267
{
2268
tryCompilingAgain = true;
2269
// bump the factor that will indicate by how much to reduce the MAX_PEEKED_BYTECODE_SIZE
2270
uint32_t val = entry->_optimizationPlan->getReduceMaxPeekedBytecode();
2271
entry->_optimizationPlan->setReduceMaxPeekedBytecode(val+1);
2272
// if we have only one more trial left, make sure you don't try above warm opt level
2273
// Lookahead at warm is disabled by default
2274
if (entry->_compilationAttemptsLeft == 1)
2275
{
2276
TR_Hotness hotness = entry->_optimizationPlan->getOptLevel();
2277
TR_Hotness newHotness = hotness > warm ? warm : hotness;
2278
entry->_optimizationPlan->setOptLevel(newHotness);
2279
entry->_optimizationPlan->setInsertInstrumentation(false); // prevent profiling
2280
entry->_optimizationPlan->setUseSampling(false); // disable recompilation of this method
2281
// In the future we may have to disable OptServer as well
2282
}
2283
break;
2284
}
2285
case compilationGCRPatchFailure:
2286
// Disable GCR trees for this body
2287
entry->_optimizationPlan->setDisableGCR();
2288
tryCompilingAgain = true;
2289
break;
2290
case compilationLambdaEnforceScorching:
2291
// This must be a warm compilation. Retry the same compilation at scorching even if it's a first time compilation
2292
// Watch out for the following scenario: (1) warm comp req. (2) Ilgen fails comp because it wants a hot comp
2293
// (3) hot comp fails due to some compiler limit and we lower opt level at warm; (4) Ilgen fails again because
2294
// it wants a hot compilation
2295
// Also we should not fail the compilation for fixed opt level.
2296
if (entry->_compilationAttemptsLeft == MAX_COMPILE_ATTEMPTS) // Raise opt level only for the first attempt
2297
{
2298
TR_Hotness hotness = entry->_optimizationPlan->getOptLevel();
2299
if (hotness <= veryHot )
2300
{
2301
entry->_optimizationPlan->setOptLevel(scorching); // force scorching recompilation
2302
entry->_optimizationPlan->setDontFailOnPurpose(true);
2303
entry->_optimizationPlan->setDoNotSwitchToProfiling(true);
2304
entry->_optimizationPlan->setDisableGCR();
2305
tryCompilingAgain = true;
2306
// If we were doing an AOT warm compilation, we will refrain from doing an AOT-hot
2307
// because we do not allow AOT compilations as retrials
2308
// (see entry->_useAotCompilation = false; at the end of this method)
2309
// This is what we probably want
2310
}
2311
}
2312
break;
2313
case compilationEnforceProfiling:
2314
entry->_optimizationPlan->setInsertInstrumentation(true); // enable profiling
2315
entry->_optimizationPlan->setDoNotSwitchToProfiling(true); // don't allow another switch
2316
entry->_optimizationPlan->setDisableGCR(); // GCR isn't needed
2317
tryCompilingAgain = true;
2318
break;
2319
case compilationNullSubstituteCodeCache:
2320
case compilationCodeMemoryExhausted:
2321
case compilationCodeCacheError:
2322
case compilationDataCacheError:
2323
default:
2324
break;
2325
} // end switch
2326
if (tryCompilingAgain && comp)
2327
{
2328
TR_PersistentMethodInfo *methodInfo = TR_PersistentMethodInfo::get(comp);
2329
if (methodInfo)
2330
methodInfo->setNextCompileLevel(entry->_optimizationPlan->getOptLevel(), entry->_optimizationPlan->insertInstrumentation());
2331
}
2332
}
2333
else if (0) // later add test for multiple aot relocation failure to catch that scenario, which shouldn't happen
2334
{
2335
TR_ASSERT(0, "multiple aot relocations likely failed for same method");
2336
}
2337
}// if (entry->_compErrCode != compilationOK)
2338
2339
// don't carry the decision to generate AOT code to the next compilation
2340
// because it may no longer be the right thing to do at that point
2341
if (tryCompilingAgain)
2342
entry->_useAotCompilation = false;
2343
2344
return tryCompilingAgain;
2345
}
2346
2347
// if compiling on app thread, there is no compilation queue
2348
void TR::CompilationInfo::purgeMethodQueue(TR_CompilationErrorCode errorCode)
2349
{
2350
// Must enter _compilationMonitor before calling this
2351
J9JavaVM *vm = _jitConfig->javaVM;
2352
J9VMThread *vmThread = vm->internalVMFunctions->currentVMThread(vm);
2353
// Generate a trace point
2354
Trc_JIT_purgeMethodQueue(vmThread);
2355
2356
while (_methodQueue)
2357
{
2358
TR_MethodToBeCompiled * cur = _methodQueue;
2359
_methodQueue = cur->_next;
2360
updateCompQueueAccountingOnDequeue(cur);
2361
// decrease the queue weight
2362
decreaseQueueWeightBy(cur->_weight);
2363
2364
// must wake up the working threads that are waiting for the
2365
// compilation to finish (only for sync comp req)
2366
// we also need to fail all those compilations
2367
2368
// Acquire the queue slot monitor now
2369
//
2370
debugPrint(vmThread, "\tre-acquiring queue-slot monitor\n");
2371
cur->acquireSlotMonitor(vmThread);
2372
debugPrint(vmThread, "+AM-", cur);
2373
2374
// fail the compilation
2375
void *startPC = 0;
2376
2377
startPC = compilationEnd(vmThread, cur->getMethodDetails(), _jitConfig, NULL, cur->_oldStartPC);
2378
cur->_newStartPC = startPC;
2379
cur->_compErrCode = errorCode;
2380
2381
// notify the sleeping threads
2382
//
2383
debugPrint(vmThread, "\tnotify sleeping threads that the compilation is done\n");
2384
cur->getMonitor()->notifyAll();
2385
debugPrint(vmThread, "ntfy-", cur);
2386
2387
// Release the queue slot monitor
2388
//
2389
debugPrint(vmThread, "\tcompilation thread releasing queue slot monitor\n");
2390
debugPrint(vmThread, "-AM-", cur);
2391
cur->releaseSlotMonitor(vmThread);
2392
2393
recycleCompilationEntry(cur);
2394
}
2395
2396
// delete all entries from the low priority queue
2397
getLowPriorityCompQueue().purgeLPQ();
2398
// and from JProfiling queue
2399
getJProfilingCompQueue().purge();
2400
}
2401
2402
void TR::CompilationInfoPerThread::suspendCompilationThread()
2403
{
2404
_compInfo.acquireCompMonitor(_compilationThread);
2405
2406
if (compilationThreadIsActive())
2407
{
2408
setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);
2409
2410
if (!isDiagnosticThread())
2411
getCompilationInfo()->decNumCompThreadsActive();
2412
2413
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
2414
{
2415
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u Suspension request for compThread %d sleeping=%s",
2416
(uint32_t)getCompilationInfo()->getPersistentInfo()->getElapsedTime(), getCompThreadId(), getMethodBeingCompiled()?"NO":"YES");
2417
}
2418
2419
// What happens if the thread is sleeping on the compilationQueueMonitor?
2420
if (getCompilationInfo()->getNumCompThreadsActive() == 0)
2421
getCompilationInfo()->purgeMethodQueue(compilationSuspended);
2422
}
2423
_compInfo.releaseCompMonitor(_compilationThread);
2424
// The thread will be sleeping on the compThreadMonitor whenever it finishes current compilation
2425
}
2426
2427
//-------------------------- suspendCompilationThread ------------------------
2428
// This method may be called when we want all JIT activity to stop temporarily
2429
// It is called normally by a java thread
2430
//----------------------------------------------------------------------------
2431
void TR::CompilationInfo::suspendCompilationThread()
2432
{
2433
// if we compile on application thread, there is no compilation
2434
// request queue and there is no compilation thread
2435
// There can only be one request that is in progress. All the others
2436
// will see the SUSPENDED state when they get the application monitor
2437
2438
TR_ASSERT(_compilationMonitor, "Must have a compilation queue monitor\n");
2439
J9JavaVM *vm = _jitConfig->javaVM;
2440
J9VMThread *vmThread = vm->internalVMFunctions->currentVMThread(vm);
2441
if (!vmThread)
2442
return; // cannot do it without a vmThread FIXME: why?
2443
acquireCompMonitor(vmThread);
2444
2445
// Must visit all compilation threads
2446
bool stoppedOneCompilationThread = false;
2447
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
2448
{
2449
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
2450
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
2451
2452
// Only compilation threads that are active need to be suspended
2453
if (curCompThreadInfoPT->compilationThreadIsActive())
2454
{
2455
curCompThreadInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);
2456
decNumCompThreadsActive();
2457
// should we try to interrupt the compilation in progress?
2458
stoppedOneCompilationThread = true;
2459
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
2460
{
2461
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u Suspension request for compThread %d sleeping=%s",
2462
(uint32_t)getPersistentInfo()->getElapsedTime(), curCompThreadInfoPT->getCompThreadId(), curCompThreadInfoPT->getMethodBeingCompiled()?"NO":"YES");
2463
}
2464
}
2465
}
2466
if (stoppedOneCompilationThread)
2467
purgeMethodQueue(compilationSuspended);
2468
TR_ASSERT(_numCompThreadsActive == 0, "We must have all compilation threads suspended at this point\n");
2469
releaseCompMonitor(vmThread);
2470
}
2471
2472
void TR::CompilationInfoPerThread::resumeCompilationThread()
2473
{
2474
_compInfo.acquireCompMonitor(_compilationThread);
2475
2476
if (getCompilationThreadState() == COMPTHREAD_SUSPENDED ||
2477
getCompilationThreadState() == COMPTHREAD_SIGNAL_SUSPEND)
2478
{
2479
if (getCompilationThreadState() == COMPTHREAD_SUSPENDED)
2480
{
2481
setCompilationThreadState(COMPTHREAD_ACTIVE);
2482
getCompThreadMonitor()->enter();
2483
getCompThreadMonitor()->notifyAll(); // wake the suspended thread
2484
getCompThreadMonitor()->exit();
2485
}
2486
else // COMPTHREAD_SIGNAL_SUSPEND
2487
{
2488
setCompilationThreadState(COMPTHREAD_ACTIVE);
2489
}
2490
2491
// The diagnostic thread should not be counted as active
2492
if (!isDiagnosticThread())
2493
getCompilationInfo()->incNumCompThreadsActive();
2494
2495
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
2496
{
2497
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Resume request for compThread %d",
2498
(uint32_t)getCompilationInfo()->getPersistentInfo()->getElapsedTime(), getCompThreadId());
2499
}
2500
}
2501
2502
_compInfo.releaseCompMonitor(_compilationThread);
2503
}
2504
2505
//----------------------------- resumeCompilationThread -----------------------
2506
// This version of resumeCompilationThread wakes up several compilation threads
2507
//-----------------------------------------------------------------------------
2508
void TR::CompilationInfo::resumeCompilationThread()
2509
{
2510
J9JavaVM *vm = _jitConfig->javaVM;
2511
J9VMThread *vmThread = vm->internalVMFunctions->currentVMThread(vm);
2512
acquireCompMonitor(vmThread);
2513
2514
/*
2515
* Count active/suspended threads for sake of sanity.
2516
* We can afford to do it because this method is not invoked very often
2517
*
2518
* FIXME:
2519
* we are now using an array, so there is no linked list to count;
2520
* therefore, we might be able to remove this entirely
2521
*/
2522
int32_t numActiveCompThreads = 0; // RAS purposes
2523
int32_t numHot = 0;
2524
TR::CompilationInfoPerThread *compInfoPTHot = NULL;
2525
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
2526
{
2527
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
2528
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
2529
2530
CompilationThreadState currentThreadState = curCompThreadInfoPT->getCompilationThreadState();
2531
if (currentThreadState == COMPTHREAD_ACTIVE ||
2532
currentThreadState == COMPTHREAD_SIGNAL_WAIT ||
2533
currentThreadState == COMPTHREAD_WAITING ||
2534
currentThreadState == COMPTHREAD_SIGNAL_SUSPEND)
2535
{
2536
if (curCompThreadInfoPT->compilationThreadIsActive())
2537
numActiveCompThreads++;
2538
if (curCompThreadInfoPT->getMethodBeingCompiled() &&
2539
curCompThreadInfoPT->getMethodBeingCompiled()->_hasIncrementedNumCompThreadsCompilingHotterMethods)
2540
{
2541
numHot++;
2542
if (currentThreadState == COMPTHREAD_SIGNAL_SUSPEND)
2543
compInfoPTHot = curCompThreadInfoPT; // memorize this for later
2544
}
2545
}
2546
}
2547
2548
// Check that our view about the number of active compilation threads is correct
2549
//
2550
if (numActiveCompThreads != getNumCompThreadsActive())
2551
{
2552
TR_ASSERT(false, "Discrepancy regarding active compilation threads: numActiveCompThreads=%d getNumCompThreadsActive()=%d\n", numActiveCompThreads, getNumCompThreadsActive());
2553
setNumCompThreadsActive(numActiveCompThreads); // Apply correction
2554
}
2555
if (getNumCompThreadsCompilingHotterMethods() != numHot)
2556
{
2557
TR_ASSERT(false, "Inconsistency with hot threads %d %d\n", getNumCompThreadsCompilingHotterMethods(), numHot);
2558
setNumCompThreadsCompilingHotterMethods(numHot); // apply correction
2559
}
2560
2561
// If there is a compilation thread executing a hot compilation and the state is
2562
// SUSPENDING, activate this thread first (see defect 182392)
2563
if (compInfoPTHot)
2564
{
2565
compInfoPTHot->setCompilationThreadState(COMPTHREAD_ACTIVE);
2566
incNumCompThreadsActive();
2567
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
2568
{
2569
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Resume compThread %d Qweight=%d active=%d",
2570
(uint32_t)getPersistentInfo()->getElapsedTime(),
2571
compInfoPTHot->getCompThreadId(),
2572
getQueueWeight(),
2573
getNumCompThreadsActive());
2574
}
2575
}
2576
2577
// If dynamicThreadActivation is used, wake compilation threads only as
2578
// many as required; otherwise wake them all
2579
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
2580
{
2581
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
2582
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
2583
2584
TR_YesNoMaybe activate = shouldActivateNewCompThread();
2585
if (activate == TR_no)
2586
break;
2587
2588
curCompThreadInfoPT->resumeCompilationThread();
2589
}
2590
2591
if (getNumCompThreadsActive() == 0)
2592
{
2593
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "No threads were activated following a resume all compilation threads call");
2594
}
2595
2596
releaseCompMonitor(vmThread);
2597
}
2598
2599
2600
int TR::CompilationInfo::computeCompilationThreadPriority(J9JavaVM *vm)
2601
{
2602
int priority = J9THREAD_PRIORITY_USER_MAX; // default value
2603
2604
// convert priority codes into priorities defined by the VM
2605
static UDATA priorityConversionTable[]={J9THREAD_PRIORITY_MIN,
2606
J9THREAD_PRIORITY_USER_MIN,
2607
J9THREAD_PRIORITY_NORMAL,
2608
J9THREAD_PRIORITY_USER_MAX,
2609
J9THREAD_PRIORITY_MAX};
2610
if (TR::Options::_compilationThreadPriorityCode >= 0 &&
2611
TR::Options::_compilationThreadPriorityCode <= 4)
2612
priority = priorityConversionTable[TR::Options::_compilationThreadPriorityCode];
2613
return priority;
2614
}
2615
2616
TR::CompilationInfoPerThread* TR::CompilationInfo::getCompInfoForThread(J9VMThread *vmThread)
2617
{
2618
for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)
2619
{
2620
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
2621
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
2622
2623
if (vmThread == curCompThreadInfoPT->getCompilationThread())
2624
return curCompThreadInfoPT;
2625
}
2626
2627
return NULL;
2628
}
2629
2630
int32_t *TR::CompilationInfo::_compThreadActivationThresholds = NULL;
2631
int32_t *TR::CompilationInfo::_compThreadSuspensionThresholds = NULL;
2632
int32_t *TR::CompilationInfo::_compThreadActivationThresholdsonStarvation = NULL;
2633
2634
void TR::CompilationInfo::updateNumUsableCompThreads(int32_t &numUsableCompThreads)
2635
{
2636
#if defined(J9VM_OPT_JITSERVER)
2637
if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
2638
{
2639
if (numUsableCompThreads <= 0)
2640
{
2641
numUsableCompThreads = DEFAULT_SERVER_USABLE_COMP_THREADS;
2642
}
2643
else if (numUsableCompThreads > MAX_SERVER_USABLE_COMP_THREADS)
2644
{
2645
fprintf(stderr,
2646
"Requested number of compilation threads is over the limit of %u.\n"
2647
"Will use the default number of threads: %u.\n",
2648
MAX_SERVER_USABLE_COMP_THREADS, DEFAULT_SERVER_USABLE_COMP_THREADS
2649
);
2650
numUsableCompThreads = DEFAULT_SERVER_USABLE_COMP_THREADS;
2651
}
2652
}
2653
else
2654
#endif /* defined(J9VM_OPT_JITSERVER) */
2655
{
2656
if (numUsableCompThreads <= 0)
2657
{
2658
numUsableCompThreads = DEFAULT_CLIENT_USABLE_COMP_THREADS;
2659
}
2660
else if (numUsableCompThreads > MAX_CLIENT_USABLE_COMP_THREADS)
2661
{
2662
fprintf(stderr,
2663
"Requested number of compilation threads is over the limit of %u. Will use %u threads.\n",
2664
MAX_CLIENT_USABLE_COMP_THREADS, MAX_CLIENT_USABLE_COMP_THREADS
2665
);
2666
numUsableCompThreads = MAX_CLIENT_USABLE_COMP_THREADS;
2667
}
2668
}
2669
}
2670
2671
bool
2672
TR::CompilationInfo::allocateCompilationThreads(int32_t numUsableCompThreads)
2673
{
2674
if (_compThreadActivationThresholds ||
2675
_compThreadSuspensionThresholds ||
2676
_compThreadActivationThresholdsonStarvation ||
2677
_arrayOfCompilationInfoPerThread)
2678
{
2679
TR_ASSERT_FATAL(false, "Compilation threads have been allocated\n");
2680
return false;
2681
}
2682
2683
TR_ASSERT((numUsableCompThreads == TR::Options::_numUsableCompilationThreads),
2684
"numUsableCompThreads %d is not equal to the Option value %d", numUsableCompThreads, TR::Options::_numUsableCompilationThreads);
2685
2686
#if defined(J9VM_OPT_JITSERVER)
2687
if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
2688
{
2689
TR_ASSERT((0 < numUsableCompThreads) && (numUsableCompThreads <= MAX_SERVER_USABLE_COMP_THREADS),
2690
"numUsableCompThreads %d is greater than supported %d", numUsableCompThreads, MAX_SERVER_USABLE_COMP_THREADS);
2691
}
2692
else
2693
#endif /* defined(J9VM_OPT_JITSERVER) */
2694
{
2695
TR_ASSERT((0 < numUsableCompThreads) && (numUsableCompThreads <= MAX_CLIENT_USABLE_COMP_THREADS),
2696
"numUsableCompThreads %d is greater than supported %d", numUsableCompThreads, MAX_CLIENT_USABLE_COMP_THREADS);
2697
}
2698
2699
uint32_t numTotalCompThreads = numUsableCompThreads + MAX_DIAGNOSTIC_COMP_THREADS;
2700
2701
TR::MonitorTable *table = TR::MonitorTable::get();
2702
if ((!table) ||
2703
(!table->allocInitClassUnloadMonitorHolders(numTotalCompThreads)))
2704
{
2705
return false;
2706
}
2707
2708
_compThreadActivationThresholds = static_cast<int32_t *>(jitPersistentAlloc((numTotalCompThreads + 1) * sizeof(int32_t)));
2709
_compThreadSuspensionThresholds = static_cast<int32_t *>(jitPersistentAlloc((numTotalCompThreads + 1) * sizeof(int32_t)));
2710
_compThreadActivationThresholdsonStarvation = static_cast<int32_t *>(jitPersistentAlloc((numTotalCompThreads + 1) * sizeof(int32_t)));
2711
2712
_arrayOfCompilationInfoPerThread = static_cast<TR::CompilationInfoPerThread **>(jitPersistentAlloc(numTotalCompThreads * sizeof(TR::CompilationInfoPerThread *)));
2713
2714
if (_compThreadActivationThresholds &&
2715
_compThreadSuspensionThresholds &&
2716
_compThreadActivationThresholdsonStarvation &&
2717
_arrayOfCompilationInfoPerThread)
2718
{
2719
// How to read it: the queueWeight has to be over 100 to activate second comp thread
2720
// the queueWeight has to be below 10 to suspend second comp thread
2721
// For example:
2722
// compThreadActivationThresholds[MAX_TOTAL_COMP_THREADS+1] = {-1, 100, 200, 300, 400, 500, 600, 700, 800};
2723
// compThreadSuspensionThresholds[MAX_TOTAL_COMP_THREADS+1] = {-1, -1, 10, 110, 210, 310, 410, 510, 610};
2724
// compThreadActivationThresholdsonStarvation[MAX_TOTAL_COMP_THREADS+1] = {-1, 800, 1600, 3200, 6400, 12800, 19200, 25600, 32000};
2725
_compThreadActivationThresholds[0] = -1;
2726
_compThreadActivationThresholds[1] = 100;
2727
_compThreadActivationThresholds[2] = 200;
2728
2729
_compThreadSuspensionThresholds[0] = -1;
2730
_compThreadSuspensionThresholds[1] = -1;
2731
_compThreadSuspensionThresholds[2] = 10;
2732
2733
for (int32_t i=3; i<(numTotalCompThreads+1); ++i)
2734
{
2735
_compThreadActivationThresholds[i] = _compThreadActivationThresholds[i-1] + 100;
2736
_compThreadSuspensionThresholds[i] = _compThreadSuspensionThresholds[i-1] + 100;
2737
}
2738
2739
_compThreadActivationThresholdsonStarvation[0] = -1;
2740
_compThreadActivationThresholdsonStarvation[1] = 800;
2741
2742
for (int32_t i=2; i<(numTotalCompThreads+1); ++i)
2743
{
2744
if (_compThreadActivationThresholdsonStarvation[i-1] < 12800)
2745
{
2746
_compThreadActivationThresholdsonStarvation[i] = _compThreadActivationThresholdsonStarvation[i-1] * 2;
2747
}
2748
else
2749
{
2750
_compThreadActivationThresholdsonStarvation[i] = _compThreadActivationThresholdsonStarvation[i-1] + 6400;
2751
}
2752
}
2753
2754
for (int32_t i=0; i<numTotalCompThreads; ++i)
2755
{
2756
_arrayOfCompilationInfoPerThread[i] = NULL;
2757
}
2758
return true;
2759
}
2760
return false;
2761
}
2762
2763
//-------------------------- startCompilationThread --------------------------
2764
// Start ONE compilation thread and initialize the associated
2765
// TR::CompilationInfoPerThread structure
2766
// This function returns immediately after the thread is created
2767
// Parameters:
2768
// priority - the desired priority of the thread (0..5); negative number
2769
// means that the priority will be computed automatically
2770
// Return value: 0 for success; error code for any error
2771
//----------------------------------------------------------------------------
2772
uintptr_t
2773
TR::CompilationInfo::startCompilationThread(int32_t priority, int32_t threadId, bool isDiagnosticThread)
2774
{
2775
if (!_compilationMonitor)
2776
return 1;
2777
2778
if (!isDiagnosticThread)
2779
{
2780
if (_numCompThreads >= TR::Options::_numUsableCompilationThreads)
2781
return 1;
2782
}
2783
else
2784
{
2785
if (_numDiagnosticThreads >= MAX_DIAGNOSTIC_COMP_THREADS)
2786
return 1;
2787
2788
// _compInfoForDiagnosticCompilationThread should be NULL before creation
2789
if (_compInfoForDiagnosticCompilationThread)
2790
return 1;
2791
}
2792
2793
J9JavaVM * vm = jitConfig->javaVM;
2794
PORT_ACCESS_FROM_JAVAVM(vm);
2795
2796
setCompBudget(TR::Options::_compilationBudget); // might do it several time, but it does not hurt
2797
2798
// Create a compInfo for this thread
2799
#if defined(J9VM_OPT_JITSERVER)
2800
TR::CompilationInfoPerThread *compInfoPT = getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER ?
2801
new (persistentMemory()) TR::CompilationInfoPerThreadRemote(*this, _jitConfig, threadId, isDiagnosticThread) :
2802
new (persistentMemory()) TR::CompilationInfoPerThread(*this, _jitConfig, threadId, isDiagnosticThread);
2803
#else
2804
TR::CompilationInfoPerThread *compInfoPT = new (persistentMemory()) TR::CompilationInfoPerThread(*this, _jitConfig, threadId, isDiagnosticThread);
2805
#endif /* defined(J9VM_OPT_JITSERVER) */
2806
2807
if (!compInfoPT || !compInfoPT->initializationSucceeded() || !compInfoPT->getCompThreadMonitor())
2808
return 1; // TODO must deallocate some things in compInfoPT as well as the memory for it
2809
2810
int32_t jitPriority;
2811
if (priority < 0)
2812
{
2813
jitPriority = computeCompilationThreadPriority(vm);
2814
if (TR::Options::getCmdLineOptions()->realTimeGC())
2815
{
2816
static char *incMaxPriority = feGetEnv("IBM_J9_THREAD_INCREMENT_MAX_PRIORITY");
2817
static char *decJitPriority = feGetEnv("TR_DECREMENT_JIT_COMPILATION_PRIORITY");
2818
if (incMaxPriority && decJitPriority)
2819
jitPriority--;
2820
}
2821
}
2822
2823
compInfoPT->setCompThreadPriority(priority < 0 ? jitPriority : priority);
2824
2825
// add this entry to the array in the compilationInfo object
2826
// NOTE: This method must be issued by a single thread because we don't hold a monitor.
2827
_arrayOfCompilationInfoPerThread[compInfoPT->getCompThreadId()] = compInfoPT;
2828
2829
// NOTE:
2830
// variable (_numDiagnosticThreads) updates are wrapped in monitor to prevent instruction re-ordering
2831
// since the order of updates matters and MUST be done AFTER _arrayOfCompilationInfoPerThread
2832
// is updated; for example on PPC, these two statements may be done in the wrong order;
2833
// the calls to the monitor insert synchronization instructions and prevent this
2834
if (isDiagnosticThread)
2835
{
2836
getCompilationMonitor()->enter();
2837
_compInfoForDiagnosticCompilationThread = compInfoPT;
2838
_numDiagnosticThreads++;
2839
getCompilationMonitor()->exit();
2840
}
2841
else
2842
{
2843
getCompilationMonitor()->enter();
2844
_numCompThreads++;
2845
getCompilationMonitor()->exit();
2846
}
2847
2848
//_methodQueue = NULL; This is initialized when compInfo is created
2849
debugPrint("\t\tstarting compilation thread\n");
2850
2851
if (vm->internalVMFunctions->createThreadWithCategory(&compInfoPT->_osThread,
2852
TR::Options::_stackSize << 10, // stack size in kb
2853
compInfoPT->getCompThreadPriority(),
2854
0, // allow thread to start immediately
2855
(j9thread_entrypoint_t)compilationThreadProc,
2856
compInfoPT,
2857
J9THREAD_CATEGORY_SYSTEM_JIT_THREAD))
2858
{
2859
//_compilationMonitor->destroy();
2860
//_compilationMonitor = NULL;
2861
// TODO must do some cleanup
2862
return 2;
2863
}
2864
2865
// Would like to wait here until the compThread attaches to the VM
2866
compInfoPT->getCompThreadMonitor()->enter();
2867
while ( !compInfoPT->getCompilationThread() && compInfoPT->getCompilationThreadState() != COMPTHREAD_ABORT )
2868
compInfoPT->getCompThreadMonitor()->wait(); // for the compThread to be initialized
2869
compInfoPT->getCompThreadMonitor()->exit();
2870
2871
if (compInfoPT->getCompilationThreadState() == COMPTHREAD_ABORT)
2872
return 3;
2873
2874
return 0;
2875
}
2876
2877
#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
2878
void *TR::CompilationInfo::searchForDLTRecord(J9Method *method, int32_t bcIndex)
2879
{
2880
int32_t hashVal = (intptr_t)method * bcIndex % DLT_HASHSIZE;
2881
if (hashVal < 0)
2882
hashVal = -hashVal;
2883
2884
//_dltMonitor->enter();
2885
struct DLT_record *dltPtr;
2886
2887
// When bcIndex is negative(invalid) I have to scan the entire hashtable
2888
// for a matching j9method
2889
if (bcIndex < 0)
2890
{
2891
for (int32_t i=0; i<DLT_HASHSIZE; i++)
2892
{
2893
dltPtr = _dltHash[i];
2894
while (dltPtr != NULL)
2895
{
2896
if (dltPtr->_method==method)
2897
{
2898
//_dltMonitor->exit();
2899
return dltPtr->_dltEntry;
2900
}
2901
dltPtr = dltPtr->_next;
2902
}
2903
}
2904
}
2905
else
2906
{
2907
dltPtr = _dltHash[hashVal];
2908
while (dltPtr != NULL)
2909
{
2910
if (dltPtr->_method==method && dltPtr->_bcIndex==bcIndex)
2911
{
2912
// Safe: since we are not giving up on vmAccess yet
2913
//_dltMonitor->exit();
2914
return dltPtr->_dltEntry;
2915
}
2916
dltPtr = dltPtr->_next;
2917
}
2918
}
2919
//_dltMonitor->exit();
2920
return NULL;
2921
}
2922
2923
void TR::CompilationInfo::insertDLTRecord(J9Method *method, int32_t bcIndex, void *dltEntry)
2924
{
2925
int32_t hashVal = (intptr_t)method * bcIndex % DLT_HASHSIZE;
2926
if (hashVal < 0)
2927
hashVal = -hashVal;
2928
2929
{
2930
OMR::CriticalSection updatingDLTRecords(_dltMonitor);
2931
struct DLT_record *dltPtr = _dltHash[hashVal];
2932
2933
while (dltPtr != NULL)
2934
{
2935
if (dltPtr->_method == method && dltPtr->_bcIndex == bcIndex)
2936
{
2937
return;
2938
}
2939
dltPtr = dltPtr->_next;
2940
}
2941
2942
struct DLT_record *myRecord;
2943
2944
if (_freeDLTRecord != NULL)
2945
{
2946
myRecord = _freeDLTRecord;
2947
_freeDLTRecord = myRecord->_next;
2948
}
2949
else
2950
myRecord = (struct DLT_record *)jitPersistentAlloc(sizeof(struct DLT_record));
2951
2952
if (!myRecord)
2953
{
2954
return;
2955
}
2956
2957
myRecord->_method = method;
2958
myRecord->_bcIndex = bcIndex;
2959
myRecord->_dltEntry = dltEntry;
2960
myRecord->_next = _dltHash[hashVal];
2961
// Memory Flush (for PPC) so myRecord is visible to other CPUs before we update the _dltHash
2962
// Doing this means we don't need locking when reading the _dltHash linked lists
2963
FLUSH_MEMORY(TR::Compiler->target.isSMP());
2964
_dltHash[hashVal] = myRecord;
2965
}
2966
}
2967
2968
void TR::CompilationInfo::cleanDLTRecordOnUnload()
2969
{
2970
for (int32_t i=0; i<DLT_HASHSIZE; i++)
2971
{
2972
struct DLT_record *prev=NULL, *curr=_dltHash[i], *next;
2973
while (curr != NULL)
2974
{
2975
J9Class *clazz = J9_CLASS_FROM_METHOD(curr->_method);
2976
next = curr->_next;
2977
2978
// Non-Anon classes will be unloaded with their classloaders, hence the class's classloader will be marked as dead.
2979
// Anon Classes can be independently unloaded without their classloaders, however their classes are marked as dying.
2980
if ( J9_ARE_ALL_BITS_SET(clazz->classLoader->gcFlags, J9_GC_CLASS_LOADER_DEAD)
2981
|| (J9CLASS_FLAGS(clazz) & J9AccClassDying) )
2982
{
2983
if (prev == NULL)
2984
_dltHash[i] = next;
2985
else
2986
prev->_next = next;
2987
2988
// FIXME: free the codeCache
2989
curr->_next = _freeDLTRecord;
2990
_freeDLTRecord = curr;
2991
}
2992
else
2993
prev = curr;
2994
curr = next;
2995
}
2996
}
2997
}
2998
#endif
2999
3000
#ifdef INVOCATION_STATS
3001
extern "C" J9Method * getNewInstancePrototype(J9VMThread * context);
3002
#include "infra/Statistics.hpp"
3003
void printAllCounts(J9JavaVM *javaVM)
3004
{
3005
J9VMThread *vmThread = javaVM->internalVMFunctions->currentVMThread(javaVM);
3006
J9ClassWalkState classWalkState;
3007
TR_StatsHisto<30> statsInvocationCountLoopy("Stats inv. count loopy methods", 5, 155);
3008
TR_StatsHisto<30> statsInvocationCountLoopless("Stats inv. count loopless methods", 5, 155);
3009
int32_t numMethodsNeverInvoked = 0;
3010
J9Class * clazz = javaVM->internalVMFunctions->allClassesStartDo(&classWalkState, javaVM, NULL);
3011
3012
while (clazz)
3013
{
3014
3015
if (!J9ROMCLASS_IS_PRIMITIVE_OR_ARRAY(clazz->romClass))
3016
{
3017
J9Method * newInstanceThunk = getNewInstancePrototype(vmThread);
3018
J9Method * ramMethods = (J9Method *) (clazz->ramMethods);
3019
for (int32_t m = 0; m < clazz->romClass->romMethodCount; m++)
3020
{
3021
J9Method * method = &ramMethods[m];
3022
J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
3023
if (!(romMethod->modifiers & (J9AccNative | J9AccAbstract)) &&
3024
method != newInstanceThunk &&
3025
!TR::CompilationInfo::isCompiled(method))
3026
{
3027
// Print the count for the interpreted method
3028
/*
3029
J9UTF8 *utf8;
3030
utf8 = J9ROMCLASS_CLASSNAME(clazz->romClass);
3031
fprintf(stderr, "%.*s", J9UTF8_LENGTH(utf8), (char *) J9UTF8_DATA(utf8));
3032
utf8 = J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(method));
3033
fprintf(stderr, ".%.*s", J9UTF8_LENGTH(utf8), (char *) J9UTF8_DATA(utf8));
3034
utf8 = J9ROMMETHOD_SIGNATURE(J9_ROM_METHOD_FROM_RAM_METHOD(method));
3035
fprintf(stderr, "%.*s", J9UTF8_LENGTH(utf8), (char *) J9UTF8_DATA(utf8));
3036
*/
3037
intptr_t count = (intptr_t) TR::CompilationInfo::getInvocationCount(method);
3038
if (count < 0)
3039
{
3040
fprintf(stderr, "Bad count\n");
3041
}
3042
else
3043
{
3044
//fprintf(stderr, " extra=%d ", count);
3045
intptr_t initialCount = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR::Options::getCmdLineOptions()->getInitialBCount() : TR::Options::getCmdLineOptions()->getInitialCount();
3046
if (count > initialCount)
3047
{
3048
fprintf(stderr, " Bad count\n");
3049
}
3050
else
3051
{
3052
intptr_t invocationCount = initialCount - count;
3053
//fprintf(stderr, " invocation count=%d\n", invocationCount);
3054
if (invocationCount==0 || count == 0) // some methods have count==0 and are never invoked
3055
{
3056
numMethodsNeverInvoked++;
3057
}
3058
else
3059
{
3060
if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))
3061
statsInvocationCountLoopy.update((double)invocationCount);
3062
else
3063
statsInvocationCountLoopless.update((double)invocationCount);
3064
}
3065
}
3066
}
3067
}
3068
}
3069
}
3070
clazz = javaVM->internalVMFunctions->allClassesNextDo(&classWalkState);
3071
}
3072
javaVM->internalVMFunctions->allClassesEndDo(&classWalkState);
3073
statsInvocationCountLoopy.report(stderr);
3074
statsInvocationCountLoopless.report(stderr);
3075
fprintf(stderr, "Methods never invoked = %d\n", numMethodsNeverInvoked);
3076
}
3077
#endif // INVOCATION_STATS
3078
3079
#include "infra/Statistics.hpp" // MCT
3080
3081
void TR::CompilationInfo::stopCompilationThreads()
3082
{
3083
J9JavaVM * const vm = _jitConfig->javaVM;
3084
J9VMThread * const vmThread = vm->internalVMFunctions->currentVMThread(vm);
3085
3086
static char * printCompStats = feGetEnv("TR_PrintCompStats");
3087
if (printCompStats)
3088
{
3089
if (statCompErrors.samples() > 0)
3090
statCompErrors.report(stderr);
3091
3092
fprintf(stderr, "Number of compilations per level:\n");
3093
for (int i = 0; i < (int)numHotnessLevels; i++)
3094
{
3095
if (_statsOptLevels[i] > 0)
3096
{
3097
fprintf(stderr, "Level=%d\tnumComp=%d", i, _statsOptLevels[i]);
3098
#if defined(J9VM_OPT_JITSERVER)
3099
if (_statsRemoteOptLevels[i] > 0)
3100
fprintf(stderr, "\tnumRemoteComp=%d", _statsRemoteOptLevels[i]);
3101
#endif /* defined(J9VM_OPT_JITSERVER) */
3102
fprintf(stderr, "\n");
3103
}
3104
}
3105
3106
if (_statNumJNIMethodsCompiled > 0)
3107
fprintf(stderr, "NumJNIMethodsCompiled=%u\n", _statNumJNIMethodsCompiled);
3108
if (numMethodsFoundInSharedCache() > 0)
3109
fprintf(stderr, "NumMethodsFoundInSharedCache=%d\n", numMethodsFoundInSharedCache());
3110
if (_statNumMethodsFromSharedCache)
3111
fprintf(stderr, "NumMethodsTakenFromSharedCache=%u\n", _statNumMethodsFromSharedCache);
3112
if (_statNumAotedMethods)
3113
fprintf(stderr, "NumAotedMethods=%u\n", _statNumAotedMethods);
3114
if (_statNumAotedMethodsRecompiled)
3115
fprintf(stderr, "NumberOfAotedMethodsThatWereRecompiled=%u (forced=%d)\n", _statNumAotedMethodsRecompiled, _statNumForcedAotUpgrades);
3116
if (_statTotalAotQueryTime)
3117
fprintf(stderr, "Time spent querying shared cache for methods: %u ms\n", _statTotalAotQueryTime/1000);
3118
3119
if (getHWProfiler() && TR_HWProfiler::_STATS_NumUpgradesDueToRI > 0)
3120
fprintf(stderr, "numUpgradesDueToRI=%u\n", TR_HWProfiler::_STATS_NumUpgradesDueToRI);
3121
3122
fprintf(stderr, "Classes loaded=%d\n", getPersistentInfo()->getNumLoadedClasses());
3123
3124
// assumptionTableMutex is not used, so the numbers may be a little off
3125
fprintf(stderr, "\tStats on assumptions:\n");
3126
TR_RuntimeAssumptionTable * rat = getPersistentInfo()->getRuntimeAssumptionTable();
3127
int32_t unreclaimedAssumptions = 0;
3128
for (int32_t i=0; i < LastAssumptionKind; i++)
3129
{
3130
fprintf(stderr, "\tAssumptionType=%d allocated=%d reclaimed=%d\n", i, rat->getAssumptionCount(i), rat->getReclaimedAssumptionCount(i));
3131
unreclaimedAssumptions += rat->getAssumptionCount(i) - rat->getReclaimedAssumptionCount(i);
3132
}
3133
int32_t assumptionsInRAT = rat->countRatAssumptions();
3134
fprintf(stderr, "Summary of assumptions: unreclaimed=%d, in RAT=%d\n", unreclaimedAssumptions, rat->countRatAssumptions());
3135
3136
fprintf(stderr, "GCR bodies=%d, GCRSaves=%d GCRRecomp=%u\n",
3137
getPersistentInfo()->getNumGCRBodies(),
3138
getPersistentInfo()->getNumGCRSaves(),
3139
_statNumGCRInducedCompilations);
3140
if (_statNumSamplingJProfilingBodies != 0)
3141
fprintf(stderr, "SamplingJProfiling bodies=%u\n", _statNumSamplingJProfilingBodies);
3142
if (_statNumJProfilingBodies != 0)
3143
fprintf(stderr, "Jprofiling bodies=%u\n", _statNumJProfilingBodies);
3144
if (_statNumMethodsFromJProfilingQueue != 0)
3145
fprintf(stderr, "Recompilation for bodies with JProfiling=%u\n", _statNumMethodsFromJProfilingQueue);
3146
if (_statNumRecompilationForBodiesWithJProfiling != 0)
3147
fprintf(stderr, "Methods taken from the queue with JProfiling requests=%u\n", _statNumRecompilationForBodiesWithJProfiling);
3148
3149
#ifdef INVOCATION_STATS
3150
printAllCounts(_jitConfig->javaVM);
3151
#endif
3152
3153
getLowPriorityCompQueue().printStats();
3154
3155
fprintf(stderr, "Compilation queue peak size = %d\n", getPeakMethodQueueSize());
3156
fprintf(stderr, "Compilation queue size at shutdown = %d\n", getMethodQueueSize());
3157
#ifdef MCT_STATS
3158
statCompReqResidencyTime.report(stderr); // MCT
3159
statCompReqProcessingTime.report(stderr); // MCT
3160
statNumReqForProcessing.report(stderr); // MCT
3161
fprintf(stderr, "NumberOfActivations=%u number of suspensions=%u\n", numCompThreadsActivations, numCompThreadsSuspensions);
3162
#endif
3163
} // if (printCompStats)
3164
3165
if (TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableAOTRelocationTiming))
3166
{
3167
fprintf(stderr, "Time spent relocating all AOT methods: %u ms\n", this->getAotRelocationTime()/1000);
3168
}
3169
3170
static char * printCompMem = feGetEnv("TR_PrintCompMem");
3171
static char * printCCUsage = feGetEnv("TR_PrintCodeCacheUsage");
3172
3173
// Example:
3174
// CodeCache: size=262144Kb used=2048Kb max_used=1079Kb free=260096Kb
3175
if (TR::Options::getCmdLineOptions()->getOption(TR_PrintCodeCacheUsage) || printCompMem || printCCUsage)
3176
{
3177
unsigned long currTotalUsedKB = (unsigned long)(TR::CodeCacheManager::instance()->getCurrTotalUsedInBytes()/1024);
3178
unsigned long maxUsedKB = (unsigned long)(TR::CodeCacheManager::instance()->getMaxUsedInBytes()/1024);
3179
3180
fprintf(stderr, "\nCodeCache: size=%" OMR_PRIuPTR "Kb used=%luKb max_used=%luKb free=%" OMR_PRIuPTR "Kb\n\n",
3181
_jitConfig->codeCacheTotalKB,
3182
currTotalUsedKB,
3183
maxUsedKB,
3184
(_jitConfig->codeCacheTotalKB - currTotalUsedKB));
3185
}
3186
3187
if (printCompMem)
3188
{
3189
int32_t codeCacheAllocated = TR::CodeCacheManager::instance()->getCurrentNumberOfCodeCaches() * _jitConfig->codeCacheKB;
3190
fprintf(stderr, "Allocated memory for code cache = %d KB\tLimit = %" OMR_PRIuPTR " KB\n",
3191
codeCacheAllocated, _jitConfig->codeCacheTotalKB);
3192
3193
TR::CodeCacheManager::instance()->printMccStats();
3194
3195
fprintf(stderr, "Allocated memory for data cache = %d KB\tLimit = %" OMR_PRIuPTR " KB\n",
3196
TR_DataCacheManager::getManager()->getTotalSegmentMemoryAllocated()/1024,
3197
_jitConfig->dataCacheTotalKB);
3198
3199
if (getJProfilerThread())
3200
fprintf(stderr, "Allocated memory for profile info = %" OMR_PRIdSIZE " KB\n", getJProfilerThread()->getProfileInfoFootprint()/1024);
3201
}
3202
3203
static char * printPersistentMem = feGetEnv("TR_PrintPersistentMem");
3204
if (printPersistentMem)
3205
{
3206
if (trPersistentMemory)
3207
trPersistentMemory->printMemStats();
3208
}
3209
3210
TR_DataCacheManager::getManager()->printStatistics();
3211
3212
bool aotStatsEnabled = TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableAOTStats);
3213
if (aotStatsEnabled)
3214
{
3215
fprintf(stderr, "AOT code compatible: %d\n", static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader);
3216
3217
TR_AOTStats *aotStats = ((TR_JitPrivateConfig *)_jitConfig->privateConfig)->aotStats;
3218
fprintf(stderr, "AOT failedPerfAssumptionCode: %d\n", aotStats->failedPerfAssumptionCode);
3219
fprintf(stderr, "COMPILE TIME INFO ------\n");
3220
fprintf(stderr, "numCHEntriesAlreadyStoredInLocalList: %d\n", aotStats->numCHEntriesAlreadyStoredInLocalList);
3221
fprintf(stderr, "numNewCHEntriesInLocalList: %d\n", aotStats->numNewCHEntriesInLocalList);
3222
fprintf(stderr, "numNewCHEntriesInSharedClass: %d\n", aotStats->numNewCHEntriesInSharedClass);
3223
fprintf(stderr, "numEntriesFoundInLocalChain: %d\n", aotStats->numEntriesFoundInLocalChain);
3224
fprintf(stderr, "numEntriesFoundAndValidatedInSharedClass: %d\n", aotStats->numEntriesFoundAndValidatedInSharedClass);
3225
fprintf(stderr, "numClassChainNotInSharedClass: %d\n", aotStats->numClassChainNotInSharedClass);
3226
fprintf(stderr, "numCHInSharedCacheButFailValiation: %d\n", aotStats->numCHInSharedCacheButFailValiation);
3227
fprintf(stderr, "numInstanceFieldInfoNotUsed: %d\n", aotStats->numInstanceFieldInfoNotUsed);
3228
fprintf(stderr, "numStaticFieldInfoNotUsed: %d\n", aotStats->numStaticFieldInfoNotUsed);
3229
fprintf(stderr, "numDefiningClassNotFound: %d\n", aotStats->numDefiningClassNotFound);
3230
fprintf(stderr, "numInstanceFieldInfoUsed: %d\n", aotStats->numInstanceFieldInfoUsed);
3231
fprintf(stderr, "numStaticFieldInfoUsed: %d\n", aotStats->numStaticFieldInfoUsed);
3232
fprintf(stderr, "numCannotGenerateHashForStore: %d\n", aotStats->numCannotGenerateHashForStore);
3233
3234
fprintf(stderr, "-------------------------\n");
3235
fprintf(stderr, "RUNTIME INFO -----------\n");
3236
3237
fprintf(stderr, "numRuntimeChainNotFound: %d\n", aotStats->numRuntimeChainNotFound);
3238
fprintf(stderr, "numRuntimeStaticFieldUnresolvedCP: %d\n", aotStats->numRuntimeStaticFieldUnresolvedCP);
3239
fprintf(stderr, "numRuntimeInstanceFieldUnresolvedCP: %d\n", aotStats->numRuntimeInstanceFieldUnresolvedCP);
3240
fprintf(stderr, "numRuntimeUnresolvedStaticFieldFromCP: %d\n", aotStats->numRuntimeUnresolvedStaticFieldFromCP);
3241
fprintf(stderr, "numRuntimeUnresolvedInstanceFieldFromCP: %d\n", aotStats->numRuntimeUnresolvedInstanceFieldFromCP);
3242
fprintf(stderr, "numRuntimeResolvedStaticFieldButFailValidation: %d\n", aotStats->numRuntimeResolvedStaticFieldButFailValidation);
3243
fprintf(stderr, "numRuntimeResolvedInstanceFieldButFailValidation: %d\n", aotStats->numRuntimeResolvedInstanceFieldButFailValidation);
3244
fprintf(stderr, "numRuntimeStaticFieldReloOK: %d\n", aotStats->numRuntimeStaticFieldReloOK);
3245
fprintf(stderr, "numRuntimeInstanceFieldReloOK: %d\n", aotStats->numRuntimeInstanceFieldReloOK);
3246
3247
fprintf(stderr, "numRuntimeClassAddressUnresolvedCP: %d\n", aotStats->numRuntimeClassAddressUnresolvedCP);
3248
fprintf(stderr, "numRuntimeClassAddressFromCP: %d\n", aotStats->numRuntimeClassAddressFromCP);
3249
fprintf(stderr, "numRuntimeClassAddressButFailValidation: %d\n", aotStats->numRuntimeClassAddressButFailValidation);
3250
fprintf(stderr, "numRuntimeClassAddressReloOK: %d\n", aotStats->numRuntimeClassAddressReloOK);
3251
3252
fprintf(stderr, "numRuntimeClassAddressRelocationCount: %d\n", aotStats->numRuntimeClassAddressRelocationCount);
3253
fprintf(stderr, "numRuntimeClassAddressReloUnresolvedCP: %d\n", aotStats->numRuntimeClassAddressReloUnresolvedCP);
3254
fprintf(stderr, "numRuntimeClassAddressReloUnresolvedClass: %d\n", aotStats->numRuntimeClassAddressReloUnresolvedClass);
3255
3256
fprintf(stderr, "numClassValidations: %d\n", aotStats->numClassValidations);
3257
fprintf(stderr, "numClassValidationsFailed: %d\n", aotStats->numClassValidationsFailed);
3258
fprintf(stderr, "numWellKnownClassesValidationsFailed: %d\n", aotStats->numWellKnownClassesValidationsFailed);
3259
3260
fprintf(stderr, "numVMCheckCastEvaluator (x86): %d\n", aotStats->numVMCheckCastEvaluator);
3261
fprintf(stderr, "numVMInstanceOfEvaluator (x86): %d\n", aotStats->numVMInstanceOfEvaluator);
3262
fprintf(stderr, "numVMIfInstanceOfEvaluator (x86): %d\n", aotStats->numVMIfInstanceOfEvaluator);
3263
fprintf(stderr, "numCheckCastVMHelperInstructions (x86): %d\n", aotStats->numCheckCastVMHelperInstructions);
3264
fprintf(stderr, "numInstanceOfVMHelperInstructions (x86): %d\n", aotStats->numInstanceOfVMHelperInstructions);
3265
fprintf(stderr, "numIfInstanceOfVMHelperInstructions (x86): %d\n", aotStats->numIfInstanceOfVMHelperInstructions);
3266
3267
3268
fprintf(stderr, "-------------------------\n");
3269
fprintf(stderr, "AOT METHOD INLINING COMPILE TIME INFO ------\n");
3270
3271
fprintf(stderr, "numStaticMethodFromDiffClassLoader: %d\n", aotStats->staticMethods.numMethodFromDiffClassLoader);
3272
fprintf(stderr, "numStaticMethodInSameClass: %d\n", aotStats->staticMethods.numMethodInSameClass);
3273
fprintf(stderr, "numStaticMethodNotInSameClass: %d\n", aotStats->staticMethods.numMethodNotInSameClass);
3274
fprintf(stderr, "numStaticMethodResolvedAtCompile: %d\n", aotStats->staticMethods.numMethodResolvedAtCompile);
3275
fprintf(stderr, "numStaticMethodNotResolvedAtCompile: %d\n", aotStats->staticMethods.numMethodNotResolvedAtCompile);
3276
fprintf(stderr, "numStaticMethodROMMethodNotInSC: %d\n", aotStats->staticMethods.numMethodROMMethodNotInSC);
3277
3278
fprintf(stderr, "numSpecialMethodFromDiffClassLoader: %d\n", aotStats->specialMethods.numMethodFromDiffClassLoader);
3279
fprintf(stderr, "numSpecialMethodInSameClass: %d\n", aotStats->specialMethods.numMethodInSameClass);
3280
fprintf(stderr, "numSpecialMethodNotInSameClass: %d\n", aotStats->specialMethods.numMethodNotInSameClass);
3281
fprintf(stderr, "numSpecialMethodResolvedAtCompile: %d\n", aotStats->specialMethods.numMethodResolvedAtCompile);
3282
fprintf(stderr, "numSpecialMethodNotResolvedAtCompile: %d\n", aotStats->specialMethods.numMethodNotResolvedAtCompile);
3283
fprintf(stderr, "numSpecialMethodROMMethodNotInSC: %d\n", aotStats->specialMethods.numMethodROMMethodNotInSC);
3284
3285
fprintf(stderr, "numVirtualMethodFromDiffClassLoader: %d\n", aotStats->virtualMethods.numMethodFromDiffClassLoader);
3286
fprintf(stderr, "numVirtualMethodInSameClass: %d\n", aotStats->virtualMethods.numMethodInSameClass);
3287
fprintf(stderr, "numVirtualMethodNotInSameClass: %d\n", aotStats->virtualMethods.numMethodNotInSameClass);
3288
fprintf(stderr, "numVirtualMethodResolvedAtCompile: %d\n", aotStats->virtualMethods.numMethodResolvedAtCompile);
3289
fprintf(stderr, "numVirtualMethodNotResolvedAtCompile: %d\n", aotStats->virtualMethods.numMethodNotResolvedAtCompile);
3290
fprintf(stderr, "numVirtualMethodROMMethodNotInSC: %d\n", aotStats->virtualMethods.numMethodROMMethodNotInSC);
3291
3292
fprintf(stderr, "numInterfaceMethodFromDiffClassLoader: %d\n", aotStats->interfaceMethods.numMethodFromDiffClassLoader);
3293
fprintf(stderr, "numInterfaceMethodInSameClass: %d\n", aotStats->interfaceMethods.numMethodInSameClass);
3294
fprintf(stderr, "numInterfaceMethodNotInSameClass: %d\n", aotStats->interfaceMethods.numMethodNotInSameClass);
3295
fprintf(stderr, "numInterfaceMethodResolvedAtCompile: %d\n", aotStats->interfaceMethods.numMethodResolvedAtCompile);
3296
fprintf(stderr, "numInterfaceMethodNotResolvedAtCompile: %d\n", aotStats->interfaceMethods.numMethodNotResolvedAtCompile);
3297
fprintf(stderr, "numInterfaceMethodROMMethodNotInSC: %d\n", aotStats->interfaceMethods.numMethodROMMethodNotInSC);
3298
3299
fprintf(stderr, "-------------------------\n");
3300
3301
fprintf(stderr, "AOT METHOD INLINING RUNTIME INFO ------\n");
3302
3303
fprintf(stderr, "numInlinedMethodOverridden: %d\n", aotStats->numInlinedMethodOverridden);
3304
fprintf(stderr, "numInlinedMethodNotResolved: %d\n", aotStats->numInlinedMethodNotResolved);
3305
fprintf(stderr, "numInlinedMethodClassNotMatch: %d\n", aotStats->numInlinedMethodClassNotMatch);
3306
fprintf(stderr, "numInlinedMethodCPNotResolved: %d\n", aotStats->numInlinedMethodCPNotResolved);
3307
fprintf(stderr, "numInlinedMethodRelocated: %d\n", aotStats->numInlinedMethodRelocated);
3308
fprintf(stderr, "numInlinedMethodValidationFailed: %d\n", aotStats->numInlinedMethodValidationFailed);
3309
3310
fprintf(stderr, "numDataAddressRelosSucceed: %d\n", aotStats->numDataAddressRelosSucceed);
3311
fprintf(stderr, "numDataAddressRelosFailed: %d\n", aotStats->numDataAddressRelosFailed);
3312
3313
fprintf(stderr, "-------------------------\n");
3314
3315
fprintf(stderr, "numStaticMethodsValidationFailed: %d\n", aotStats->staticMethods.numFailedValidations);
3316
fprintf(stderr, "numStaticMethodsValidationSucceeded: %d\n", aotStats->staticMethods.numSucceededValidations);
3317
fprintf(stderr, "numSpecialMethodsValidationFailed: %d\n", aotStats->specialMethods.numFailedValidations);
3318
fprintf(stderr, "numSpecialMethodsValidationSucceeded: %d\n", aotStats->specialMethods.numSucceededValidations);
3319
fprintf(stderr, "numVirtualMethodsValidationFailed: %d\n", aotStats->virtualMethods.numFailedValidations);
3320
fprintf(stderr, "numVirtualMethodsValidationSucceeded: %d\n", aotStats->virtualMethods.numSucceededValidations);
3321
fprintf(stderr, "numInterfaceMethodsValidationFailed: %d\n", aotStats->interfaceMethods.numFailedValidations);
3322
fprintf(stderr, "numInterfaceMethodsValidationSucceeded: %d\n", aotStats->interfaceMethods.numSucceededValidations);
3323
fprintf(stderr, "numAbstractMethodsValidationFailed: %d\n", aotStats->abstractMethods.numFailedValidations);
3324
fprintf(stderr, "numAbstractMethodsValidationSucceeded: %d\n", aotStats->abstractMethods.numSucceededValidations);
3325
3326
fprintf(stderr, "-------------------------\n");
3327
fprintf(stderr, "numProfiledClassGuardsValidationFailed: %d\n", aotStats->profiledClassGuards.numFailedValidations);
3328
fprintf(stderr, "numProfiledClassGuardsValidationSucceeded: %d\n", aotStats->profiledClassGuards.numSucceededValidations);
3329
fprintf(stderr, "numProfiledMethodGuardsValidationFailed: %d\n", aotStats->profiledMethodGuards.numFailedValidations);
3330
fprintf(stderr, "numProfiledMethodGuardsValidationSucceeded: %d\n", aotStats->profiledMethodGuards.numSucceededValidations);
3331
fprintf(stderr, "-------------------------\n");
3332
3333
fprintf(stderr, "RELO FAILURES BY TYPE ------\n");
3334
for (uint32_t i = 0; i < TR_NumExternalRelocationKinds; i++)
3335
{
3336
fprintf(stderr, "%s: %d\n", TR::ExternalRelocation::getName((TR_ExternalRelocationTargetKind)i), aotStats->numRelocationsFailedByType[i]);
3337
}
3338
fprintf(stderr, "-------------------------\n");
3339
3340
} // AOT stats
3341
3342
3343
if (printCompStats && (dynamicThreadPriority() || compBudgetSupport()))
3344
{
3345
fprintf(stderr, "Number of yields =%4u\n", _statNumYields);
3346
fprintf(stderr, "NumPriorityChanges=%4u\n", _statNumPriorityChanges);
3347
fprintf(stderr, "NumUpgradeInterpretedMethod =%u\n", _statNumUpgradeInterpretedMethod);
3348
fprintf(stderr, "NumDowngradeInterpretedMethod=%u\n", _statNumDowngradeInterpretedMethod);
3349
fprintf(stderr, "NumUpgradeJittedMethod=%u\n", _statNumUpgradeJittedMethod);
3350
fprintf(stderr, "NumQueuePromotions=%u\n", _statNumQueuePromotions);
3351
}
3352
3353
#if defined(J9VM_OPT_JITSERVER)
3354
static char *printJITServerIPMsgStats = feGetEnv("TR_PrintJITServerIPMsgStats");
3355
if (printJITServerIPMsgStats)
3356
{
3357
if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
3358
{
3359
TR_J9VMBase *vmj9 = (TR_J9VMBase *)TR_J9VMBase::get(_jitConfig, NULL);
3360
JITServerIProfiler *iProfiler = (JITServerIProfiler *)vmj9->getIProfiler();
3361
iProfiler->printStats();
3362
}
3363
}
3364
3365
static char *printJITServerConnStats = feGetEnv("TR_PrintJITServerConnStats");
3366
if (printJITServerConnStats)
3367
{
3368
if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
3369
{
3370
fprintf(stderr, "Number of connections opened = %u\n", JITServer::ServerStream::getNumConnectionsOpened());
3371
fprintf(stderr, "Number of connections closed = %u\n", JITServer::ServerStream::getNumConnectionsClosed());
3372
}
3373
else if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)
3374
{
3375
fprintf(stderr, "Number of connections opened = %u\n", JITServer::ClientStream::getNumConnectionsOpened());
3376
fprintf(stderr, "Number of connections closed = %u\n", JITServer::ClientStream::getNumConnectionsClosed());
3377
}
3378
}
3379
3380
static char *printJITServerAOTCacheStats = feGetEnv("TR_PrintJITServerAOTCacheStats");
3381
if (printJITServerAOTCacheStats)
3382
{
3383
if (auto aotCacheMap = getJITServerAOTCacheMap())
3384
aotCacheMap->printStats(stderr);
3385
if (auto deserializer = getJITServerAOTDeserializer())
3386
deserializer->printStats(stderr);
3387
}
3388
#endif /* defined(J9VM_OPT_JITSERVER) */
3389
3390
#ifdef STATS
3391
if (compBudgetSupport() || dynamicThreadPriority())
3392
{
3393
fprintf(stderr, "Compilation request queue size at shutdown=%d\n", getMethodQueueSize());
3394
statQueueSize.report(stderr);
3395
if (compBudgetSupport())
3396
{
3397
statBudgetEpoch.report(stderr);
3398
statBudgetSmallLag.report(stderr);
3399
statBudgetMediumLag.report(stderr);
3400
statEpochLength.report(stderr);
3401
}
3402
statEvents.report(stderr);
3403
statLowPriority.report(stderr);
3404
statLowBudget.report(stderr);
3405
statOverhead.report(stderr);
3406
}
3407
#endif
3408
acquireCompMonitor(vmThread);
3409
3410
// Cycle through all non-diagnostic threads and stop them
3411
for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)
3412
{
3413
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
3414
3415
if (!curCompThreadInfoPT->isDiagnosticThread())
3416
stopCompilationThread(curCompThreadInfoPT);
3417
}
3418
3419
TR_ASSERT_FATAL(getNumCompThreadsActive() == 0, "All threads must be inactive at this point\n");
3420
3421
purgeMethodQueue(compilationSuspended);
3422
3423
// Cycle though all non-diagnostic threads and wait for them to terminate. At this point it is possible that a
3424
// compilation thread has crashed and is going through the JitDump process. The reason we skipped terminating the
3425
// diagnostic threads in the above loop is because the JitDump logic will activate the diagnostic thread to generate
3426
// the JitDump, so the diagnostic thread must not be in a terminated state at that point.
3427
for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)
3428
{
3429
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
3430
3431
if (!curCompThreadInfoPT->isDiagnosticThread())
3432
{
3433
while (curCompThreadInfoPT->getCompilationThreadState() != COMPTHREAD_STOPPED)
3434
{
3435
getCompilationMonitor()->notifyAll();
3436
waitOnCompMonitor(vmThread);
3437
}
3438
}
3439
}
3440
3441
// Now that all compilation threads have terminated, we are sure none of them have crashed, or they have finished
3442
// generating a JitDump. Only at this point can we terminate the diagnostic threads. If a compilation thread did
3443
// crash we will actually never execute code following this comment. This is because the crashed thread will be
3444
// in an active state, since it has crashed during a compilation, and the we will be waiting on the comp monitor
3445
// for the crashed thread in the loop above. However because the diagnostic data is generated on the crashed
3446
// thread this thread will never return to execute the state processing loop, and thus will never terminate.
3447
// This is ok, because following the dump process in the JVM we will terminate the entire JVM process.
3448
for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)
3449
{
3450
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
3451
3452
if (curCompThreadInfoPT->isDiagnosticThread())
3453
stopCompilationThread(curCompThreadInfoPT);
3454
}
3455
3456
// Wake up the diagnostic thread and stop it. If it is currently active then we will block here until the JitDump
3457
// process is complete (see #11860).
3458
for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)
3459
{
3460
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
3461
3462
if (curCompThreadInfoPT->isDiagnosticThread())
3463
{
3464
while (curCompThreadInfoPT->getCompilationThreadState() != COMPTHREAD_STOPPED)
3465
{
3466
getCompilationMonitor()->notifyAll();
3467
waitOnCompMonitor(vmThread);
3468
}
3469
}
3470
}
3471
3472
// Remove the method pool entries
3473
//
3474
PORT_ACCESS_FROM_JAVAVM(_jitConfig->javaVM);
3475
while (_methodPool)
3476
{
3477
TR_MethodToBeCompiled *next = _methodPool->_next;
3478
if (_methodPool->_numThreadsWaiting == 0)
3479
{
3480
_methodPool->shutdown();
3481
j9mem_free_memory(_methodPool);
3482
}
3483
else // Some thread may need this entry after the waiting thread resumes activity
3484
{
3485
_methodPool->_entryShouldBeDeallocated = true;
3486
}
3487
_methodPool = next;
3488
}
3489
#ifdef LINUX
3490
// Now that all compilation threads are stopped we can close the perfFile stream
3491
if (TR::CompilationInfoPerThreadBase::getPerfFile())
3492
{
3493
// Generate any non-method entries (trampolines, etc) that are present in each codecache
3494
TR::CodeCacheManager *manager = TR::CodeCacheManager::instance();
3495
for (TR::CodeCache *cc = manager->getFirstCodeCache(); cc; cc = cc->getNextCodeCache())
3496
{
3497
cc->generatePerfToolEntries(TR::CompilationInfoPerThreadBase::getPerfFile());
3498
}
3499
3500
j9jit_fclose(TR::CompilationInfoPerThreadBase::getPerfFile());
3501
TR::CompilationInfoPerThreadBase::setPerfFile(NULL); // prevent closing twice
3502
}
3503
#endif
3504
3505
releaseCompMonitor(vmThread);
3506
#if defined(J9VM_OPT_JITSERVER)
3507
if (getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)
3508
{
3509
try
3510
{
3511
JITServer::ClientStream client(getPersistentInfo());
3512
client.writeError(JITServer::MessageType::clientSessionTerminate, getPersistentInfo()->getClientUID());
3513
}
3514
catch (const JITServer::StreamFailure &e)
3515
{
3516
JITServerHelpers::postStreamFailure(OMRPORT_FROM_J9PORT(_jitConfig->javaVM->portLibrary), this);
3517
// catch the stream failure exception if the server dies before the dummy message is send for termination.
3518
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
3519
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "JITServer StreamFailure (server unreachable before the termination message was sent): %s", e.what());
3520
}
3521
}
3522
#endif /* defined(J9VM_OPT_JITSERVER) */
3523
}
3524
3525
void TR::CompilationInfo::stopCompilationThread(CompilationInfoPerThread* compInfoPT)
3526
{
3527
compInfoPT->setCompilationShouldBeInterrupted(SHUTDOWN_COMP_INTERRUPT);
3528
3529
switch (compInfoPT->getCompilationThreadState())
3530
{
3531
case COMPTHREAD_SUSPENDED:
3532
compInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_TERMINATE);
3533
compInfoPT->getCompThreadMonitor()->enter();
3534
compInfoPT->getCompThreadMonitor()->notifyAll();
3535
compInfoPT->getCompThreadMonitor()->exit();
3536
break;
3537
3538
case COMPTHREAD_ACTIVE:
3539
case COMPTHREAD_SIGNAL_WAIT:
3540
case COMPTHREAD_WAITING:
3541
compInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_TERMINATE);
3542
3543
if (!compInfoPT->isDiagnosticThread())
3544
decNumCompThreadsActive();
3545
break;
3546
3547
case COMPTHREAD_SIGNAL_SUSPEND:
3548
compInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_TERMINATE);
3549
break;
3550
3551
case COMPTHREAD_SIGNAL_TERMINATE:
3552
case COMPTHREAD_STOPPING:
3553
case COMPTHREAD_STOPPED:
3554
// Weird case; we should not do anything
3555
break;
3556
3557
case COMPTHREAD_UNINITIALIZED:
3558
// Compilation thread did not have time to become fully initialized
3559
compInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_TERMINATE);
3560
break;
3561
3562
default:
3563
TR_ASSERT_FATAL(false, "No other comp thread state possible here");
3564
}
3565
}
3566
3567
IDATA J9THREAD_PROC compilationThreadProc(void *entryarg)
3568
{
3569
//J9JITConfig *jitConfig = (J9JITConfig *)entryarg;
3570
TR::CompilationInfoPerThread *compInfoPT = (TR::CompilationInfoPerThread *)entryarg;
3571
J9JITConfig *jitConfig = compInfoPT->getJitConfig();
3572
J9JavaVM *vm = jitConfig->javaVM;
3573
J9VMThread *compThread = 0;
3574
TR::CompilationInfo *compInfo = TR::CompilationInfo::get();
3575
static bool TR_NoStructuredHandler = feGetEnv("TR_NoStructuredHandler")?1:0;
3576
3577
int rc = vm->internalVMFunctions->internalAttachCurrentThread
3578
(vm, &compThread, NULL,
3579
J9_PRIVATE_FLAGS_DAEMON_THREAD | J9_PRIVATE_FLAGS_NO_OBJECT |
3580
J9_PRIVATE_FLAGS_SYSTEM_THREAD | J9_PRIVATE_FLAGS_ATTACHED_THREAD,
3581
compInfoPT->getOsThread());
3582
3583
if (rc != JNI_OK)
3584
{
3585
compInfoPT->getCompThreadMonitor()->enter();
3586
compInfoPT->setCompilationThreadState(COMPTHREAD_ABORT);
3587
compInfoPT->getCompThreadMonitor()->notifyAll();
3588
compInfoPT->getCompThreadMonitor()->exit();
3589
return JNI_ERR;
3590
}
3591
3592
#if defined(LINUX)
3593
j9thread_set_name(j9thread_self(), "JIT Compilation");
3594
#endif
3595
3596
compInfo->acquireCompMonitor(compThread);
3597
compInfo->debugPrint(compThread, "+CM\n");
3598
if (compInfoPT->getCompThreadId() == 0)
3599
{
3600
compInfoPT->setCompilationThreadState(COMPTHREAD_ACTIVE);
3601
compInfo->incNumCompThreadsActive();
3602
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
3603
{
3604
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Created compThread %d as ACTIVE",
3605
(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), compInfoPT->getCompThreadId());
3606
}
3607
}
3608
else // all other compilation threads should start as suspended
3609
{
3610
compInfoPT->setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);
3611
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
3612
{
3613
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Created compThread %d as SUSPENDED",
3614
(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), compInfoPT->getCompThreadId());
3615
}
3616
}
3617
compInfo->releaseCompMonitor(compThread);
3618
3619
compInfoPT->getCompThreadMonitor()->enter();
3620
compInfoPT->setCompilationThread(compThread);
3621
3622
compInfoPT->getCompThreadMonitor()->notifyAll(); // just in case main thread is waiting for compThread to appear
3623
compInfoPT->getCompThreadMonitor()->exit();
3624
3625
compInfo->debugPrint(compThread, "\tCompilation Thread attached to the VM\n");
3626
3627
compInfo->debugPrint(compThread, "\tCompilation Thread acquiring compilation monitor\n");
3628
compInfo->acquireCompMonitor(compThread);
3629
3630
// It is possible that the shutdown signal came before this thread has had the time
3631
// to become fully initialized. If that's the case, the state will appear as STOPPING
3632
// instead of UNINITIALIZED. This can happen when we destroy the cache; the java app
3633
// starts and finishes immediately
3634
if (compInfoPT->getCompilationThreadState() == COMPTHREAD_SIGNAL_TERMINATE)
3635
{
3636
compInfoPT->setCompilationThreadState(COMPTHREAD_STOPPING);
3637
// Release the monitor before calling DetachCurrentThread to avoid deadlock
3638
compInfo->releaseCompMonitor(compThread);
3639
if (compThread)
3640
vm->internalVMFunctions->DetachCurrentThread((JavaVM *) vm);
3641
3642
// Re-acquire the monitor
3643
compInfo->acquireCompMonitor(compThread);
3644
compInfoPT->setCompilationThreadState(COMPTHREAD_STOPPED);
3645
compInfo->getCompilationMonitor()->notify();
3646
3647
j9thread_exit((J9ThreadMonitor*)((TR::Monitor *)compInfo->getCompilationMonitor())->getVMMonitor());
3648
3649
return 0; // unreachable
3650
}
3651
3652
PORT_ACCESS_FROM_VMC(compThread);
3653
IDATA result;
3654
3655
#if defined(J9VM_PORT_SIGNAL_SUPPORT)
3656
if (!TR_NoStructuredHandler)
3657
{
3658
/* copied the flags from vmthread.c: note that for the JIT we are not really
3659
interested in continuing. We are installing the handler merely to get
3660
support for crash dumps */
3661
U_32 flags = J9PORT_SIG_FLAG_SIGALLSYNC | J9PORT_SIG_FLAG_MAY_CONTINUE_EXECUTION;
3662
compThread->gpProtected = 1;
3663
3664
I_32 sig_result = j9sig_protect((j9sig_protected_fn)protectedCompilationThreadProc, compInfoPT,
3665
vm->internalVMFunctions->structuredSignalHandler, compThread,
3666
flags, (UDATA*)&result);
3667
if (sig_result != 0)
3668
{
3669
result = JNI_ERR;
3670
}
3671
}
3672
else
3673
#endif
3674
result = protectedCompilationThreadProc(privatePortLibrary, compInfoPT);
3675
3676
j9thread_exit((J9ThreadMonitor*)((TR::Monitor *)compInfo->getCompilationMonitor())->getVMMonitor());
3677
3678
return result;
3679
}
3680
3681
#if defined(LINUX)
3682
#include "sched.h"
3683
#endif
3684
3685
IDATA J9THREAD_PROC protectedCompilationThreadProc(J9PortLibrary *, TR::CompilationInfoPerThread*compInfoPT/*void *vmthread*/)
3686
{
3687
J9VMThread * compThread = compInfoPT->getCompilationThread();//(J9VMThread *) vmthread;
3688
J9JavaVM * vm = compThread->javaVM;
3689
TR::CompilationInfo * compInfo = TR::CompilationInfo::get();
3690
3691
//TODO: decide if the compilation budget should be per thread or not
3692
compInfo->setCompBudgetSupport(TR::Options::_compilationBudget > 0 &&
3693
compInfo->asynchronousCompilation() &&
3694
TR::Compiler->target.numberOfProcessors() < 4 &&
3695
j9thread_get_cpu_time(j9thread_self()) >= 0); // returns negative value if not supported
3696
3697
compInfo->setIdleThreshold(IDLE_THRESHOLD/TR::Compiler->target.numberOfProcessors());
3698
3699
3700
#ifdef J9VM_OPT_JAVA_OFFLOAD_SUPPORT
3701
if ( vm->javaOffloadSwitchOnWithReasonFunc != NULL )
3702
(* vm->javaOffloadSwitchOnWithReasonFunc)(compThread, J9_JNI_OFFLOAD_SWITCH_JIT_COMPILATION_THREAD);
3703
#endif
3704
3705
#if defined(WINDOWS)
3706
// affinity to proc 0
3707
3708
/*
3709
if (TR::Options::getCmdLineOptions()->getOption(TR_CummTiming) ||
3710
TR::Options::getCmdLineOptions()->getOption(TR_Timing) ||
3711
TR::Options::getCmdLineOptions()->getOption(TR_EnableCompYieldStats))
3712
setThreadAffinity(j9thread_get_handle(j9thread_self())); // otherwise we get bad numbers
3713
*/
3714
if (TR::Options::_compThreadAffinityMask)
3715
{
3716
uintptr_t affinityMask = TR::Options::_compThreadAffinityMask;
3717
int32_t numBitsSetInMask = populationCount(affinityMask);
3718
int32_t bitNumberToSet = compInfoPT->getCompThreadId() % numBitsSetInMask;
3719
uintptr_t myMask = 0x1;
3720
int32_t oneBits = 0;
3721
for (int32_t k = 0; k < 8*sizeof(uintptr_t); k++, myMask <<= 1)
3722
{
3723
if (!(affinityMask & myMask))
3724
continue; // jump over bits that are 0
3725
// I found a bit that is set
3726
if (oneBits == bitNumberToSet)
3727
break;
3728
oneBits++;
3729
}
3730
setThreadAffinity(j9thread_get_handle(j9thread_self()), myMask);
3731
}
3732
#elif defined(LINUX) && !defined(J9ZTPF)
3733
3734
// affinity to proc 0
3735
if (TR::Options::_compThreadAffinityMask)
3736
{
3737
cpu_set_t cpuMask;
3738
CPU_ZERO(&cpuMask);
3739
UDATA mask = TR::Options::_compThreadAffinityMask;
3740
3741
for (int cpuID=0; mask; cpuID++,mask>>=1)
3742
{
3743
if (mask & 1)
3744
CPU_SET(cpuID, &cpuMask);
3745
}
3746
3747
if (sched_setaffinity(0, sizeof(cpuMask), &cpuMask) < 0)
3748
// if (pthread_setaffinity_np(hThread, sizeof(cpuMask), &cpuMask) < 0)
3749
{
3750
perror("Error setting affinity");
3751
}
3752
else
3753
{
3754
//printf("Successfully set affinity of comp thread!\n");
3755
}
3756
}
3757
3758
#endif
3759
compInfoPT->run();
3760
compInfoPT->setCompilationThreadState(COMPTHREAD_STOPPING);
3761
3762
compInfo->debugPrint(compThread, "\tstopping compilation thread loop\n");
3763
3764
// print time spent in compilation thread (may work reliably only on Windows)
3765
static char * printCompTime = feGetEnv("TR_PrintCompTime");
3766
if (printCompTime)
3767
{
3768
fprintf(stderr, "Time spent in compilation thread =%u ms\n",
3769
(unsigned)(j9thread_get_self_cpu_time(j9thread_self())/1000000));
3770
}
3771
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
3772
{
3773
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"Time spent in compilation thread =%u ms",
3774
(unsigned)(j9thread_get_self_cpu_time(j9thread_self())/1000000));
3775
}
3776
3777
if (TR::Options::isAnyVerboseOptionSet())
3778
{
3779
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"Stopping compilation thread, vmThread pointer %p, thread ID %d", compThread, compInfoPT->getCompThreadId());
3780
}
3781
3782
#ifdef J9VM_OPT_JAVA_OFFLOAD_SUPPORT
3783
if ( vm->javaOffloadSwitchOffWithReasonFunc != NULL )
3784
(* vm->javaOffloadSwitchOffWithReasonFunc)(compThread, J9_JNI_OFFLOAD_SWITCH_JIT_COMPILATION_THREAD);
3785
#endif
3786
3787
3788
// Release the monitor before calling DetachCurrentThread to avoid deadlock
3789
compInfo->releaseCompMonitor(compThread);
3790
if (compThread)
3791
vm->internalVMFunctions->DetachCurrentThread((JavaVM *) vm);
3792
3793
// Re-acquire the monitor and signal the shutdown thread
3794
compInfo->acquireCompMonitor(compThread);
3795
compInfoPT->setCompilationThreadState(COMPTHREAD_STOPPED);
3796
compInfo->getCompilationMonitor()->notify();
3797
//compInfoPT->setCompilationThread(0);
3798
return 0;
3799
}
3800
3801
#if defined(J9VM_OPT_JITSERVER)
3802
JITServer::ServerStream *
3803
TR::CompilationInfoPerThread::getStream()
3804
{
3805
return (_methodBeingCompiled) ? _methodBeingCompiled->_stream : NULL;
3806
}
3807
#endif /* defined(J9VM_OPT_JITSERVER) */
3808
3809
void
3810
TR::CompilationInfoPerThread::run()
3811
{
3812
#if defined(J9VM_OPT_JITSERVER)
3813
TR::compInfoPT = this; // set the thread_local pointer to this object on first run
3814
#endif
3815
for (
3816
CompilationThreadState threadState = getCompilationThreadState();
3817
threadState != COMPTHREAD_SIGNAL_TERMINATE;
3818
threadState = getCompilationThreadState()
3819
)
3820
{
3821
switch (threadState)
3822
{
3823
case COMPTHREAD_ACTIVE:
3824
{
3825
processEntries();
3826
break;
3827
}
3828
case COMPTHREAD_SIGNAL_WAIT:
3829
{
3830
waitForWork();
3831
break;
3832
}
3833
case COMPTHREAD_SIGNAL_SUSPEND:
3834
{
3835
doSuspend();
3836
break;
3837
}
3838
default:
3839
{
3840
TR_ASSERT(false, "No other state possible here %d\n", getCompilationThreadState());
3841
break;
3842
}
3843
}
3844
}
3845
}
3846
3847
void
3848
TR::CompilationInfoPerThread::waitForWork()
3849
{
3850
TR::CompilationInfo * compInfo = getCompilationInfo();
3851
J9VMThread * compThread = getCompilationThread();
3852
compInfo->debugPrint(compThread, "\tcompilation thread waiting for work\n");
3853
compInfo->debugPrint(compThread, "wait-CM\n");
3854
compInfo->incNumCompThreadsJobless();
3855
setLastTimeThreadWentToSleep(compInfo->getPersistentInfo()->getElapsedTime());
3856
setCompilationThreadState(COMPTHREAD_WAITING);
3857
compInfo->waitOnCompMonitor(compThread);
3858
if (getCompilationThreadState() == COMPTHREAD_WAITING)
3859
{
3860
/*
3861
* If we were signaled to suspend or stop,
3862
* we need to make sure to not lose that information.
3863
*/
3864
setCompilationThreadState(COMPTHREAD_ACTIVE);
3865
}
3866
compInfo->decNumCompThreadsJobless();
3867
compInfo->debugPrint(compThread, "+CM\n");
3868
}
3869
3870
void
3871
TR::CompilationInfoPerThread::doSuspend()
3872
{
3873
_compInfo.setSuspendThreadDueToLowPhysicalMemory(false);
3874
getCompThreadMonitor()->enter();
3875
setCompilationThreadState(COMPTHREAD_SUSPENDED);
3876
_compInfo.releaseCompMonitor(getCompilationThread()); // release the queue monitor before waiting
3877
setLastTimeThreadWasSuspended(_compInfo.getPersistentInfo()->getElapsedTime());
3878
setVMThreadNameWithFlag(getCompilationThread(), getCompilationThread(), getSuspendedThreadName(), 1);
3879
getCompThreadMonitor()->wait(); // wait here until someone notifies us
3880
setVMThreadNameWithFlag(getCompilationThread(), getCompilationThread(), getActiveThreadName(), 1);
3881
getCompThreadMonitor()->exit();
3882
_compInfo.acquireCompMonitor(getCompilationThread());
3883
}
3884
3885
J9::J9SegmentCache
3886
TR::CompilationInfoPerThread::initializeSegmentCache(J9::J9SegmentProvider &segmentProvider)
3887
{
3888
#if defined(J9VM_OPT_JITSERVER)
3889
if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() != JITServer::CLIENT)
3890
#endif /* defined(J9VM_OPT_JITSERVER) */
3891
{
3892
try
3893
{
3894
J9::J9SegmentCache segmentCache(1 << 24, segmentProvider);
3895
return segmentCache;
3896
}
3897
catch (const std::bad_alloc &allocationFailure)
3898
{
3899
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
3900
{
3901
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Failed to initialize segment cache of size 1 << 24");
3902
}
3903
}
3904
}
3905
try
3906
{
3907
J9::J9SegmentCache segmentCache(1 << 21, segmentProvider);
3908
return segmentCache;
3909
}
3910
catch (const std::bad_alloc &allocationFailure)
3911
{
3912
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
3913
{
3914
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Failed to initialize segment cache of size 1 << 21");
3915
}
3916
}
3917
J9::J9SegmentCache segmentCache(1 << 16, segmentProvider);
3918
return segmentCache;
3919
}
3920
3921
void
3922
TR::CompilationInfoPerThread::processEntries()
3923
{
3924
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
3925
{
3926
TR_VerboseLog::writeLineLocked(
3927
TR_Vlog_DISPATCH,
3928
"Starting to process queue entries. compThreadID=%d state=%d Q_SZ=%d Q_SZI=%d QW=%d\n",
3929
getCompThreadId(),
3930
getCompilationThreadState(),
3931
_compInfo.getMethodQueueSize(),
3932
_compInfo.getNumQueuedFirstTimeCompilations(),
3933
_compInfo.getQueueWeight()
3934
);
3935
}
3936
// Possible scenarios here
3937
// 1. We take a method from queue and compile it
3938
// 2. We refrain to take a method from queue because that means two simultaneous compilations --> wait to be notified
3939
// 3. We refrain to take a method from queue because compilation consumes too much CPU.
3940
// 3.1 If there is another active comp thread, then suspend this one. The activation should be avoided in this situation
3941
// 3.2 If this is the last active comp thread, wait on the comp monitor timed.
3942
// Note: the diagnostic thread must not wait.
3943
TR::CompilationInfo *compInfo = getCompilationInfo();
3944
J9VMThread * compThread = getCompilationThread();
3945
try
3946
{
3947
J9::SegmentAllocator scratchSegmentAllocator(MEMORY_TYPE_JIT_SCRATCH_SPACE | MEMORY_TYPE_VIRTUAL, *_jitConfig->javaVM);
3948
J9::J9SegmentCache scratchSegmentCache(initializeSegmentCache(scratchSegmentAllocator).ref());
3949
while (getCompilationThreadState() == COMPTHREAD_ACTIVE)
3950
{
3951
TR::CompilationInfo::TR_CompThreadActions compThreadAction = TR::CompilationInfo::UNDEFINED_ACTION;
3952
TR_MethodToBeCompiled *entry = compInfo->getNextMethodToBeCompiled(this, _previousCompilationThreadState == COMPTHREAD_WAITING, &compThreadAction);
3953
switch (compThreadAction)
3954
{
3955
case TR::CompilationInfo::PROCESS_ENTRY:
3956
{
3957
// Compilation request extracted; go work on it
3958
TR_ASSERT(entry, "Attempting to process NULL entry");
3959
processEntry(*entry, scratchSegmentCache);
3960
break;
3961
}
3962
case TR::CompilationInfo::GO_TO_SLEEP_EMPTY_QUEUE:
3963
{
3964
// This compilation thread goes to sleep because there is no more work to do
3965
if (isDiagnosticThread() && TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseDump))
3966
TR_VerboseLog::writeLineLocked(TR_Vlog_JITDUMP, "Diagnostic thread encountered an empty queue");
3967
3968
setCompilationThreadState(COMPTHREAD_WAITING);
3969
setLastTimeThreadWentToSleep(compInfo->getPersistentInfo()->getElapsedTime());
3970
int64_t waitTimeMillis = 256;
3971
intptr_t monitorStatus = compInfo->waitOnCompMonitorTimed(compThread, waitTimeMillis, 0);
3972
if (getCompilationThreadState() == COMPTHREAD_WAITING)
3973
{
3974
/*
3975
* A status of 0 indicates that 'the monitor has been waited on, notified, and reobtained.'
3976
*/
3977
if (monitorStatus == 0)
3978
/*
3979
* If we were signaled to suspend or stop,
3980
* we need to make sure to not lose that information.
3981
*/
3982
{
3983
setCompilationThreadState(COMPTHREAD_ACTIVE);
3984
}
3985
else
3986
{
3987
TR_ASSERT(monitorStatus == J9THREAD_TIMED_OUT, "Unexpected monitor state");
3988
// It's possible that a notification was sent just after the
3989
// timeout expired. Hence, if something was added to the compilation
3990
// queue we must attempt to process it
3991
if (_compInfo.getMethodQueueSize() > 0)
3992
{
3993
setCompilationThreadState(COMPTHREAD_ACTIVE);
3994
}
3995
else
3996
{
3997
setCompilationThreadState(COMPTHREAD_SIGNAL_WAIT);
3998
}
3999
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
4000
{
4001
TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH, "compThreadID=%d woke up after timeout on compMonitor\n", getCompThreadId());
4002
}
4003
}
4004
}
4005
break;
4006
}
4007
case TR::CompilationInfo::GO_TO_SLEEP_CONCURRENT_EXPENSIVE_REQUESTS:
4008
setCompilationThreadState(COMPTHREAD_SIGNAL_WAIT);
4009
break;
4010
4011
case TR::CompilationInfo::SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT:
4012
case TR::CompilationInfo::SUSPEND_COMP_THREAD_EMPTY_QUEUE:
4013
TR_ASSERT(compInfo->getNumCompThreadsActive() > 1, "Should not suspend the last active compilation thread: %d\n", compInfo->getNumCompThreadsActive());
4014
setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);
4015
compInfo->decNumCompThreadsActive();
4016
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
4017
{
4018
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Suspending compThread %d due to %s Qweight=%d active=%d overallCompCpuUtil=%d",
4019
(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(),
4020
getCompThreadId(),
4021
compThreadAction == TR::CompilationInfo::SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT ? "exceeding CPU entitlement" : "empty queue",
4022
compInfo->getQueueWeight(),
4023
compInfo->getNumCompThreadsActive(),
4024
compInfo->getOverallCompCpuUtilization());
4025
}
4026
break;
4027
4028
case TR::CompilationInfo::THROTTLE_COMP_THREAD_EXCEED_CPU_ENTITLEMENT:
4029
{
4030
TR_ASSERT(compInfo->getNumCompThreadsActive() <= 1, "Throttling when we have several comp threads active: %d\n", compInfo->getNumCompThreadsActive());
4031
int32_t sleepTimeMs = compInfo->computeCompThreadSleepTime(getLastCompilationDuration());
4032
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
4033
{
4034
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u compThread %d sleeping %d ms due to throttling Qweight=%d active=%d overallCompCpuUtil=%d",
4035
(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(),
4036
getCompThreadId(),
4037
sleepTimeMs,
4038
compInfo->getQueueWeight(),
4039
compInfo->getNumCompThreadsActive(),
4040
compInfo->getOverallCompCpuUtilization());
4041
}
4042
compInfo->debugPrint(compThread, "\tcompilation thread waiting some time\n");
4043
compInfo->debugPrint(compThread, "wait-CM\n");
4044
// Don't increment jobless here because there is work to be done
4045
// The thread will wake up after specified time and process the request at front of queue
4046
setCompilationThreadState(COMPTHREAD_WAITING);
4047
setLastTimeThreadWentToSleep(compInfo->getPersistentInfo()->getElapsedTime());
4048
intptr_t monitorStatus = compInfo->waitOnCompMonitorTimed(compThread, sleepTimeMs, 0);
4049
if (getCompilationThreadState() == COMPTHREAD_WAITING)
4050
{
4051
/*
4052
* If we were signaled to suspend or stop,
4053
* we need to make sure to not lose that information.
4054
*/
4055
setCompilationThreadState(COMPTHREAD_ACTIVE);
4056
}
4057
compInfo->debugPrint(compThread, "+CM\n");
4058
}
4059
break;
4060
4061
default:
4062
TR_ASSERT_FATAL(false, "Invalid action: %d\n", compThreadAction);
4063
break;
4064
}
4065
}
4066
}
4067
catch (const std::bad_alloc &allocationFailure)
4068
{
4069
TR_ASSERT(!TR::Compiler->host.is64Bit() ,"Virtual memory exhaustion is unexpected on 64 bit platforms.");
4070
compInfo->setRampDownMCT();
4071
if (compInfo->getNumCompThreadsActive() > 1)
4072
{
4073
if (compilationThreadIsActive())
4074
{
4075
setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);
4076
compInfo->decNumCompThreadsActive();
4077
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompilationThreads, TR_VerbosePerformance))
4078
{
4079
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u Suspending compilation thread %d due to insufficient resources",
4080
(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(), getCompThreadId());
4081
}
4082
}
4083
}
4084
else
4085
{
4086
/*
4087
* Even the last compilation thread could not allocate an initial segment
4088
* Memory is hopelessly fragmented: stop all compilations
4089
*/
4090
compInfo->getPersistentInfo()->setDisableFurtherCompilation(true);
4091
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompilationThreads, TR_VerbosePerformance, TR_VerboseCompFailure))
4092
{
4093
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u Disable further compilation due to OOM while processing compile entries", (uint32_t)compInfo->getPersistentInfo()->getElapsedTime());
4094
}
4095
compInfo->purgeMethodQueue(compilationVirtualAddressExhaustion);
4096
// Must change the state to prevent an infinite loop
4097
// Change it to COMPTHREAD_SIGNAL_WAIT because the compilation queue is empty
4098
setCompilationThreadState(COMPTHREAD_SIGNAL_WAIT);
4099
}
4100
}
4101
#if defined(J9VM_OPT_JITSERVER)
4102
static bool enableJITServerPerCompConn = feGetEnv("TR_EnableJITServerPerCompConn") ? true : false;
4103
if (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT && !enableJITServerPerCompConn)
4104
{
4105
JITServer::ClientStream *client = getClientStream();
4106
if (client)
4107
{
4108
// Inform the server that client is closing the connection with a connectionTerminate message
4109
if (JITServerHelpers::isServerAvailable())
4110
{
4111
try
4112
{
4113
client->writeError(JITServer::MessageType::connectionTerminate, 0 /* placeholder */);
4114
}
4115
catch (const JITServer::StreamFailure &e)
4116
{
4117
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
4118
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "JITServer StreamFailure when sending connectionTerminate: %s", e.what());
4119
}
4120
}
4121
4122
client->~ClientStream();
4123
TR_Memory::jitPersistentFree(client);
4124
setClientStream(NULL);
4125
}
4126
}
4127
#endif /* defined(J9VM_OPT_JITSERVER) */
4128
}
4129
4130
void
4131
TR::CompilationInfoPerThread::processEntry(TR_MethodToBeCompiled &entry, J9::J9SegmentProvider &scratchSegmentProvider)
4132
{
4133
TR::CompilationInfo *compInfo = getCompilationInfo();
4134
J9VMThread *compThread = getCompilationThread();
4135
TR::IlGeneratorMethodDetails & details = entry.getMethodDetails();
4136
J9Method *method = details.getMethod();
4137
4138
setMethodBeingCompiled(&entry); // must have compilation monitor
4139
4140
// Increase main queue weight while still holding compilation monitor
4141
if (entry._reqFromSecondaryQueue || entry._reqFromJProfilingQueue)
4142
compInfo->increaseQueueWeightBy(entry._weight);
4143
4144
compInfo->printQueue();
4145
4146
entry._compInfoPT = this; // need to know which comp thread is handling this request
4147
4148
// update the last time the compilation thread had to do something.
4149
compInfo->setLastReqStartTime(compInfo->getPersistentInfo()->getElapsedTime());
4150
4151
// Update how many compilation threads are working on hot/scorching methods
4152
if (entry._weight >= TR::Options::_expensiveCompWeight)
4153
{
4154
compInfo->incNumCompThreadsCompilingHotterMethods(); // must be called with compMonitor in hand
4155
entry._hasIncrementedNumCompThreadsCompilingHotterMethods = true;
4156
}
4157
4158
// Now we no longer need the monitor - it is not held during compilation
4159
//
4160
compInfo->debugPrint(compThread, "\tcompilation thread releasing monitor before compile\n");
4161
compInfo->debugPrint(compThread, "-CM\n");
4162
compInfo->releaseCompMonitor(compThread);
4163
4164
// We cannot examine the fields of method because it might have been unloaded
4165
// First we need to acquire VM access or prevent unloading
4166
//
4167
// Acquire VM access
4168
//
4169
acquireVMAccessNoSuspend(compThread);
4170
compInfo->debugPrint(compThread, "+VMacc\n");
4171
4172
// If GC is in the middle of a duty cycle, wait for the cycle to finish
4173
// This is for RealTime only. Note that we need to perform this operation with VMAccess
4174
// in hand. Otherwise, after the comp thread has found that GC is not active but before
4175
// it acquires VM access, the GC could start a cycle and decide to unload a method
4176
// which will be later pinned by the compilation thread. The problem is that in realtime
4177
// GC does not execute all the work atomically. It may decide to unload some classes now,
4178
// then pause for a while, then coming back and doing the actual unloading without
4179
// verifying again that the class has been pinned
4180
//
4181
if (TR::Options::getCmdLineOptions()->realTimeGC())
4182
waitForGCCycleMonitor(true); // the parameter indicates that the thread has VM access
4183
4184
if (!shouldPerformCompilation(entry))
4185
{
4186
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
4187
{
4188
TR_VerboseLog::writeLineLocked(
4189
TR_Vlog_DISPATCH,
4190
"Rejecting compilation request for j9m=%p. unloaded=%d fromJPQ=%d",
4191
entry.getMethodDetails().getMethod(), entry._unloadedMethod, entry._reqFromJProfilingQueue);
4192
}
4193
4194
// Acquire compilation monitor
4195
//
4196
compInfo->debugPrint(compThread, "\tacquiring compilation monitor\n");
4197
compInfo->acquireCompMonitor(compThread);
4198
compInfo->debugPrint(compThread, "+CM\n");
4199
4200
// Release VM access
4201
//
4202
compInfo->debugPrint(compThread, "\tcompilation thread releasing VM access\n");
4203
releaseVMAccess(compThread);
4204
compInfo->debugPrint(compThread, "-VMacc\n");
4205
// decrease the queue weight
4206
compInfo->decreaseQueueWeightBy(entry._weight);
4207
// Update how many compilation threads are working on hot/scorching methods
4208
if (entry._hasIncrementedNumCompThreadsCompilingHotterMethods)
4209
compInfo->decNumCompThreadsCompilingHotterMethods();
4210
4211
// put the request back into the pool
4212
//
4213
setMethodBeingCompiled(NULL); // Must have the compQmonitor
4214
compInfo->recycleCompilationEntry(&entry);
4215
4216
// there are no threads to be notified because either this is an async request
4217
// or a sync request where classes have been redefined in which case the jit hook will to the signalling
4218
return;
4219
}
4220
4221
// Pin the class of the method being compiled to prevent it from being unloaded
4222
//
4223
// This conversion is safe. The macro J9VM_J9CLASS_TO_HEAPCLASS will not make a conversion if Classes on Heap is not enabled.
4224
jobject classObject = NULL;
4225
if (!entry.isOutOfProcessCompReq())
4226
classObject = compThread->javaVM->internalVMFunctions->j9jni_createLocalRef((JNIEnv*)compThread, J9VM_J9CLASS_TO_HEAPCLASS(details.getClass()));
4227
4228
// Do the hack for newInstance thunks
4229
// Also make the method appear as interpreted, otherwise we might want to access recompilation info
4230
// FIXME: do this more elegantly
4231
//
4232
//TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();
4233
if (details.isNewInstanceThunk())
4234
{
4235
J9::NewInstanceThunkDetails &newInstanceDetails = static_cast<J9::NewInstanceThunkDetails &>(details);
4236
J9Class *classForNewInstance = newInstanceDetails.classNeedingThunk();
4237
TR::CompilationInfo::setJ9MethodExtra(method,(uintptr_t)classForNewInstance | J9_STARTPC_NOT_TRANSLATED);
4238
}
4239
4240
#ifdef STATS
4241
statQueueSize.update(compInfo->getMethodQueueSize());
4242
#endif
4243
TR_ASSERT(entry._optimizationPlan, "Must have an optimization plan");
4244
4245
// The server should not adjust the opt plan requested by the client.
4246
if (!entry.isOutOfProcessCompReq())
4247
TR::CompilationController::getCompilationStrategy()->adjustOptimizationPlan(&entry, 0);
4248
4249
entry._tryCompilingAgain = false; // this field may be set by compile()
4250
4251
// The following call will return with compilation monitor and the
4252
// queue slot (entry) monitor in hand
4253
//
4254
void *startPC = compile(compThread, &entry, scratchSegmentProvider);
4255
4256
// We have acquired VM access above and will be releasing it below. It is possible however that during the
4257
// compilation process in the above `compile(...)` call we have released VM access and have subsequently
4258
// crashed or asserted. In such a scenario the JitDump process will have started and queued the method
4259
// for recompilation with a custom signal handler to catch the crash/assertion and return. The JitDump
4260
// compilation will have hopefully crashed/asserted in the same place as the original compilation, and
4261
// thus we will not be holding VM access at that point. This means we will return from the above call to
4262
// `compile(...)` without holding VM access, and below we will attempt to call `j9jni_deleteLocalRef` to
4263
// unpin the class. The `j9jni_deleteLocalRef` function has a requirement that we hold VM access otherwise
4264
// it will assert. We do not want to assert, as that will end up calling `abort()` and the JitDump process
4265
// will not complete, nor will any dump handlers following JitDump.
4266
if ((compThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS) == 0)
4267
{
4268
TR_ASSERT_FATAL(isDiagnosticThread(), "A compilation thread has finished a compilation but does not hold VM access");
4269
4270
acquireVMAccessNoSuspend(compThread);
4271
compInfo->debugPrint(compThread, "+VMacc\n");
4272
}
4273
4274
// Unpin the class
4275
if (!entry.isOutOfProcessCompReq())
4276
compThread->javaVM->internalVMFunctions->j9jni_deleteLocalRef((JNIEnv*)compThread, classObject);
4277
4278
// Update how many compilation threads are working on hot/scorching methods
4279
if (entry._hasIncrementedNumCompThreadsCompilingHotterMethods)
4280
compInfo->decNumCompThreadsCompilingHotterMethods();
4281
4282
entry._newStartPC = startPC;
4283
4284
if (startPC && startPC != entry._oldStartPC)
4285
{
4286
compInfo->debugPrint("\tcompilation succeeded for method", details, compThread);
4287
// Add upgrade request to secondary queue if we downgraded, this is not GCR and method
4288
// looks important enough that an upgrade is justified
4289
if (entry._compErrCode == compilationOK)
4290
{
4291
if (entry._optimizationPlan->shouldAddToUpgradeQueue())
4292
{
4293
// clone this request, adjust its _oldStartPC to match the _newStartPC for the
4294
// this request, and insert it in the low upgrade queue
4295
compInfo->getLowPriorityCompQueue().addUpgradeReqToLPQ(getMethodBeingCompiled(), TR_MethodToBeCompiled::REASON_UPGRADE);
4296
#ifdef STATS
4297
fprintf(stderr, "Downgraded request will be added to upgrade queue\n");
4298
#endif
4299
}
4300
#if defined(J9VM_OPT_JITSERVER)
4301
else if (entry.shouldUpgradeOutOfProcessCompilation())
4302
{
4303
// If it's a local cold downgraded compilation, add an upgrade request to the LPQ, hoping that
4304
// the server will become available at some point in the future
4305
if (TR::Options::isAnyVerboseOptionSet(
4306
TR_VerboseJITServer,
4307
TR_VerboseCompilationDispatch,
4308
TR_VerbosePerformance,
4309
TR_VerboseCompFailure))
4310
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "t=%6u Buffering an upgrade request into the LPQ: j9method=%p",
4311
(uint32_t) compInfo->getPersistentInfo()->getElapsedTime(),
4312
entry.getMethodDetails().getMethod());
4313
compInfo->getLowPriorityCompQueue().addUpgradeReqToLPQ(getMethodBeingCompiled(), TR_MethodToBeCompiled::REASON_SERVER_UNAVAILABLE);
4314
}
4315
#endif
4316
}
4317
}
4318
else // compilation failure
4319
{
4320
compInfo->debugPrint("\tcompilation failed for method", details, compThread);
4321
}
4322
// Update statistics regarding the compilation status (including compilationOK)
4323
compInfo->updateCompilationErrorStats((TR_CompilationErrorCode)entry._compErrCode);
4324
4325
// Copy this because it is needed later and entry may be recycled
4326
bool tryCompilingAgain = entry._tryCompilingAgain;
4327
4328
if (entry._tryCompilingAgain)
4329
{
4330
// We got interrupted during the compile, and want to requeue this compilation request
4331
//
4332
TR_ASSERT(!entry._unloadedMethod, "For unloaded methods, it should not be possible to try compiling again");
4333
4334
CompilationPriority oldPriority = (CompilationPriority)entry._priority;
4335
if (oldPriority <= CP_ASYNC_MAX)
4336
{
4337
oldPriority = CP_ASYNC_MAX;
4338
// While we increased the priority of this request, there might be a SYNC request in the queue
4339
// which has higher priority. In that case we should remove the possible reservation of a dataCache
4340
if (reservedDataCache() && compInfo->getMethodQueue() && compInfo->getMethodQueue()->_priority >= CP_ASYNC_MAX)
4341
{
4342
TR_DataCacheManager::getManager()->makeDataCacheAvailable(reservedDataCache());
4343
setReservedDataCache(NULL);
4344
}
4345
}
4346
else
4347
{
4348
oldPriority = CP_SYNC_BELOW_MAX;
4349
}
4350
4351
entry._priority = oldPriority;
4352
--entry._compilationAttemptsLeft;
4353
entry._hasIncrementedNumCompThreadsCompilingHotterMethods = false; // re-initialize
4354
entry._GCRrequest = false; // pretend it's not GCR
4355
entry._reqFromSecondaryQueue = TR_MethodToBeCompiled::REASON_NONE; // we are going to put this into the main queue, so entry is not coming from LPQ anymore
4356
// TODO: the following is needed or otherwise we will wrongly increase the Q weight when extracting it again
4357
// However, we lose our _reqFromJProfilingQueue flag so we will not insert profiling trees
4358
// We need some other form of flag, maybe in the optimization plan or
4359
// retrials of compilations from JPQ are not going to work correctly
4360
entry._reqFromJProfilingQueue = false;
4361
#if defined(J9VM_OPT_JITSERVER)
4362
entry.unsetRemoteCompReq(); // remote compilation decisions do not carry over from one retrial to the next
4363
#endif
4364
4365
compInfo->debugPrint("\trequeueing interrupted compilation request", details, compThread);
4366
4367
// After releasing the monitors and vm access below, we will loop back to the head of the loop, and retry the
4368
// compilation. Do not put the request back into the pool, instead requeue.
4369
//
4370
requeue();
4371
setMethodBeingCompiled(NULL); // Must have the compQmonitor
4372
}
4373
else // compilation will not be retried
4374
{
4375
TR_OptimizationPlan::freeOptimizationPlan(entry._optimizationPlan); // we no longer need the optimization plan
4376
// decrease the queue weight
4377
compInfo->decreaseQueueWeightBy(entry._weight);
4378
// Put the request back into the pool
4379
setMethodBeingCompiled(NULL);
4380
compInfo->recycleCompilationEntry(&entry);
4381
4382
// notify the sleeping threads that the compilation request has been served
4383
// (either it succeeded or it failed and we are not going to requeue).
4384
//
4385
compInfo->debugPrint(compThread, "\tnotify sleeping threads that the compilation is done\n");
4386
entry.getMonitor()->notifyAll();
4387
compInfo->debugPrint(compThread, "ntfy-", &entry);
4388
}
4389
4390
compInfo->printQueue();
4391
4392
// Release the queue slot monitor
4393
//
4394
compInfo->debugPrint(compThread, "\tcompilation thread releasing queue slot monitor\n");
4395
compInfo->debugPrint(compThread, "-AM-", &entry);
4396
entry.releaseSlotMonitor(compThread);
4397
4398
// At this point we should always have VMAccess
4399
// We should always have the compilation monitor
4400
// we should never have classUnloadMonitor
4401
4402
// Release VM access
4403
//
4404
compInfo->debugPrint(compThread, "\tcompilation thread releasing VM access\n");
4405
releaseVMAccess(compThread);
4406
compInfo->debugPrint(compThread, "-VMacc\n");
4407
// We can suspend this thread if too many are active
4408
if (
4409
!isDiagnosticThread() // must not be reserved for log
4410
&& compInfo->getNumCompThreadsActive() > 1 // we should have at least one active besides this one
4411
&& compilationThreadIsActive() // We haven't already been signaled to suspend or terminate
4412
&& (
4413
compInfo->getRampDownMCT() // force to have only one thread active
4414
|| compInfo->getSuspendThreadDueToLowPhysicalMemory()
4415
|| (
4416
!tryCompilingAgain
4417
/*&& compInfoPT->getCompThreadId() != 0*/
4418
&& TR::Options::getCmdLineOptions()->getOption(TR_SuspendEarly)
4419
&& compInfo->getQueueWeight() < TR::CompilationInfo::getCompThreadSuspensionThreshold(compInfo->getNumCompThreadsActive())
4420
)
4421
#if defined(J9VM_OPT_JITSERVER)
4422
|| (compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT
4423
&& compInfo->getCompThreadActivationPolicy() == JITServer::CompThreadActivationPolicy::SUSPEND) // keep suspending threads until server space frees up
4424
#endif
4425
)
4426
)
4427
{
4428
// Suspend this thread
4429
setCompilationThreadState(COMPTHREAD_SIGNAL_SUSPEND);
4430
compInfo->decNumCompThreadsActive();
4431
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
4432
{
4433
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Suspend compThread %d Qweight=%d active=%d %s %s %s",
4434
(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(),
4435
getCompThreadId(),
4436
compInfo->getQueueWeight(),
4437
compInfo->getNumCompThreadsActive(),
4438
compInfo->getRampDownMCT() ? "RampDownMCT" : "",
4439
compInfo->getSuspendThreadDueToLowPhysicalMemory() ? "LowPhysicalMem" : "",
4440
#if defined(J9VM_OPT_JITSERVER)
4441
compInfo->getCompThreadActivationPolicy() == JITServer::CompThreadActivationPolicy::SUSPEND ? "ServerLowPhysicalMemOrHighThreadCount" :
4442
#endif
4443
""
4444
);
4445
}
4446
// If the other remaining active thread(s) are sleeping (maybe because
4447
// we wanted to avoid two concurrent hot requests) we need to wake them
4448
// now as a preventive measure. Worst case scenario they will go back to sleep
4449
if (compInfo->getNumCompThreadsJobless() > 0)
4450
{
4451
compInfo->getCompilationMonitor()->notifyAll();
4452
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
4453
{
4454
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u compThread %d notifying other sleeping comp threads. Jobless=%d",
4455
(uint32_t)compInfo->getPersistentInfo()->getElapsedTime(),
4456
getCompThreadId(),
4457
compInfo->getNumCompThreadsJobless());
4458
}
4459
}
4460
if (tryCompilingAgain)
4461
{
4462
// For compilation retrial we normally keep the data cache
4463
// Because another thread may handle the request we have to unreserve any data cache
4464
if (reservedDataCache())
4465
{
4466
TR_DataCacheManager::getManager()->makeDataCacheAvailable(reservedDataCache());
4467
setReservedDataCache(NULL);
4468
// TODO: write a message into the trace buffer because this is a corner case
4469
}
4470
}
4471
}
4472
else // We will not suspend this thread
4473
{
4474
// If the low memory flag was set but there was no additional comp thread
4475
// to suspend, we must clear the flag now
4476
if (compInfo->getSuspendThreadDueToLowPhysicalMemory() &&
4477
compInfo->getNumCompThreadsActive() < 2)
4478
compInfo->setSuspendThreadDueToLowPhysicalMemory(false);
4479
}
4480
}
4481
4482
bool
4483
TR::CompilationInfoPerThread::shouldPerformCompilation(TR_MethodToBeCompiled &entry)
4484
{
4485
if (entry.isOutOfProcessCompReq())
4486
return true;
4487
TR::CompilationInfo *compInfo = getCompilationInfo();
4488
TR::IlGeneratorMethodDetails &details = entry.getMethodDetails();
4489
J9Method *method = details.getMethod();
4490
4491
// Do not compile unloaded methods
4492
if (entry._unloadedMethod)
4493
return false;
4494
4495
// Do not compile replaced methods
4496
if ((TR::Options::getCmdLineOptions()->getOption(TR_EnableHCR) || TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug))
4497
&& details.getClass() && J9_IS_CLASS_OBSOLETE(details.getClass()))
4498
return false;
4499
4500
4501
if (entry._reqFromSecondaryQueue)
4502
{
4503
// This is a request coming from the low priority queue
4504
bool doCompile = false;
4505
4506
// Determine if this was a fast comp req for an interpreted method
4507
if (!entry._oldStartPC)
4508
{
4509
// Set method->extra = J9_JIT_QUEUED_FOR_COMPILATION
4510
// and stimulate a compilation (if conditions are right)
4511
if (!(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers & J9AccNative)) // never change the extra field of a native method
4512
{
4513
if (!TR::CompilationInfo::isCompiled(method)) // Don't touch methods compiled through other means
4514
{
4515
if (compInfo->getInvocationCount(method) > 0) // Valid invocation counter
4516
{
4517
// FIXME: is this safe here?
4518
// What if the method is about to be compiled?
4519
compInfo->setJ9MethodVMExtra(method, J9_JIT_QUEUED_FOR_COMPILATION);
4520
doCompile = true;
4521
}
4522
}
4523
else // compiled body
4524
{
4525
compInfo->getLowPriorityCompQueue().incStatsBypass(); // statistics
4526
}
4527
}
4528
// stop tracking this method in the hashtable
4529
if (compInfo->getLowPriorityCompQueue().isTrackingEnabled())
4530
compInfo->getLowPriorityCompQueue().stopTrackingMethod(method);
4531
}
4532
else // RE-compilation request from LPQ
4533
{
4534
TR_ASSERT(entry._reqFromSecondaryQueue == TR_MethodToBeCompiled::REASON_UPGRADE, "wrong reason for upgrade");
4535
// This method might have failed compilation or have been rejected due to filters
4536
void *startPC = TR::CompilationInfo::getPCIfCompiled(method);
4537
if (startPC)
4538
{
4539
// A compilation attempt might have already happened for this method
4540
// (and failed or succeeded)
4541
J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(startPC);
4542
if (!linkageInfo->isBeingCompiled()) // This field is never reset
4543
{
4544
// get its level
4545
TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(startPC);
4546
// The method might have already been recompiled
4547
// Or a compilation request might have been attempted and failed. The linkage
4548
// word could tell us if this body has ever been queued for compilation
4549
4550
if (bodyInfo && bodyInfo->getHotness() < warm)
4551
{
4552
doCompile = true;
4553
linkageInfo->setIsBeingRecompiled();
4554
TR_PersistentMethodInfo *methodInfo = bodyInfo->getMethodInfo();
4555
// adjust the level in persistentMethodInfo as well
4556
methodInfo->setNextCompileLevel(entry._optimizationPlan->getOptLevel(), false);
4557
// set the reason for recompilation
4558
methodInfo->setReasonForRecompilation(TR_PersistentMethodInfo::RecompDueToSecondaryQueue);
4559
}
4560
}
4561
else
4562
{
4563
compInfo->getLowPriorityCompQueue().incStatsBypass(); // statistics
4564
}
4565
}
4566
else
4567
{
4568
// This case corresponds to a situation where we had a downgraded first time compilation
4569
// into the main queue and an upgrade into the LPQ. The request from the main queue fails
4570
// and we now have to execute the upgrade.
4571
// Do not do it
4572
}
4573
}
4574
if (!doCompile)
4575
return false;
4576
}
4577
else if (entry._reqFromJProfilingQueue)
4578
{
4579
// We should not compile a request from JProfiling queue if the method has been
4580
// recompiled since we put this request in the JPQ. Our expectation is that
4581
// the current startPC is entry->_oldStartPC
4582
void *startPC = TR::CompilationInfo::getJ9MethodStartPC(method);
4583
if (startPC != entry._oldStartPC)
4584
return false;
4585
4586
// A compilation request might have been attempted and failed. The linkage
4587
// word could tell us if this body has ever been queued for compilation
4588
J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(startPC);
4589
if (linkageInfo->isBeingCompiled()) // This field is never reset
4590
return false;
4591
linkageInfo->setIsBeingRecompiled();
4592
TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(startPC);
4593
// bodyInfo must exist because requests from JQP are always recompilations
4594
TR_PersistentMethodInfo *methodInfo = bodyInfo->getMethodInfo();
4595
// set the reason for recompilation
4596
methodInfo->setReasonForRecompilation(TR_PersistentMethodInfo::RecompDueToJProfiling);
4597
// adjust the level in persistentMethodInfo as well
4598
methodInfo->setNextCompileLevel(entry._optimizationPlan->getOptLevel(), false);
4599
}
4600
return true;
4601
}
4602
4603
TR_MethodToBeCompiled *
4604
TR::CompilationInfo::addMethodToBeCompiled(TR::IlGeneratorMethodDetails & details, void *pc,
4605
CompilationPriority priority, bool async,
4606
TR_OptimizationPlan *optimizationPlan, bool *queued,
4607
TR_YesNoMaybe methodIsInSharedCache)
4608
{
4609
// Make sure the entry is consistent
4610
//
4611
#if DEBUG
4612
if (pc)
4613
{
4614
TR_PersistentMethodInfo* methodInfo = TR::Recompilation::getMethodInfoFromPC(pc);
4615
if (methodInfo)
4616
TR_ASSERT(details.getMethod() == (J9Method *)methodInfo->getMethodInfo(), "assertion failure");
4617
}
4618
#endif
4619
4620
// Add this method to the queue of methods waiting to be compiled.
4621
TR_MethodToBeCompiled *cur = NULL, *prev = NULL;
4622
uint32_t queueWeight = 0; // QW
4623
int32_t numEntries = 0;
4624
4625
// See if the method is already in the queue or is already being compiled
4626
//
4627
J9VMThread *vmThread = _jitConfig->javaVM->internalVMFunctions->currentVMThread(_jitConfig->javaVM);
4628
TR_J9VMBase * fe = TR_J9VMBase::get(_jitConfig, vmThread);
4629
4630
// search among the threads
4631
for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)
4632
{
4633
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
4634
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
4635
4636
TR_MethodToBeCompiled *compMethod = curCompThreadInfoPT->getMethodBeingCompiled();
4637
if (compMethod)
4638
{
4639
queueWeight += compMethod->_weight; // QW
4640
if (compMethod->getMethodDetails().sameAs(details, fe))
4641
{
4642
if (!compMethod->_unloadedMethod) // Redefinition; see cmvc 192606 and RTC 36898
4643
{
4644
// If the priority has increased, use the new priority.
4645
//
4646
if (compMethod->_priority < priority)
4647
compMethod->_priority = priority;
4648
return compMethod;
4649
}
4650
}
4651
}
4652
}
4653
4654
J9Method *method = details.getMethod();
4655
4656
// Ordinary, non-JNI methods that are interpreted have their 'j9method->extra' field
4657
// set to J9_JIT_QUEUED_FOR_COMPILATION when they are added to the queue
4658
// Thus, we can skip searching the queue if j9method->extra has another value
4659
// However, sync compilations do not set method->extra to J9_JIT_QUEUED_FOR_COMPILATION
4660
bool skipSearchingForDuplicates = false;
4661
static char *disableSkipSearching = feGetEnv("TR_DisableSkipSearchingForRequestDuplicates");
4662
if (!disableSkipSearching &&
4663
pc == 0 && // Interpreted methods
4664
details.isOrdinaryMethod() &&
4665
!isJNINative(method) &&
4666
!(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers & J9AccNative) &&
4667
getJ9MethodVMExtra(method) != J9_JIT_QUEUED_FOR_COMPILATION)
4668
{
4669
skipSearchingForDuplicates = true;
4670
}
4671
4672
if (skipSearchingForDuplicates)
4673
{
4674
// In this case we only have to scan the synchronous requests in the queue
4675
for (prev = NULL, cur = _methodQueue; cur; prev = cur, cur = cur->_next)
4676
{
4677
// Stop the search when we finished with sync entries
4678
if (cur->_priority < CP_SYNC_MIN)
4679
{
4680
cur = NULL; // signal that we din't find the entry
4681
break;
4682
}
4683
if (cur->getMethodDetails().sameAs(details, fe))
4684
break;
4685
}
4686
}
4687
else // Scan the entire queue
4688
{
4689
for (prev = NULL, cur = _methodQueue; cur; prev = cur, cur = cur->_next)
4690
{
4691
numEntries++;
4692
queueWeight += cur->_weight;
4693
if (cur->getMethodDetails().sameAs(details, fe))
4694
break;
4695
}
4696
}
4697
4698
// NOTE: we do not need to search the methodPool since we cannot reach here if an entry
4699
// for the compilation of this method is already in the pool. Things are put in the pool
4700
// after the compilation completes and we have updated the J9Method etc.
4701
// in which case the compilation is already done and we should not even try to enqueue
4702
4703
if (cur)
4704
{
4705
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))
4706
TR_VerboseLog::writeLineLocked(TR_Vlog_CR,"%p Already present in compilation queue. OldPriority=%x NewPriority=%x entry=%p",
4707
_jitConfig->javaVM->internalVMFunctions->currentVMThread(_jitConfig->javaVM), cur->_priority, priority, cur);
4708
4709
// Method is already in the queue.
4710
// If the startPC has changed, assume the new one is more recent.
4711
//
4712
if (pc)
4713
cur->_oldStartPC = pc;
4714
4715
// If the priority has increased, use the new priority
4716
//
4717
if (cur->_priority < priority)
4718
cur->_priority = priority;
4719
// If the optimization level is higher, just upgrade
4720
// (unless the methods has excessive complexity)
4721
//
4722
if (cur->_optimizationPlan->getOptLevel() != optimizationPlan->getOptLevel())
4723
{
4724
if (cur->_optimizationPlan->getOptLevel() < optimizationPlan->getOptLevel())
4725
cur->_optimizationPlan->setOptLevel(optimizationPlan->getOptLevel());
4726
if (pc)
4727
{
4728
TR_PersistentMethodInfo *methodInfo = TR::Recompilation::getMethodInfoFromPC(pc);
4729
if (methodInfo && methodInfo->getNextCompileLevel() != cur->_optimizationPlan->getOptLevel())
4730
methodInfo->setNextCompileLevel(cur->_optimizationPlan->getOptLevel(), cur->_optimizationPlan->insertInstrumentation());
4731
}
4732
}
4733
// If the position in the queue is still correct, just return
4734
//
4735
if (!prev || prev->_priority >= cur->_priority)
4736
return cur;
4737
4738
// Must re-position in the queue
4739
//
4740
prev->_next = cur->_next; // take it out of the queue
4741
}
4742
4743
// If method is not yet in the queue prepare the queue entry
4744
//
4745
else
4746
{
4747
// If we skipped searching, we cannot do the validation checks
4748
if (!skipSearchingForDuplicates)
4749
{
4750
if (queueWeight != _queueWeight) //QW
4751
{
4752
if (TR::Options::isAnyVerboseOptionSet())
4753
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "Discrepancy for queue weight while adding to queue: computed=%u recorded=%u\n", queueWeight, _queueWeight);
4754
// correction
4755
_queueWeight = queueWeight;
4756
}
4757
if (numEntries != _numQueuedMethods)
4758
{
4759
if (TR::Options::isAnyVerboseOptionSet())
4760
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "Discrepancy for queue size while adding to queue: Before adding numEntries=%d _numQueuedMethods=%d\n", numEntries, _numQueuedMethods);
4761
TR_ASSERT(false, "Discrepancy for queue size while adding to queue");
4762
}
4763
}
4764
cur = getCompilationQueueEntry();
4765
if (cur == NULL) // Memory Allocation Failure.
4766
return NULL;
4767
4768
cur->initialize(details, pc, priority, optimizationPlan);
4769
cur->_jitStateWhenQueued = getPersistentInfo()->getJitState();
4770
4771
bool isJNINativeMethodRequest = false;
4772
if (pc)
4773
{
4774
J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(pc);
4775
#if defined(OSX) && defined(AARCH64)
4776
pthread_jit_write_protect_np(0);
4777
#endif
4778
linkageInfo->setIsBeingRecompiled(); // mark that we try to compile it
4779
#if defined(OSX) && defined(AARCH64)
4780
pthread_jit_write_protect_np(1);
4781
#endif
4782
4783
// Update persistentMethodInfo with the level we want to compile to
4784
//
4785
TR_PersistentJittedBodyInfo* bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(pc);
4786
TR_ASSERT(bodyInfo, "We must have bodyInfo because we recompile");
4787
TR_PersistentMethodInfo* methodInfo = bodyInfo->getMethodInfo(); //TR::Recompilation::getMethodInfoFromPC(pc);
4788
TR_ASSERT(methodInfo, "We must have methodInfo because we recompile");
4789
methodInfo->setNextCompileLevel(optimizationPlan->getOptLevel(), optimizationPlan->insertInstrumentation());
4790
// check if this is an invalidation request and if so increase the appropriate counter
4791
//
4792
if (bodyInfo->getIsInvalidated())
4793
incNumInvRequestsQueued(cur);
4794
4795
// Increment this only if recompilations are due to sampling
4796
if (linkageInfo->isSamplingMethodBody())
4797
{
4798
if (methodInfo->getReasonForRecompilation() != TR_PersistentMethodInfo::RecompDueToGCR)
4799
_intervalStats._numRecompilationsInInterval++;
4800
else
4801
incNumGCRRequestsQueued(cur);
4802
}
4803
// Should we bump the count of first time compilations?
4804
// If not, the danger is that there will be many GCR compilations and we enter STEADY state
4805
}
4806
else if (details.isOrdinaryMethod()) // ordinary interpreted methods
4807
{
4808
isJNINativeMethodRequest = isJNINative(method);
4809
if (async
4810
&& (getInvocationCount(method) == 0) // this will filter out JNI natives
4811
&& !(J9_ROM_METHOD_FROM_RAM_METHOD(method)->modifiers & J9AccNative)) // Never change the extra field of a native method
4812
{
4813
setJ9MethodVMExtra(method, J9_JIT_QUEUED_FOR_COMPILATION);
4814
}
4815
_intervalStats._numFirstTimeCompilationsInInterval++;
4816
_numQueuedFirstTimeCompilations++;
4817
}
4818
cur->_entryTime = getPersistentInfo()->getElapsedTime(); // cheaper version
4819
#if defined(J9VM_INTERP_AOT_RUNTIME_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))
4820
cur->_methodIsInSharedCache = methodIsInSharedCache;
4821
#endif
4822
incrementMethodQueueSize(); // one more method added to the queue
4823
*queued = true; // set the flag that we added a new request to the queue
4824
4825
Trc_JIT_CompRequest(vmThread, method, pc, !async, optimizationPlan->getOptLevel(), (int)priority, _numQueuedMethods);
4826
4827
// Increase the queue weight
4828
uint8_t entryWeight; // must be less than 256
4829
if (!details.isOrdinaryMethod() || details.isNewInstanceThunk() || isJNINativeMethodRequest)
4830
entryWeight = THUNKS_WEIGHT; // 1
4831
else if (methodIsInSharedCache == TR_yes && !pc) // first time compilations that are AOT loads
4832
entryWeight = TR::Options::_weightOfAOTLoad;
4833
else if (optimizationPlan->getOptLevel() == warm) // most common case first
4834
{
4835
// Compilation may be downgraded to cold during classLoadPhase
4836
// While we cannot anticipate that classLoadPhase will last till the method
4837
// is extracted from the queue, this is the best estimate
4838
if (TR::CompilationInfo::isJSR292(method))
4839
{
4840
entryWeight = (uint32_t)TR::Options::_weightOfJSR292;
4841
}
4842
else if (getPersistentInfo()->isClassLoadingPhase() && !isCompiled(method) &&
4843
!TR::Options::getCmdLineOptions()->getOption(TR_DontDowngradeToCold) &&
4844
TR::Options::getCmdLineOptions()->allowRecompilation()) // don't do it for fixed level
4845
{
4846
entryWeight = COLD_WEIGHT;
4847
}
4848
else
4849
{
4850
// Smaller methods are easier to compile
4851
J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
4852
uint32_t methodSize = getMethodBytecodeSize(romMethod);
4853
4854
if (methodSize < 8)
4855
{
4856
entryWeight = COLD_WEIGHT;
4857
}
4858
else
4859
{
4860
// Loopless methods are easier to compile
4861
if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))
4862
entryWeight = WARM_LOOPY_WEIGHT;
4863
else
4864
entryWeight = WARM_LOOPLESS_WEIGHT;
4865
}
4866
}
4867
}
4868
else if (optimizationPlan->getOptLevel() == cold)
4869
entryWeight = COLD_WEIGHT;
4870
else if (optimizationPlan->getOptLevel() >= veryHot)
4871
entryWeight = VERY_HOT_WEIGHT;
4872
else if (optimizationPlan->getOptLevel() == hot)
4873
entryWeight = HOT_WEIGHT;
4874
else if (optimizationPlan->getOptLevel() == noOpt)
4875
entryWeight = NOOPT_WEIGHT;
4876
else
4877
{
4878
entryWeight = THUNKS_WEIGHT;
4879
TR_ASSERT(false, "Unknown hotness level %d\n", optimizationPlan->getOptLevel());
4880
}
4881
4882
// Other tweaks go here: method size, profiling bodies, loopy/loopless, classLoadPhase, sync/async
4883
cur->_weight = entryWeight;
4884
increaseQueueWeightBy(entryWeight);
4885
4886
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))
4887
TR_VerboseLog::writeLineLocked(TR_Vlog_CR, "%p Added entry %p of weight %d to comp queue. Now Q_SZ=%d weight=%d",
4888
_jitConfig->javaVM->internalVMFunctions->currentVMThread(_jitConfig->javaVM), cur, entryWeight, getMethodQueueSize(), getQueueWeight());
4889
4890
// Examine if we need to activate a new thread
4891
TR_YesNoMaybe activate = shouldActivateNewCompThread();
4892
if (activate == TR_maybe &&
4893
TR::Options::getCmdLineOptions()->getOption(TR_ActivateCompThreadWhenHighPriReqIsBlocked) &&
4894
getNumCompThreadsActive() == 1 &&
4895
priority >= CP_ASYNC_BELOW_MAX) // AOT loads and JNI
4896
{
4897
TR::CompilationInfoPerThread * lowPriCompThread = findFirstLowPriorityCompilationInProgress(priority);
4898
if (lowPriCompThread)
4899
{
4900
activate = TR_yes;
4901
4902
// Increase the weight of the blocking entry so that the newly activated thread
4903
// remains active until the blocking request gets compiled
4904
//
4905
TR_MethodToBeCompiled *lowPriCompReq = lowPriCompThread->getMethodBeingCompiled();
4906
uint8_t targetWeight = _compThreadSuspensionThresholds[2] <= 0xff ? _compThreadSuspensionThresholds[2] : 0xff;
4907
if (lowPriCompReq->_weight < targetWeight)
4908
{
4909
uint8_t diffWeight = targetWeight - lowPriCompReq->_weight;
4910
increaseQueueWeightBy(diffWeight);
4911
lowPriCompReq->_weight = targetWeight;
4912
}
4913
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
4914
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u High priority req (0x%x) blocked by priority 0x%x",
4915
(uint32_t)getPersistentInfo()->getElapsedTime(), priority, lowPriCompReq->_priority);
4916
}
4917
}
4918
4919
if (activate == TR_yes)
4920
{
4921
// Must find one that is SUSPENDED/SUSPENDING otherwise the logic in shouldActivateNewCompThread is incorrect
4922
TR::CompilationInfoPerThread *compInfoPT = getFirstSuspendedCompilationThread();
4923
4924
TR_ASSERT_FATAL(compInfoPT != NULL, "Could not find a suspended/suspending compilation thread");
4925
4926
compInfoPT->resumeCompilationThread();
4927
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
4928
{
4929
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"t=%6u Activate compThread %d Qweight=%d active=%d",
4930
(uint32_t)getPersistentInfo()->getElapsedTime(),
4931
compInfoPT->getCompThreadId(),
4932
getQueueWeight(),
4933
getNumCompThreadsActive());
4934
}
4935
}
4936
}
4937
4938
// Move the entry to the right place in the queue
4939
//
4940
queueEntry(cur);
4941
4942
return cur;
4943
}
4944
4945
//--------------------------- queueEntry ---------------------------------
4946
// Insert the compilation request in the queue at the appropriate place
4947
// based on its priority. Must have compilationQueueMonitor in hanb
4948
//------------------------------------------------------------------------
4949
void TR::CompilationInfo::queueEntry(TR_MethodToBeCompiled *entry)
4950
{
4951
TR_ASSERT_FATAL(entry->_freeTag & ENTRY_INITIALIZED, "queuing an entry which is not initialized\n");
4952
4953
entry->_freeTag |= ENTRY_QUEUED;
4954
4955
if (!_methodQueue || _methodQueue->_priority < entry->_priority)
4956
{
4957
entry->_next = _methodQueue;
4958
_methodQueue = entry;
4959
}
4960
else
4961
{
4962
for (TR_MethodToBeCompiled *prev = _methodQueue; ; prev = prev->_next)
4963
{
4964
if (!prev->_next || prev->_next->_priority < entry->_priority)
4965
{
4966
entry->_next = prev->_next;
4967
prev->_next = entry;
4968
break;
4969
}
4970
}
4971
}
4972
}
4973
4974
//--------------------------------- requeue ----------------------------------
4975
// Put the request that is currently being compiled, back into the queue
4976
// and increment the number of queued methods
4977
//----------------------------------------------------------------------------
4978
void TR::CompilationInfoPerThread::requeue()
4979
{
4980
TR_ASSERT(_methodBeingCompiled, "Invalid use of requeue.");
4981
_compInfo.incrementMethodQueueSize();
4982
if (_methodBeingCompiled->getMethodDetails().isOrdinaryMethod() && _methodBeingCompiled->_oldStartPC==0)
4983
_compInfo._numQueuedFirstTimeCompilations++;
4984
if (_methodBeingCompiled->_entryIsCountedAsInvRequest)
4985
_compInfo.incNumInvRequestsQueued(_methodBeingCompiled);
4986
_methodBeingCompiled->_compErrCode = compilationOK; // reset the error code
4987
_compInfo.queueEntry(_methodBeingCompiled);
4988
_methodBeingCompiled = NULL;
4989
}
4990
4991
//------------------------- adjustCompilationEntryAndRequeue -----------------
4992
// Search for the given method in the compilation queue
4993
// If found, we may adjust the optimization plan. There is a very good
4994
// likelihood that a matching entry will be found.
4995
//----------------------------------------------------------------------------
4996
TR_MethodToBeCompiled *
4997
TR::CompilationInfo::adjustCompilationEntryAndRequeue(
4998
TR::IlGeneratorMethodDetails &details,
4999
TR_PersistentMethodInfo *methodInfo,
5000
TR_Hotness newOptLevel, bool useProfiling,
5001
CompilationPriority priority,
5002
TR_J9VMBase *fe)
5003
{
5004
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
5005
{
5006
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
5007
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
5008
5009
if (curCompThreadInfoPT->getMethodBeingCompiled() &&
5010
curCompThreadInfoPT->getMethodBeingCompiled()->getMethodDetails().sameAs(details, fe))
5011
return NULL; // didn't do anything
5012
}
5013
5014
// Search the queue for my method
5015
TR_MethodToBeCompiled *cur, *prev;
5016
for (prev = NULL, cur = _methodQueue; cur; prev = cur, cur = cur->_next)
5017
{
5018
if (cur->getMethodDetails().sameAs(details, fe))
5019
break;
5020
}
5021
if (cur)
5022
{
5023
// here define the list of exclusions
5024
bool exclude = cur->getMethodDetails().isNewInstanceThunk() ||
5025
cur->_compilationAttemptsLeft < MAX_COMPILE_ATTEMPTS; // do not do it for retrials
5026
// we could also do it only for upgrades cur->_optimizationPlan->isUpgradeRecompilation()
5027
if (exclude)
5028
{
5029
cur = NULL;
5030
}
5031
else
5032
{
5033
cur->_optimizationPlan->setOptLevel(newOptLevel);
5034
cur->_optimizationPlan->setInsertInstrumentation(useProfiling);
5035
methodInfo->setNextCompileLevel(newOptLevel, useProfiling);
5036
5037
if (cur->_priority < priority)
5038
{
5039
// take the method out
5040
if (prev)
5041
prev->_next = cur->_next;
5042
else
5043
_methodQueue = cur->_next;
5044
// put it back at its proper place
5045
cur->_priority = priority;
5046
queueEntry(cur);
5047
}
5048
}
5049
//fprintf(stderr, "Adjusting optimization plan in the queue\n");
5050
}
5051
return cur;
5052
}
5053
5054
int32_t TR::CompilationInfo::promoteMethodInAsyncQueue(J9Method * method, void *pc)
5055
{
5056
// See if the method is already in the queue or is already being compiled
5057
//
5058
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
5059
{
5060
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
5061
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
5062
5063
if (curCompThreadInfoPT->getMethodBeingCompiled() &&
5064
!curCompThreadInfoPT->getMethodBeingCompiled()->isDLTCompile() &&
5065
method == curCompThreadInfoPT->getMethodBeingCompiled()->getMethodDetails().getMethod())
5066
{
5067
changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 9);
5068
return 0; // didn't do anything
5069
}
5070
}
5071
5072
int i = 0;
5073
TR_MethodToBeCompiled *cur, *prev;
5074
for (prev = NULL, cur = _methodQueue; cur; prev = cur, cur = cur->_next)
5075
{
5076
if (!cur->isDLTCompile() && method == cur->getMethodDetails().getMethod())
5077
break;
5078
i++;
5079
}
5080
5081
if (!cur || !prev || cur->_priority >= CP_ASYNC_MAX || prev->_priority >= CP_ASYNC_MAX)
5082
return -i;
5083
changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 9);
5084
_statNumQueuePromotions++;
5085
#ifdef STATS
5086
fprintf(stderr, "Promoting method in queue QSZ=%d\n", getMethodQueueSize());
5087
#endif
5088
cur->_priority = CP_ASYNC_MAX;
5089
5090
// take the method out
5091
prev->_next = cur->_next;
5092
// find insertion point
5093
if (_methodQueue->_priority < CP_ASYNC_MAX) // common case
5094
{
5095
cur->_next = _methodQueue;
5096
_methodQueue = cur;
5097
// FIXME: how about the compilation lag
5098
}
5099
else
5100
{
5101
for (prev = _methodQueue; prev->_next; prev = prev->_next)
5102
if (prev->_next->_priority < CP_ASYNC_MAX)
5103
{
5104
cur->_next = prev->_next;
5105
prev->_next = cur;
5106
break;
5107
}
5108
}
5109
return i;
5110
}
5111
5112
void TR::CompilationInfo::changeCompReqFromAsyncToSync(J9Method * method)
5113
{
5114
5115
TR_MethodToBeCompiled *cur = NULL, *prev = NULL;
5116
// See if the method is already in the queue or is already being compiled
5117
//
5118
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
5119
{
5120
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
5121
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
5122
5123
if (curCompThreadInfoPT->getMethodBeingCompiled() &&
5124
!curCompThreadInfoPT->getMethodBeingCompiled()->isDLTCompile() &&
5125
method == curCompThreadInfoPT->getMethodBeingCompiled()->getMethodDetails().getMethod())
5126
{
5127
if (curCompThreadInfoPT->getMethodBeingCompiled()->_priority <= CP_ASYNC_MAX)
5128
{
5129
curCompThreadInfoPT->getMethodBeingCompiled()->_priority = CP_SYNC_NORMAL;
5130
cur = curCompThreadInfoPT->getMethodBeingCompiled();
5131
break;
5132
}
5133
}
5134
}
5135
if (!cur)
5136
{
5137
for (cur = _methodQueue; cur; prev = cur, cur = cur->_next)
5138
if (!cur->isDLTCompile() && method == cur->getMethodDetails().getMethod())
5139
break;
5140
// Check if this is an asynchronous request
5141
//
5142
if (cur && cur->_priority <= CP_ASYNC_MAX)
5143
{
5144
// Take the method out, increase its priority and insert it at the proper place
5145
//
5146
cur->_priority = CP_SYNC_NORMAL;
5147
if (prev)
5148
{
5149
prev->_next = cur->_next;
5150
queueEntry(cur);
5151
}
5152
else // method already at the top of the queue
5153
{
5154
// Nothing to do
5155
}
5156
}
5157
else
5158
{
5159
cur = NULL; // prevent further processing
5160
}
5161
}
5162
if (cur)
5163
{
5164
TR_ASSERT(!cur->_changedFromAsyncToSync, "_changedFromAsyncToSync must be false");
5165
J9Method *method = cur->getMethodDetails().getMethod();
5166
cur->_changedFromAsyncToSync = true; // Flag the method as synchronous
5167
// Allow new invocations to trigger compilations
5168
if (getJ9MethodVMExtra(method) == J9_JIT_QUEUED_FOR_COMPILATION)
5169
setInvocationCount(method, 0);
5170
// fprintf(stderr, "Changed method %p priority from async to sync\n", method);
5171
}
5172
}
5173
5174
// Must hold compilation queue monitor in hand
5175
// Should only be used when compiling on separate thread, otherwise
5176
// _arrayOfCompilationInfoPerThread does not exist (or is full of null pointers)
5177
TR_MethodToBeCompiled * TR::CompilationInfo::requestExistsInCompilationQueue(TR::IlGeneratorMethodDetails & details, TR_FrontEnd *fe)
5178
{
5179
// See if the method is already in the queue or under compilation
5180
//
5181
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
5182
{
5183
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
5184
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
5185
5186
if (
5187
curCompThreadInfoPT->getMethodBeingCompiled() &&
5188
curCompThreadInfoPT->getMethodBeingCompiled()->getMethodDetails().sameAs(details, fe) &&
5189
!curCompThreadInfoPT->getMethodBeingCompiled()->_unloadedMethod) // Redefinition; see cmvc 192606 and RTC 36898
5190
return curCompThreadInfoPT->getMethodBeingCompiled();
5191
}
5192
5193
for (TR_MethodToBeCompiled *cur = _methodQueue; cur; cur = cur->_next)
5194
if (cur->getMethodDetails().sameAs(details, fe))
5195
return cur;
5196
return NULL;
5197
}
5198
5199
TR_MethodToBeCompiled *TR::CompilationInfo::peekNextMethodToBeCompiled()
5200
{
5201
if (_methodQueue)
5202
return _methodQueue;
5203
else if (getLowPriorityCompQueue().hasLowPriorityRequest() && canProcessLowPriorityRequest())
5204
// These upgrade requests should not hinder the application too much.
5205
// If possible, we should decrease the priority of the compilation thread
5206
// Note that on LINUX priorities do not work
5207
// If we cannot lower the priority, we should wait for some idle time
5208
// or space compilations apart. if we return NULL here, the compilation
5209
// thread will go to sleep and we need a mechanism to wake it up
5210
//
5211
return getLowPriorityCompQueue().getFirstLPQRequest();
5212
else if (!getJProfilingCompQueue().isEmpty() && canProcessJProfilingRequest())
5213
return getJProfilingCompQueue().getFirstCompRequest();
5214
else
5215
return NULL;
5216
}
5217
5218
5219
TR_MethodToBeCompiled *
5220
TR::CompilationInfo::getNextMethodToBeCompiled(TR::CompilationInfoPerThread *compInfoPT,
5221
bool compThreadCameOutOfSleep,
5222
TR_CompThreadActions *compThreadAction)
5223
{
5224
TR_MethodToBeCompiled *nextMethodToBeCompiled = NULL;
5225
5226
// Only the diagnostic thread should be processing JitDump compilations. This is to ensure proper tracing is active
5227
// and proper synchronization is performed w.r.t. special events (interpreter shutdown, etc.). The logic here is
5228
// split into two parts. In the event we are a diagnostic thread, the JitDump process will have ensured the method
5229
// compilation queue has been purged and all further compilations have been suspended until the entire JitDump
5230
// process in complete. This also means if we are a diagnostic thread, then the only entries in the queue should
5231
// be JitDump compile requests. We will ensure this is the case via a fatal assert.
5232
//
5233
// In addition there can be scenarios in which a non-diagnostic compilation thread is still attempting to process
5234
// entries while the JitDump process (in a crashed thread) is happening. This is because one compilation thread
5235
// must always be active, and there is a timing hole between purging of the queue in the JitDump process, and when
5236
// the diagnostic thread is resumed. This means a non-diagnostic thread could attempt to pick up a JitDump
5237
// compilation request (see eclipse-openj9/openj9#11772 for details). We must ensure that this does not happen and simply
5238
// skip the request if we are a non-diagnostic thread attempting to process a JitDump compilation.
5239
if (compInfoPT->isDiagnosticThread())
5240
{
5241
// We never want to self-suspend the diagnostic thread. The JitDump process will do it after it is complete.
5242
*compThreadAction = GO_TO_SLEEP_EMPTY_QUEUE;
5243
5244
if (_methodQueue)
5245
{
5246
nextMethodToBeCompiled = _methodQueue;
5247
_methodQueue = _methodQueue->_next;
5248
5249
// See explanation at the start of this function of why it is important to ensure this
5250
TR_ASSERT_FATAL(nextMethodToBeCompiled->getMethodDetails().isJitDumpMethod(), "Diagnostic thread attempting to process non-JitDump compilation");
5251
5252
*compThreadAction = PROCESS_ENTRY;
5253
}
5254
}
5255
else
5256
{
5257
*compThreadAction = PROCESS_ENTRY;
5258
5259
// Due to the above mentioned timing hole, a non-diagnostic compilation thread may still be trying to process
5260
// entries. We prevent it from processing JitDump compilation requests here.
5261
if (_methodQueue != NULL && !_methodQueue->getMethodDetails().isJitDumpMethod())
5262
{
5263
// If the request is sync or AOT load, take it now
5264
if (_methodQueue->_priority >= CP_SYNC_MIN // sync comp
5265
|| _methodQueue->_methodIsInSharedCache == TR_yes // very cheap relocation
5266
#if defined(J9VM_OPT_JITSERVER)
5267
|| getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER // compile right away in server mode
5268
#endif
5269
)
5270
{
5271
nextMethodToBeCompiled = _methodQueue;
5272
_methodQueue = _methodQueue->_next;
5273
}
5274
// Check if we need to throttle
5275
else if (exceedsCompCpuEntitlement() == TR_yes &&
5276
!compThreadCameOutOfSleep && // Don't throttle a comp thread that has just slept its share of time
5277
(TR::Options::_compThreadCPUEntitlement < 100 || getNumCompThreadsActive() * 100 > (TR::Options::_compThreadCPUEntitlement + 50)))
5278
{
5279
// If at all possible suspend the compilation thread
5280
// Otherwise, perform a timed wait
5281
if (getNumCompThreadsActive() > 1)
5282
*compThreadAction = SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;
5283
else
5284
*compThreadAction = THROTTLE_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;
5285
}
5286
// Avoid two concurrent hot compilations
5287
else if (getNumCompThreadsCompilingHotterMethods() <= 0 || // no hot compilation in progress
5288
_methodQueue->_weight < TR::Options::_expensiveCompWeight) // This is a cheaper comp
5289
{
5290
nextMethodToBeCompiled = _methodQueue;
5291
_methodQueue = _methodQueue->_next;
5292
}
5293
else // scan for a cold/warm method
5294
{
5295
TR_MethodToBeCompiled *prev = _methodQueue;
5296
for (nextMethodToBeCompiled = _methodQueue->_next; nextMethodToBeCompiled; prev = nextMethodToBeCompiled, nextMethodToBeCompiled = nextMethodToBeCompiled->_next)
5297
{
5298
if (nextMethodToBeCompiled->_optimizationPlan->getOptLevel() <= warm || // cheaper comp
5299
nextMethodToBeCompiled->_priority >= CP_SYNC_MIN || // sync comp
5300
nextMethodToBeCompiled->_methodIsInSharedCache == TR_yes) // very cheap relocation
5301
{
5302
prev->_next = nextMethodToBeCompiled->_next;
5303
break;
5304
}
5305
}
5306
if (!nextMethodToBeCompiled)
5307
{
5308
*compThreadAction = GO_TO_SLEEP_CONCURRENT_EXPENSIVE_REQUESTS;
5309
5310
// make sure there is at least one thread that is not jobless
5311
TR::CompilationInfoPerThread * const * arrayOfCompInfoPT = getArrayOfCompilationInfoPerThread();
5312
int32_t numActive = 0, numHot = 0, numLowPriority = 0;
5313
for (int32_t i = 0; i < getNumUsableCompilationThreads(); i++)
5314
{
5315
TR::CompilationInfoPerThread *curCompThreadInfoPT = arrayOfCompInfoPT[i];
5316
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
5317
5318
CompilationThreadState currentThreadState = curCompThreadInfoPT->getCompilationThreadState();
5319
if (
5320
currentThreadState == COMPTHREAD_ACTIVE
5321
|| currentThreadState == COMPTHREAD_SIGNAL_WAIT
5322
|| currentThreadState == COMPTHREAD_WAITING
5323
|| currentThreadState == COMPTHREAD_SIGNAL_SUSPEND
5324
)
5325
{
5326
if (curCompThreadInfoPT->getMethodBeingCompiled() &&
5327
curCompThreadInfoPT->getMethodBeingCompiled()->_priority < CP_ASYNC_NORMAL)
5328
numLowPriority++;
5329
if (curCompThreadInfoPT->compilationThreadIsActive())
5330
numActive++;
5331
if (curCompThreadInfoPT->getMethodBeingCompiled() &&
5332
curCompThreadInfoPT->getMethodBeingCompiled()->_hasIncrementedNumCompThreadsCompilingHotterMethods)
5333
numHot++;
5334
}
5335
}
5336
5337
// There is a method to be compiled, but this thread is not going to take it out of the queue
5338
// There are two cases when this might happen:
5339
// (1) Two hot requests going in parallel
5340
// (2) Two low priority requests going in parallel during startup phase
5341
TR_ASSERT(numHot >= 1 || numLowPriority >= 1, "We must have a comp thread working on a hot or low priority method %d %d", numHot, numLowPriority);
5342
5343
if (numActive <= 1) // Current thread is by default active because it tried to dequeue a request
5344
{
5345
// There is no thread left to handle the existing request
5346
// See defect 182392 for why this could have happened and for the solution
5347
//fprintf(stderr, "JIT WARNING: no active thread left to handle queued request\n");
5348
}
5349
// sanity checks
5350
if (getNumCompThreadsActive() != numActive)
5351
{
5352
TR_ASSERT(false, "Inconsistency with active threads %d %d\n", getNumCompThreadsActive(), numActive);
5353
setNumCompThreadsActive(numActive); // apply correction
5354
}
5355
if (getNumCompThreadsCompilingHotterMethods() != numHot)
5356
{
5357
TR_ASSERT(false, "Inconsistency with hot threads %d %d\n", getNumCompThreadsCompilingHotterMethods(), numHot);
5358
setNumCompThreadsCompilingHotterMethods(numHot); // apply correction
5359
}
5360
}
5361
}
5362
if (nextMethodToBeCompiled) // A request has been dequeued
5363
{
5364
updateCompQueueAccountingOnDequeue(nextMethodToBeCompiled);
5365
}
5366
}
5367
// When no request is in the main queue we can look in the low priority queue
5368
else if (getLowPriorityCompQueue().hasLowPriorityRequest() &&
5369
canProcessLowPriorityRequest())
5370
{
5371
// Check if we need to throttle
5372
if (exceedsCompCpuEntitlement() == TR_yes &&
5373
!compThreadCameOutOfSleep && // Don't throttle a comp thread that has just slept its share of time
5374
(TR::Options::_compThreadCPUEntitlement < 100 || getNumCompThreadsActive() * 100 > (TR::Options::_compThreadCPUEntitlement + 50))
5375
#if defined(J9VM_OPT_JITSERVER)
5376
&& !getLowPriorityCompQueue().getFirstLPQRequest()->shouldUpgradeOutOfProcessCompilation() // Don't throttle if compilation will be done remotely
5377
#endif
5378
)
5379
{
5380
// If at all possible suspend the compilation thread
5381
// Otherwise, perform a timed wait
5382
if (getNumCompThreadsActive() > 1)
5383
*compThreadAction = SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;
5384
else
5385
*compThreadAction = THROTTLE_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;
5386
}
5387
else
5388
{
5389
nextMethodToBeCompiled = getLowPriorityCompQueue().extractFirstLPQRequest();
5390
}
5391
}
5392
// Now let's look in the JProfiling queue
5393
else if (!getJProfilingCompQueue().isEmpty() && canProcessJProfilingRequest())
5394
{
5395
// Check if we need to throttle
5396
if (exceedsCompCpuEntitlement() == TR_yes &&
5397
!compThreadCameOutOfSleep && // Don't throttle a comp thread that has just slept its share of time
5398
(TR::Options::_compThreadCPUEntitlement < 100 || getNumCompThreadsActive() * 100 >(TR::Options::_compThreadCPUEntitlement + 50)))
5399
{
5400
// If at all possible suspend the compilation thread
5401
// Otherwise, perform a timed wait
5402
if (getNumCompThreadsActive() > 1)
5403
*compThreadAction = SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;
5404
else
5405
*compThreadAction = THROTTLE_COMP_THREAD_EXCEED_CPU_ENTITLEMENT;
5406
}
5407
else
5408
{
5409
nextMethodToBeCompiled = getJProfilingCompQueue().extractFirstCompRequest();
5410
}
5411
}
5412
else
5413
{
5414
// Cannot take a request either from main queue or LPQ
5415
// If this is the last active compilation thread, then go to sleep,
5416
// otherwise suspend the compilation thread
5417
if (getNumCompThreadsActive() > 1)
5418
{
5419
*compThreadAction = SUSPEND_COMP_THREAD_EMPTY_QUEUE;
5420
}
5421
else
5422
{
5423
*compThreadAction = GO_TO_SLEEP_EMPTY_QUEUE;
5424
}
5425
}
5426
5427
if (nextMethodToBeCompiled != NULL)
5428
{
5429
// See explanation at the start of this function of why it is important to ensure this
5430
TR_ASSERT_FATAL(!nextMethodToBeCompiled->getMethodDetails().isJitDumpMethod(), "Non-diagnostic thread attempting to process JitDump compilation");
5431
}
5432
}
5433
5434
return nextMethodToBeCompiled;
5435
}
5436
5437
//----------------------------- computeCompThreadSleepTime ----------------------
5438
// Compute how much the compilation thread should sleep for throttling purposes
5439
// Parameters: compilationTimeMs is the wall clock time spent by previous
5440
// compilation
5441
// The return value is in ms.
5442
//-------------------------------------------------------------------------------
5443
int32_t TR::CompilationInfo::computeCompThreadSleepTime(int32_t compilationTimeMs)
5444
{
5445
int32_t sleepTimeMs = 1;
5446
if (TR::Options::_compThreadCPUEntitlement > 0)
5447
{
5448
sleepTimeMs = compilationTimeMs * (100 / TR::Options::_compThreadCPUEntitlement - 1);
5449
}
5450
// some bounds for sleep time
5451
if (sleepTimeMs < TR::Options::_minSleepTimeMsForCompThrottling) // too small values are not useful because of high overhead of calling wait()
5452
sleepTimeMs = TR::Options::_minSleepTimeMsForCompThrottling;
5453
if (sleepTimeMs > TR::Options::_maxSleepTimeMsForCompThrottling) // TODO: need an options for this value
5454
sleepTimeMs = TR::Options::_maxSleepTimeMsForCompThrottling;
5455
return sleepTimeMs;
5456
}
5457
5458
// FIXME: this should be called only when running async - i have not yet figured
5459
// out how to figure this info out for interpreted methods scheduled for their
5460
// first compilation
5461
bool TR::CompilationInfo::isQueuedForCompilation(J9Method * method, void *oldStartPC)
5462
{
5463
TR_ASSERT(oldStartPC, "isQueuedForCompilation should not be called for interpreted methods\n");
5464
5465
J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(oldStartPC);
5466
return linkageInfo->isBeingCompiled();
5467
}
5468
5469
#if defined(TR_HOST_X86)
5470
JIT_HELPER(initialInvokeExactThunkGlue);
5471
#else
5472
JIT_HELPER(_initialInvokeExactThunkGlue);
5473
#endif
5474
5475
void *TR::CompilationInfo::startPCIfAlreadyCompiled(J9VMThread * vmThread, TR::IlGeneratorMethodDetails & details, void *oldStartPC)
5476
{
5477
if (details.isNewInstanceThunk())
5478
{
5479
return jitNewInstanceMethodStartAddress(vmThread, static_cast<J9::NewInstanceThunkDetails &>(details).classNeedingThunk());
5480
}
5481
else if (details.isMethodHandleThunk())
5482
{
5483
J9::MethodHandleThunkDetails &thunkDetails = static_cast<J9::MethodHandleThunkDetails &>(details);
5484
if (!thunkDetails.isShareable())
5485
return NULL; // Don't let the presence of a shareable thunk interfere with other requests
5486
5487
J9JITConfig *jitConfig = vmThread->javaVM->jitConfig;
5488
if (!jitConfig)
5489
return NULL;
5490
5491
void *thunkStartPC = NULL;
5492
TR_J9VMBase * fe = TR_J9VMBase::get(jitConfig, vmThread);
5493
5494
{
5495
TR::VMAccessCriticalSection startPCIfAlreadyCompiled(fe);
5496
uintptr_t methodHandle = *thunkDetails.getHandleRef();
5497
void *thunkAddress = fe->methodHandle_jitInvokeExactThunk(methodHandle);
5498
void *initialInvokeExactThunkGlueAddress;
5499
#if defined(J9ZOS390)
5500
initialInvokeExactThunkGlueAddress = (void*)TOC_UNWRAP_ADDRESS(_initialInvokeExactThunkGlue);
5501
#elif defined(TR_HOST_POWER) && (defined(TR_HOST_64BIT) || defined(AIXPPC)) && !defined(__LITTLE_ENDIAN__)
5502
initialInvokeExactThunkGlueAddress = (*(void **)_initialInvokeExactThunkGlue);
5503
#elif defined(TR_HOST_X86)
5504
initialInvokeExactThunkGlueAddress = (void*)initialInvokeExactThunkGlue;
5505
#else
5506
initialInvokeExactThunkGlueAddress = (void*)_initialInvokeExactThunkGlue;
5507
#endif
5508
if (thunkAddress != initialInvokeExactThunkGlueAddress)
5509
{
5510
// thunkAddress is the jit entry point for a thunk. We need to find
5511
// the corresponding startPC (which is the interpreter entry point).
5512
//
5513
// TODO:JSR292: This could also be a j2i thunk/helper address! Should
5514
// return NULL in that case. For now, set TR_DisableThunkTupleJ2I to
5515
// avoid this case.
5516
//
5517
J9JITHashTable *hashTable = (J9JITHashTable *) avl_search(jitConfig->translationArtifacts, (UDATA)thunkAddress);
5518
if (hashTable)
5519
{
5520
J9JITExceptionTable *metadata = hash_jit_artifact_search(hashTable, (UDATA)thunkAddress);
5521
if (metadata)
5522
thunkStartPC = (void*)metadata->startPC;
5523
}
5524
bool verboseDetails = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseMethodHandleDetails);
5525
if (verboseDetails)
5526
{
5527
if (thunkStartPC)
5528
TR_VerboseLog::writeLineLocked(TR_Vlog_MHD, "%p Metadata lookup: handle %p thunk body at %p has startPC %p", vmThread, (void*)methodHandle, thunkAddress, thunkStartPC);
5529
else
5530
TR_VerboseLog::writeLineLocked(TR_Vlog_MHD, "%p Metadata lookup FAILED for: handle %p thunk body at %p -- jit will probably create a redundant body", vmThread, (void*)methodHandle, thunkAddress);
5531
}
5532
}
5533
}
5534
5535
return thunkStartPC;
5536
}
5537
5538
void *startPC = 0;
5539
J9Method *method = details.getMethod();
5540
5541
if (!oldStartPC)
5542
{
5543
// first compilation of the method: J9Method would be updated if the
5544
// compilation has already taken place
5545
//
5546
startPC = getPCIfCompiled(method);
5547
}
5548
else
5549
{
5550
J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(oldStartPC);
5551
if (linkageInfo->recompilationAttempted())
5552
startPC = getPCIfCompiled(method);
5553
}
5554
return startPC;
5555
}
5556
5557
// Must have compilation monitor when calling this method
5558
void TR::CompilationInfo::recycleCompilationEntry(TR_MethodToBeCompiled *entry)
5559
{
5560
TR_ASSERT_FATAL((entry->_freeTag & (ENTRY_INITIALIZED)) || (entry->_freeTag & (ENTRY_IN_POOL_NOT_FREE|ENTRY_IN_POOL_FREE|ENTRY_DEALLOCATED)),
5561
"recycling an improper entry\n");
5562
entry->_freeTag |= ENTRY_IN_POOL_NOT_FREE;
5563
if (entry->_numThreadsWaiting == 0)
5564
entry->_freeTag |= ENTRY_IN_POOL_FREE;
5565
5566
entry->_next = _methodPool;
5567
_methodPool = entry;
5568
_methodPoolSize++;
5569
5570
// If the pool grows too big, start deallocating entries
5571
if (_methodPoolSize >= METHOD_POOL_SIZE_THRESHOLD)
5572
{
5573
TR_MethodToBeCompiled *prev = _methodPool;
5574
TR_MethodToBeCompiled *crt = _methodPool->_next;
5575
while (crt && _methodPoolSize >= METHOD_POOL_SIZE_THRESHOLD/2)
5576
{
5577
if (crt->_numThreadsWaiting == 0)
5578
{
5579
TR_ASSERT_FATAL(crt->_freeTag & ENTRY_IN_POOL_FREE, "Will deallocate an entry that is not free\n");
5580
5581
prev->_next = crt->_next;
5582
_methodPoolSize--;
5583
crt->shutdown(); // free the monitor and string associated with it
5584
PORT_ACCESS_FROM_JITCONFIG(_jitConfig);
5585
j9mem_free_memory(crt);
5586
crt = prev->_next;
5587
}
5588
else
5589
{
5590
prev = crt;
5591
crt = crt->_next;
5592
}
5593
}
5594
}
5595
}
5596
5597
5598
static void deleteMethodHandleRef(J9::MethodHandleThunkDetails & details, J9VMThread *vmThread, TR_FrontEnd *fe)
5599
{
5600
bool verboseDetails = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseMethodHandleDetails);
5601
TR_J9VMBase *fej9 = (TR_J9VMBase *)fe;
5602
5603
if (verboseDetails)
5604
{
5605
TR::VMAccessCriticalSection deleteMethodHandleRef(fej9);
5606
uintptr_t methodHandle = * details.getHandleRef();
5607
TR_VerboseLog::writeLineLocked(TR_Vlog_MHD,"%p Deleting MethodHandle %p global reference", vmThread, (j9object_t)methodHandle);
5608
}
5609
5610
vmThread->javaVM->internalVMFunctions->j9jni_deleteGlobalRef((JNIEnv*)vmThread, (jobject)details.getHandleRef(), false);
5611
if (details.getArgRef())
5612
vmThread->javaVM->internalVMFunctions->j9jni_deleteGlobalRef((JNIEnv*)vmThread, (jobject)details.getArgRef(), false);
5613
}
5614
5615
5616
void *TR::CompilationInfo::compileMethod(J9VMThread * vmThread, TR::IlGeneratorMethodDetails & details, void *oldStartPC,
5617
TR_YesNoMaybe requireAsyncCompile,
5618
TR_CompilationErrorCode *compErrCode,
5619
bool *queued, TR_OptimizationPlan * optimizationPlan)
5620
{
5621
TR_J9VMBase * fe = TR_J9VMBase::get(_jitConfig, vmThread);
5622
TR_ASSERT(!fe->isAOT_DEPRECATED_DO_NOT_USE(), "We need a non-AOT vm here.");
5623
5624
J9Method *method = details.getMethod();
5625
5626
J9::NewInstanceThunkDetails * newInstanceThunkDetails = NULL;
5627
if (details.isNewInstanceThunk())
5628
newInstanceThunkDetails = & static_cast<J9::NewInstanceThunkDetails &>(details);
5629
5630
J9::MethodHandleThunkDetails *methodHandleThunkDetails = NULL;
5631
if (details.isMethodHandleThunk())
5632
methodHandleThunkDetails = & static_cast<J9::MethodHandleThunkDetails &>(details);
5633
5634
J9Class *clazz = details.getClass();
5635
5636
bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest);
5637
if (verbose)
5638
{
5639
TR_VerboseLog::CriticalSection vlogLock;
5640
TR_VerboseLog::write(TR_Vlog_CR, "%p Compile request %s", vmThread, details.name());
5641
5642
if (newInstanceThunkDetails)
5643
{
5644
if (clazz)
5645
{
5646
int32_t len;
5647
char * className = fe->getClassNameChars(fe->convertClassPtrToClassOffset(clazz), len);
5648
TR_VerboseLog::write(" j9class=%p %.*s", clazz, len, className);
5649
}
5650
}
5651
else if (methodHandleThunkDetails)
5652
{
5653
// No vm access needed here, because we're not inspecting the handle object -- only printing its address.
5654
TR_VerboseLog::write(" handle=%p", (void*)*(methodHandleThunkDetails->getHandleRef()));
5655
if (methodHandleThunkDetails->getArgRef())
5656
TR_VerboseLog::write(" arg=%p", (void*)*(methodHandleThunkDetails->getArgRef()));
5657
}
5658
5659
char buf[500];
5660
fe->printTruncatedSignature(buf, sizeof(buf), (TR_OpaqueMethodBlock *)method);
5661
TR_VerboseLog::write(" j9method=%p %s optLevel=%d", method, buf, optimizationPlan->getOptLevel());
5662
if (clazz && J9_IS_CLASS_OBSOLETE(clazz))
5663
{
5664
TR_ASSERT(!fe->isAOT_DEPRECATED_DO_NOT_USE(), "Shouldn't get obsolete classes in AOT");
5665
TR_VerboseLog::write(" OBSOLETE class=%p -- request declined", clazz);
5666
}
5667
TR_VerboseLog::writeLine("");
5668
}
5669
5670
// Pin the class of the method in case GC wants to unload it
5671
bool classPushed = false;
5672
// Why wouldn't we do this for AOT??
5673
if (!fe->isAOT_DEPRECATED_DO_NOT_USE())
5674
{
5675
if (clazz && J9_IS_CLASS_OBSOLETE(clazz))
5676
return NULL;
5677
5678
PUSH_OBJECT_IN_SPECIAL_FRAME(vmThread, J9VM_J9CLASS_TO_HEAPCLASS(clazz));
5679
classPushed = true;
5680
}
5681
5682
#ifdef J9VM_JIT_GC_ON_RESOLVE_SUPPORT
5683
// If gcOnResolve, scavenge now, unless the JIT is in test mode,
5684
// and not connected to a real fe. Do this only when recompiling
5685
// or when compiling a newInstanceThunk (otherwise we're too slow)
5686
//
5687
if ( (_jitConfig->runtimeFlags & J9JIT_SCAVENGE_ON_RESOLVE) &&
5688
!(_jitConfig->runtimeFlags & J9JIT_TOSS_CODE) && !requireAsyncCompile &&
5689
(oldStartPC || newInstanceThunkDetails))
5690
jitCheckScavengeOnResolve(vmThread);
5691
#endif
5692
5693
void *startPC = 0;
5694
bool needCompile = true;
5695
5696
// always need to compile if it's a log compilation
5697
if (!(optimizationPlan->isLogCompilation()))
5698
{
5699
if (newInstanceThunkDetails)
5700
{
5701
// Ask the VM if this compilation is required
5702
//
5703
startPC = jitNewInstanceMethodStartAddress(vmThread, clazz);
5704
if (startPC || fe->isAOT_DEPRECATED_DO_NOT_USE())
5705
needCompile = false;
5706
} // if
5707
else if (!oldStartPC && !details.isMethodInProgress())
5708
{
5709
startPC = getPCIfCompiled(method);
5710
if (startPC)
5711
{
5712
debugPrint("\tcompile request already done", method); //, vmThread, entry->getMethodDetails());
5713
needCompile = false;
5714
}
5715
} // if
5716
else if (oldStartPC) // recompilation case
5717
{
5718
if (fe->isAOT_DEPRECATED_DO_NOT_USE())
5719
{
5720
J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(oldStartPC);
5721
if (linkageInfo->recompilationAttempted())
5722
{
5723
startPC = getPCIfCompiled(method); // provide the new startPC
5724
// must look like a compiled method
5725
if (startPC)
5726
{
5727
debugPrint("\tcompile request already done", method); //, vmThread, entry->getMethodDetails());
5728
needCompile = false;
5729
}
5730
} // if
5731
} // if
5732
} // if
5733
} // if !isLogCompilation()
5734
5735
if (optimizationPlan->isGPUCompilation())
5736
needCompile=1;
5737
5738
if (needCompile)
5739
{
5740
// AOT goes to application thread?
5741
if (!fe->isAOT_DEPRECATED_DO_NOT_USE())
5742
startPC = compileOnSeparateThread(vmThread, details, oldStartPC, requireAsyncCompile, compErrCode, queued, optimizationPlan);
5743
}
5744
else
5745
{
5746
if (compErrCode)
5747
*compErrCode = compilationNotNeeded;
5748
}
5749
5750
if (!fe->isAOT_DEPRECATED_DO_NOT_USE())
5751
if (classPushed)
5752
POP_OBJECT_IN_SPECIAL_FRAME(vmThread);
5753
return startPC;
5754
}
5755
5756
#if defined(J9VM_OPT_SHARED_CLASSES)
5757
extern bool
5758
validateSharedClassAOTHeader(J9JavaVM *javaVM, J9VMThread *curThread, TR::CompilationInfo *compInfo, TR_FrontEnd *fe);
5759
#endif
5760
5761
void *TR::CompilationInfo::compileOnSeparateThread(J9VMThread * vmThread, TR::IlGeneratorMethodDetails & details,
5762
void *oldStartPC, TR_YesNoMaybe requireAsyncCompile,
5763
TR_CompilationErrorCode *compErrCode,
5764
bool *queued,
5765
TR_OptimizationPlan * optimizationPlan)
5766
{
5767
void *startPC = NULL;
5768
5769
J9Method *method = details.getMethod();
5770
TR_J9VMBase *fe = TR_J9VMBase::get(_jitConfig, vmThread);
5771
5772
// Grab the compilation monitor
5773
//
5774
debugPrint(vmThread, "\tapplication thread acquiring compilation monitor\n");
5775
acquireCompMonitor(vmThread);
5776
debugPrint(vmThread, "+CM\n");
5777
5778
// Even before checking whether compilation threads are active, we need
5779
// to check if a compilation for this body has already been performed
5780
5781
// Now that we have the lock
5782
// Check if the compilation is already done by looking at the J9Method/LinkageInfo.
5783
//
5784
// If it is not already done, then either
5785
// 1 - we are the first thread to get here, we will create a brand new entry in the queue.
5786
// 2 - an entry in the queue already exists - a compilation is in progress or in queue
5787
// that hasn't finished yet. We will definitely find the old entry when we try to add
5788
// to the queue.
5789
//
5790
if (!details.isMethodInProgress())
5791
startPC = startPCIfAlreadyCompiled(vmThread, details, oldStartPC);
5792
if (startPC && !details.isJitDumpMethod() &&
5793
!optimizationPlan->isGPUCompilation())
5794
{
5795
// Release the compilation lock and return
5796
debugPrint(vmThread, "\tapplication thread releasing compilation monitor - compile already done\n");
5797
debugPrint(vmThread, "-CM\n");
5798
releaseCompMonitor(vmThread);
5799
if (compErrCode)
5800
*compErrCode = compilationNotNeeded;
5801
if (TR::Options::getJITCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))
5802
TR_VerboseLog::writeLineLocked(TR_Vlog_CR,"%p Already compiled at %p", startPC);
5803
return startPC;
5804
}
5805
5806
// If there are no active threads ready to perform the compilation or further compilations are disabled we will
5807
// end this compilation request. The only exception to this case is if we are performing a JitDump compilation,
5808
// in which case we always want to proceed with the compilation since it will be performed on the diagnostic
5809
// thread. Note that the diagnostic thread is not counted towards `getNumCompThreadsActive` count.
5810
if ((getNumCompThreadsActive() == 0 || getPersistentInfo()->getDisableFurtherCompilation()) && !details.isJitDumpMethod())
5811
{
5812
bool shouldReturn = true;
5813
5814
// Fail the compilation, unless this is on the queue (maybe even in progress)
5815
if (!requestExistsInCompilationQueue(details, fe))
5816
{
5817
startPC = compilationEnd(vmThread, details, _jitConfig, 0, oldStartPC);
5818
}
5819
else // Similar request already exists in the queue. We cannot fail this compilation
5820
{
5821
// If this is a sync compilation we must wait for the queued compilation to finish
5822
// Otherwise, code patching could put as in an infinite loop (see 185740)
5823
// It's also safe to continue for async compilations: if a similar request
5824
// already exists we will bail out and let the Java thread go.
5825
shouldReturn = false;
5826
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompFailure, TR_VerboseCompileRequest))
5827
{
5828
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"t=%u <WARNING: JIT Compilations are suspended. Current request will be coalesced with existing one in the queue>", (uint32_t)getPersistentInfo()->getElapsedTime());
5829
}
5830
}
5831
5832
if (shouldReturn)
5833
{
5834
debugPrint(vmThread, "\tapplication thread release compilation monitor - comp thread AWOL\n");
5835
debugPrint(vmThread, "-CM\n");
5836
releaseCompMonitor(vmThread);
5837
if (compErrCode)
5838
*compErrCode = compilationSuspended;
5839
5840
// Update statistics regarding the reason for compilation failure
5841
updateCompilationErrorStats(compilationSuspended);
5842
5843
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompFailure, TR_VerboseCompileRequest))
5844
{
5845
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"t=%u <WARNING: JIT Compilations are suspended>", (uint32_t)getPersistentInfo()->getElapsedTime());
5846
}
5847
5848
return startPC;
5849
}
5850
}
5851
5852
5853
// Determine if the compilation is going to be synchronous or asynchronous.
5854
// newInstance Thunks, and invalidated methods need be compiled synchronously
5855
//
5856
debugPrint(vmThread, "\tQueuing ");
5857
5858
TR_ASSERT(asynchronousCompilation() || requireAsyncCompile != TR_yes, "We cannot require async compilation when it is turned off");
5859
5860
bool forcedSync = false;
5861
bool async = asynchronousCompilation() && requireAsyncCompile != TR_no;
5862
if (async)
5863
{
5864
J9::PrivateLinkage::LinkageInfo *linkageInfo = oldStartPC ? J9::PrivateLinkage::LinkageInfo::get(oldStartPC) : 0;
5865
if (requireAsyncCompile != TR_yes && !oldStartPC && !details.isMethodInProgress())
5866
{
5867
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
5868
// if the method is specified to be compiled at count=0, -Xjit:{*method*}(count=0), then do it synchronously
5869
//
5870
if (TR::Options::getJITCmdLineOptions()->anOptionSetContainsACountValue() ||
5871
TR::Options::getAOTCmdLineOptions()->anOptionSetContainsACountValue())
5872
{
5873
bool hasBackwardBranches = (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod)) ? true : false;
5874
bool isAOT = !TR::Options::getJITCmdLineOptions()->anOptionSetContainsACountValue();
5875
TR::OptionSet * optionSet = findOptionSet(method, isAOT);
5876
5877
if (optionSet &&
5878
(optionSet->getOptions()->getInitialCount() == 0 ||
5879
(optionSet->getOptions()->getInitialBCount() == 0 && hasBackwardBranches)))
5880
async = false;
5881
}
5882
5883
if (async)
5884
{
5885
bool isORB = false;
5886
J9ROMClass *declaringClazz = J9_CLASS_FROM_METHOD(method)->romClass;
5887
J9UTF8 * className = J9ROMCLASS_CLASSNAME(declaringClazz);
5888
if (J9UTF8_LENGTH(className) == 36 &&
5889
0==memcmp(utf8Data(className), "com/ibm/rmi/io/FastPathForCollocated", 36))
5890
{
5891
J9UTF8 *utf8 = J9ROMMETHOD_NAME(J9_ROM_METHOD_FROM_RAM_METHOD(method));
5892
if (J9UTF8_LENGTH(utf8)==21 &&
5893
0==memcmp(J9UTF8_DATA(utf8), "isVMDeepCopySupported", 21))
5894
isORB = true;
5895
}
5896
5897
if (fe && requireAsyncCompile != TR_yes && isORB)
5898
async = false;
5899
}
5900
}
5901
5902
if (!async)
5903
{
5904
debugPrint("forced synchronous");
5905
forcedSync = true;
5906
}
5907
else
5908
{
5909
debugPrint("asynchronous");
5910
// for async requests we can avoid checking the queue
5911
if ((linkageInfo && linkageInfo->isBeingCompiled()) || // for jitted methods
5912
(oldStartPC == 0 && // for interpreted methods
5913
details.isOrdinaryMethod() &&
5914
getJ9MethodVMExtra(details.getMethod()) == J9_JIT_QUEUED_FOR_COMPILATION)) // this will also filter out JNI natives
5915
{
5916
// Release the compilation lock and return
5917
debugPrint(vmThread, "\tapplication thread releasing compilation monitor - comp.req. in progress\n");
5918
debugPrint(vmThread, "-CM\n");
5919
releaseCompMonitor(vmThread);
5920
if (compErrCode)
5921
*compErrCode = compilationInProgress;
5922
return 0; // mark that compilation is not yet done
5923
}
5924
// When the compilation queue is very large, it may be better to postpone
5925
// the asynchronous compilations by replenishing the invocation counter.
5926
// This avoids the overhead associated with searching the right place to
5927
// insert into the compilation queue (which is a priority queue)
5928
if (getMethodQueueSize() >= TR::Options::_qszLimit &&
5929
oldStartPC == 0 && // Only look at interpreted methods
5930
details.isOrdinaryMethod()) // Do not apply this optimization to DLT
5931
{
5932
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
5933
if (!(romMethod->modifiers & J9AccNative)) // We are not allowed to change the invocation count for native methods
5934
{
5935
int32_t newCount = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR_DEFAULT_INITIAL_BCOUNT : TR_DEFAULT_INITIAL_COUNT;
5936
bool success = TR::CompilationInfo::replenishInvocationCountIfExpired(method, newCount);
5937
if (success)
5938
{
5939
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
5940
{
5941
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Reencoding count=%d for j9m=%p because Q_SZ is too large", newCount, method);
5942
}
5943
// Release the compilation lock and return
5944
debugPrint(vmThread, "\tapplication thread releasing compilation monitor - comp.req. in progress\n");
5945
debugPrint(vmThread, "-CM\n");
5946
releaseCompMonitor(vmThread);
5947
if (compErrCode)
5948
*compErrCode = compilationNotNeeded;
5949
return 0; // mark that compilation is not yet done
5950
}
5951
}
5952
}
5953
}
5954
}
5955
else
5956
{
5957
debugPrint("synchronous");
5958
}
5959
5960
#if defined(J9VM_OPT_METHOD_HANDLE)
5961
// Check to make sure we never queue a thunk archetype
5962
// See JTC-JAT 56314
5963
if (details.isOrdinaryMethod() || details.isMethodInProgress())
5964
{
5965
J9Method *method = (J9Method*)details.getMethod();
5966
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
5967
5968
if (_J9ROMMETHOD_J9MODIFIER_IS_SET(romMethod, J9AccMethodFrameIteratorSkip))
5969
{
5970
if (details.isMethodHandleThunk())
5971
{
5972
if (compErrCode)
5973
*compErrCode = compilationFailure;
5974
5975
debugPrint(vmThread, "\tapplication thread releasing compilation monitor - trying to compile thunk archetype\n");
5976
debugPrint(vmThread, "-CM\n");
5977
releaseCompMonitor(vmThread);
5978
return 0; // In prod, it's safe just to fail to queue the method
5979
}
5980
else
5981
{
5982
TR_ASSERT(0, "Should never attempt a JavaOrdinaryMethod compilation on a method with the J9AccMethodFrameIteratorSkip flag");
5983
Assert_JIT_unreachable();
5984
}
5985
}
5986
}
5987
#endif /* defined(J9VM_OPT_METHOD_HANDLE) */
5988
5989
TR_YesNoMaybe methodIsInSharedCache = TR_no;
5990
bool useCodeFromSharedCache = false;
5991
#if defined(J9VM_INTERP_AOT_RUNTIME_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))
5992
// Check to see if we find the method in the shared cache
5993
// If yes, raise the priority to be processed ahead of other methods
5994
//
5995
5996
if (TR::Options::sharedClassCache() && !TR::Options::getAOTCmdLineOptions()->getOption(TR_NoLoadAOT) && details.isOrdinaryMethod())
5997
{
5998
if (!isJNINative(method) && !isCompiled(method))
5999
{
6000
// If the method is in shared cache but we decide not to take it from there
6001
// we must bump the count, because this is a method whose count was decreased to scount
6002
// We can get the answer wrong if the method was not in the cache to start with, but other
6003
// other JVM added the method to the cache meanwhile. The net effect is that the said
6004
// method may have its count bumped up and compiled later
6005
//
6006
if (vmThread->javaVM->sharedClassConfig->existsCachedCodeForROMMethod(vmThread, fe->getROMMethodFromRAMMethod(method)))
6007
{
6008
if (static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader == TR_yes)
6009
{
6010
methodIsInSharedCache = TR_yes;
6011
useCodeFromSharedCache = true;
6012
}
6013
else
6014
{
6015
TR_ASSERT_FATAL(static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader != TR_maybe, "Should not be possible for aotValidHeader to be TR_maybe at this point\n");
6016
}
6017
}
6018
}
6019
}
6020
#endif // defined(J9VM_INTERP_AOT_RUNTIME_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))
6021
6022
// determine priority
6023
CompilationPriority compPriority = CP_SYNC_NORMAL;
6024
if (async)
6025
{
6026
if (details.isMethodInProgress())
6027
compPriority = CP_ASYNC_BELOW_MAX;
6028
else if (details.isMethodHandleThunk())
6029
{
6030
if (static_cast<J9::MethodHandleThunkDetails &>(details).isShareable())
6031
{
6032
// Shareable thunks are quick to compile and provide much benefit over interpreter
6033
//
6034
compPriority = CP_ASYNC_ABOVE_NORMAL;
6035
}
6036
else if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableReducedPriorityForCustomMethodHandleThunks))
6037
{
6038
// Custom thunks are expensive to compile and likely provide less benefit
6039
// than compiling the java code that calls (and hopefully inlines) them.
6040
//
6041
compPriority = CP_ASYNC_BELOW_NORMAL;
6042
}
6043
}
6044
else
6045
{
6046
compPriority = CP_ASYNC_NORMAL;
6047
if (oldStartPC) // compiled method
6048
{
6049
TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(oldStartPC);
6050
TR_ASSERT(bodyInfo, "assertion failure: bodyInfo is NULL");
6051
6052
TR_PersistentMethodInfo *methodInfo = bodyInfo->getMethodInfo();
6053
TR_ASSERT(methodInfo, "assertion failure: methodInfo is NULL");
6054
6055
TR_Hotness hotness = bodyInfo->getHotness();
6056
6057
TR_Hotness nextHotness = optimizationPlan->getOptLevel();
6058
6059
6060
// Recompilations of profiling bodies are problematic when a large number of
6061
// threads is used and the compilation thread is starved; once we decided we
6062
// are done with the profiling step we must compile the next body sooner rather
6063
// than later
6064
if (bodyInfo->getIsProfilingBody() && !TR::Options::getCmdLineOptions()->getOption(TR_DisablePostProfileCompPriorityBoost))
6065
{
6066
if (getMethodQueueSize() > TR::Options::_compPriorityQSZThreshold)
6067
compPriority = CP_ASYNC_ABOVE_NORMAL;
6068
}
6069
// decrease priority of upgrades
6070
// Also decrease priority of any recompilations during classLoadPhase
6071
// Also decrease priority of GCR recompilations
6072
// Also decrease priority of RI recompilations
6073
else if (optimizationPlan->isUpgradeRecompilation() ||
6074
getPersistentInfo()->isClassLoadingPhase() ||
6075
(bodyInfo->getUsesGCR() && nextHotness < hot) ||
6076
(methodInfo->getReasonForRecompilation() == TR_PersistentMethodInfo::RecompDueToRI))
6077
compPriority = CP_ASYNC_BELOW_NORMAL;
6078
// give priority to very-hot, scorching requests
6079
else if (nextHotness > hot && (dynamicThreadPriority() || compBudgetSupport()))
6080
compPriority = CP_ASYNC_ABOVE_NORMAL;
6081
// hot methods below 6% will be given lower priority
6082
else if (nextHotness == hot &&
6083
optimizationPlan->getPerceivedCPUUtil() <= (TR::Options::_sampleInterval * 1000 / TR::Options::_veryHotSampleThreshold) &&
6084
bodyInfo->getSamplingRecomp()) // recompilation triggered through sampling (as opposed to EDO)
6085
{
6086
compPriority = CP_ASYNC_BELOW_NORMAL;
6087
//fprintf(stderr, "CP_ASYNC_BELOW_NORMAL\n");
6088
}
6089
}
6090
else // interpreted method
6091
{
6092
// increase priority of JNI thunks
6093
if (method && isJNINative(method))
6094
compPriority = CP_ASYNC_ABOVE_NORMAL;
6095
#if defined(J9VM_INTERP_AOT_RUNTIME_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))
6096
else if (useCodeFromSharedCache) // Use higher priority for methods from shared cache
6097
compPriority = CP_ASYNC_BELOW_MAX;
6098
#endif
6099
}
6100
}
6101
if (TR::Options::getCmdLineOptions()->getOption(TR_EnableEarlyCompilationDuringIdleCpu) &&
6102
oldStartPC == 0 && // interpreted method
6103
compPriority <= CP_ASYNC_NORMAL &&
6104
details.isOrdinaryMethod() && // exclude DLT and thunks
6105
!useCodeFromSharedCache && // exclude AOT loads
6106
!isJNINative(method) // exclude JNI
6107
)
6108
{
6109
// Search the LPQ and if not found, add method to LPQ and bump invocation count
6110
// If method found, it means counter expired a second time, so move request to main queue
6111
TR_CompilationErrorCode err = scheduleLPQAndBumpCount(details, fe);
6112
if (err != compilationOK)
6113
{
6114
// Release the compilation lock before returning
6115
debugPrint(vmThread, "\tapplication thread releasing compilation monitor - comp.req. in progress\n");
6116
debugPrint(vmThread, "-CM\n");
6117
releaseCompMonitor(vmThread);
6118
if (compErrCode)
6119
*compErrCode = err;
6120
return 0; // mark that compilation is not yet done
6121
}
6122
}
6123
}// if (async)
6124
6125
6126
// Set up the compilation request
6127
//
6128
debugPrint(" compile request", method);
6129
6130
6131
TR_MethodToBeCompiled *entry =
6132
addMethodToBeCompiled(details, oldStartPC, compPriority, async,
6133
optimizationPlan, queued, methodIsInSharedCache);
6134
6135
if (entry == NULL)
6136
{
6137
releaseCompMonitor(vmThread);
6138
if (compErrCode)
6139
*compErrCode = compilationFailure;
6140
return 0; // We couldn't add a method entry to be compiled.
6141
}
6142
6143
#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
6144
if (details.isMethodInProgress() &&
6145
!isCompiled(method) &&
6146
*queued &&
6147
!TR::Options::getCmdLineOptions()->getOption(TR_DisableDLTrecompilationPrevention))
6148
{
6149
// Scan the queue for a J9 request of the same j9method and make this request synchronous
6150
// The DLT flag means that we cannot have JNI or newInstance
6151
if (!async)
6152
changeCompReqFromAsyncToSync(method);
6153
else
6154
{
6155
TR_MethodToBeCompiled *reqMe, *prevReq;
6156
for (prevReq=NULL, reqMe=_methodQueue; reqMe; prevReq = reqMe, reqMe = reqMe->_next)
6157
{
6158
if (!reqMe->isDLTCompile() && reqMe->getMethodDetails().getMethod() == method)
6159
break;
6160
}
6161
if (reqMe && reqMe->_priority<CP_ASYNC_ABOVE_NORMAL)
6162
{
6163
reqMe->_priority = CP_ASYNC_ABOVE_NORMAL;
6164
if (prevReq && prevReq->_priority<CP_ASYNC_ABOVE_NORMAL)
6165
{
6166
prevReq->_next = reqMe->_next;
6167
queueEntry(reqMe);
6168
}
6169
}
6170
}
6171
}
6172
#endif // J9VM_JIT_DYNAMIC_LOOP_TRANSFER
6173
6174
// If a request is already queued for this method, see if we need to block
6175
// waiting for the compilation result. Do not wait if the requester specifically asks
6176
// for an asynchronous compilation (very rare event possible due to some races)
6177
//
6178
if (!(*queued) && entry->_changedFromAsyncToSync && requireAsyncCompile != TR_yes)
6179
{
6180
async = false;
6181
forcedSync = true;
6182
}
6183
entry->_async = async;
6184
6185
// no need to grab slot monitor or releasing VM access if we are doing async
6186
if (async)
6187
{
6188
printQueue();
6189
6190
// The compilation thread may be running at very low priority
6191
// Speed it up
6192
/*
6193
if (dynamicThreadPriority())
6194
{
6195
if (compPriority >= CP_ASYNC_ABOVE_NORMAL)
6196
{
6197
changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 10);
6198
}
6199
else if (getMethodQueueSize() >= LARGE_QUEUE)
6200
{
6201
changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 13);
6202
}
6203
else if (getCompThreadPriority() < J9THREAD_PRIORITY_NORMAL)
6204
{
6205
changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 14);
6206
}
6207
}
6208
*/
6209
#ifdef STATS
6210
//if (compPriority >= CP_ASYNC_ABOVE_NORMAL)
6211
// fprintf(stderr, "Adding request at priority CP_ASYNC_ABOVE_NORMAL\n");
6212
#endif
6213
6214
// We can avoid notifying the compilation thread if there were
6215
// other requests in the compilation queue
6216
// However we have to consider the case when one of the comp threads (though active)
6217
// is waiting on comp monitor because it wants the avoid two hot concurrent compilations
6218
// (if the really active comp thread gets suspended we remain with just one comp thread
6219
// sleeping and no notification will be sent)
6220
if (getMethodQueueSize() <= 1 ||
6221
getNumCompThreadsJobless() > 0) // send notification if any thread is sleeping on comp monitor waiting for suitable work
6222
{
6223
debugPrint(vmThread, "\tnotifying the compilation thread of the compile request\n");
6224
getCompilationMonitor()->notifyAll();
6225
debugPrint(vmThread, "ntfy-CM\n");
6226
}
6227
// TODO find a way to wake up only one compilation thread
6228
6229
// Release the compilation monitor
6230
//
6231
debugPrint(vmThread, "\tapplication thread releasing compilation monitor\n");
6232
debugPrint(vmThread, "-CM\n");
6233
releaseCompMonitor(vmThread);
6234
6235
if (compErrCode)
6236
*compErrCode = compilationInProgress;
6237
6238
startPC = 0; // return 0 to show the compilation hasn't already been done
6239
}
6240
else // synchronous request
6241
{
6242
TR_ASSERT(requireAsyncCompile != TR_yes, "An async compile request is being forced to go in sync");
6243
6244
// Grab the application thread monitor
6245
//
6246
debugPrint(vmThread, "\tapplication thread acquiring monitor for queue slot\n");
6247
entry->acquireSlotMonitor(vmThread);
6248
debugPrint(vmThread, "+AM-", entry);
6249
6250
printQueue();
6251
// synchronous requests must receive immediate attention
6252
if (dynamicThreadPriority())
6253
changeCompThreadPriority(J9THREAD_PRIORITY_MAX, 11);
6254
debugPrint(vmThread, "\tnotifying the compilation thread of the compile request\n");
6255
getCompilationMonitor()->notifyAll();
6256
debugPrint(vmThread, "ntfy-CM\n");
6257
6258
// Temporary sanity check
6259
TR_ASSERT_FATAL(entry->_numThreadsWaiting != 0x7fff, "ERROR _numThreadsWaiting is about to overflow\n");
6260
6261
// Before releasing the compilation monitor, mark that we have one more thead waiting for this entry
6262
//
6263
entry->_numThreadsWaiting++;
6264
6265
// Release the compilation monitor
6266
//
6267
debugPrint(vmThread, "\tapplication thread releasing compilation monitor\n");
6268
debugPrint(vmThread, "-CM\n");
6269
releaseCompMonitor(vmThread);
6270
6271
// Release VM Access
6272
//
6273
debugPrint(vmThread, "\tapplication thread releasing VM access\n");
6274
releaseVMAccess(vmThread);
6275
debugPrint(vmThread, "-VMacc\n");
6276
6277
// wait for compilation to finish.
6278
//
6279
debugPrint(vmThread, "\tapplication thread waiting for compile to finish\n");
6280
debugPrint(vmThread, "wait-", entry);
6281
entry->getMonitor()->wait();
6282
6283
debugPrint(vmThread, "\tapplication thread re-acquired queue slot monitor (got notification of compilation)\n");
6284
debugPrint(vmThread, "+AM-", entry);
6285
6286
// Now the compilation should have been done (or the compilation
6287
// thread has been stopped or suspended).
6288
//
6289
startPC = entry->_newStartPC;
6290
// For HCR should we return 0 or oldStartPC?
6291
if (startPC && startPC != oldStartPC)
6292
debugPrint("\tcompile request succeeded", entry->getMethodDetails(), vmThread);
6293
else
6294
debugPrint("\tcompile request failed", entry->getMethodDetails(), vmThread);
6295
if (compErrCode)
6296
*compErrCode = (TR_CompilationErrorCode)entry->_compErrCode;
6297
6298
//freeMethodToBeCompiled(entry);
6299
6300
// Release the monitor now
6301
//
6302
debugPrint(vmThread, "\tapplication thread releasing AppMonitor\n");
6303
debugPrint(vmThread, "-AM-", entry);
6304
6305
entry->releaseSlotMonitor(vmThread);
6306
6307
// Grab the compilation mutex to be able to decrement numThreadsWaiting
6308
// and access entryShouldBeDeallocated
6309
// When numThreadsWaiting reaches 0, the entry can be reused or deallocated
6310
//
6311
acquireCompMonitor(vmThread);
6312
6313
#if defined(J9VM_OPT_JITSERVER)
6314
// If a remote sync compilation has been changed to a local sync compilation,
6315
// queue a new remote async compilation entry for this method.
6316
// - The second compilation is queued only when this is the last thread waiting
6317
// for the compilation of the method.
6318
// - If for any reason, the current compilation request is changed to a sync
6319
// compilation from an async compilation, it probably means we can’t do an
6320
// async compilation. Don't queue the second async remote compilation.
6321
if (entry->hasChangedToLocalSyncComp() &&
6322
(entry->_numThreadsWaiting <= 1) &&
6323
!forcedSync &&
6324
(startPC && startPC != oldStartPC))
6325
{
6326
void *currOldStartPC = startPCIfAlreadyCompiled(vmThread, details, startPC);
6327
// If currOldStartPC is NULL, the method body defined by startPC has not been
6328
// recompiled. We will queue the second remote aync compilation here. Otherwise,
6329
// another thread is doing the recompilation and will take care of queueing
6330
// the second compilation.
6331
if (!currOldStartPC)
6332
{
6333
CompilationPriority compPriority = CP_ASYNC_NORMAL;
6334
bool queuedForRemote = false;
6335
bool isAsync = true;
6336
TR_OptimizationPlan *plan = TR_OptimizationPlan::alloc(entry->_origOptLevel);
6337
TR_YesNoMaybe mthInSharedCache = TR_no;
6338
6339
if (plan)
6340
{
6341
TR_MethodToBeCompiled *entryRemoteCompReq = addMethodToBeCompiled(details, currOldStartPC, compPriority, isAsync,
6342
plan, &queuedForRemote, mthInSharedCache);
6343
6344
if (entryRemoteCompReq)
6345
{
6346
entryRemoteCompReq->_async = isAsync;
6347
6348
if (getMethodQueueSize() <= 1 ||
6349
getNumCompThreadsJobless() > 0) // send notification if any thread is sleeping on comp monitor waiting for suitable work
6350
{
6351
getCompilationMonitor()->notifyAll();
6352
}
6353
if (TR::Options::getJITCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))
6354
TR_VerboseLog::writeLineLocked(TR_Vlog_CR,"%p Queued a remote async compilation: entry=%p, j9method=%p",
6355
vmThread, entryRemoteCompReq, entryRemoteCompReq->getMethodDetails().getMethod());
6356
}
6357
if (!queuedForRemote)
6358
TR_OptimizationPlan::freeOptimizationPlan(plan);
6359
}
6360
}
6361
}
6362
#endif /* defined(J9VM_OPT_JITSERVER) */
6363
6364
entry->_numThreadsWaiting--;
6365
6366
TR_ASSERT_FATAL(!(entry->_freeTag & (ENTRY_DEALLOCATED|ENTRY_IN_POOL_FREE)), "Java thread waking up with a freed entry");
6367
6368
if (entry->_numThreadsWaiting == 0) // The tag should be ENTRY_IN_POOL_NOT_FREE
6369
if (entry->_freeTag & ENTRY_IN_POOL_NOT_FREE) // comp thread has recycled this entry
6370
entry->_freeTag |= ENTRY_IN_POOL_FREE;
6371
//else Do nothing cause we'll wait for the comp thread to completely recycle the entry
6372
6373
// Temporary sanity check because PPC does not use prod with assumes.
6374
TR_ASSERT_FATAL(entry->_numThreadsWaiting >= 0, "ERROR _numThreadsWaiting has become negative");
6375
6376
if (entry->_entryShouldBeDeallocated && entry->_numThreadsWaiting == 0)
6377
{
6378
entry->shutdown();
6379
PORT_ACCESS_FROM_JITCONFIG(_jitConfig);
6380
j9mem_free_memory(entry);
6381
}
6382
releaseCompMonitor(vmThread);
6383
6384
// Reacquire VM access
6385
//
6386
acquireVMAccess(vmThread);
6387
debugPrint(vmThread, "+VMacc\n");
6388
} // synchronous requests
6389
6390
return startPC;
6391
}
6392
6393
#ifdef TR_HOST_S390
6394
void
6395
TR::CompilationInfoPerThreadBase::outputVerboseMMapEntry(
6396
TR_ResolvedMethod *compilee,
6397
const struct tm &date,
6398
const struct timeval &time,
6399
void *startPC,
6400
void *endPC,
6401
const char *fmt,
6402
const char *profiledString,
6403
const char *compileString
6404
)
6405
{
6406
TR_VerboseLog::writeLine(
6407
TR_Vlog_MMAP,
6408
fmt,
6409
date.tm_hour,
6410
date.tm_min,
6411
date.tm_sec,
6412
time.tv_usec,
6413
compilee->classNameLength(), compilee->classNameChars(),
6414
compilee->nameLength(), compilee->nameChars(),
6415
compilee->signatureLength(), compilee->signatureChars(),
6416
"[",
6417
profiledString,
6418
compileString,
6419
"]",
6420
startPC,
6421
endPC
6422
);
6423
}
6424
6425
void
6426
TR::CompilationInfoPerThreadBase::outputVerboseMMapEntries(
6427
TR_ResolvedMethod *compilee,
6428
TR_MethodMetaData *metaData,
6429
const char *profiledString,
6430
const char *compileString
6431
)
6432
{
6433
6434
#if defined(TR_HOST_64BIT) || defined(TR_TARGET_64BIT)
6435
static const char *fmtNoEOL="\n%02d%02d%02d.%06ld %.*s,%.*s,%.*s%s%s%s%s,%016p,%016p";
6436
static const char * fmtEOL="\n%02d%02d%02d.%06ld %.*s,%.*s,%.*s%s%s%s%s,%016p,%016p\n";
6437
#else
6438
static const char *fmtNoEOL="\n%02d%02d%02d.%06ld %.*s,%.*s,%.*s%s%s%s%s,%x,%x";
6439
static const char * fmtEOL="\n%02d%02d%02d.%06ld %.*s,%.*s,%.*s%s%s%s%s,%x,%x\n";
6440
#endif
6441
struct timeval time;
6442
gettimeofday(&time, 0);
6443
struct tm date;
6444
if (!localtime_r(&time.tv_sec, &date)) return;
6445
6446
TR_VerboseLog::CriticalSection vlogLock;
6447
outputVerboseMMapEntry(
6448
compilee,
6449
date,
6450
time,
6451
reinterpret_cast<void *>(metaData->startPC),
6452
reinterpret_cast<void *>(metaData->endWarmPC),
6453
fmtNoEOL,
6454
profiledString,
6455
compileString
6456
);
6457
if (metaData->startColdPC)
6458
outputVerboseMMapEntry(
6459
compilee,
6460
date,
6461
time,
6462
reinterpret_cast<void *>(metaData->startColdPC),
6463
reinterpret_cast<void *>(metaData->endPC),
6464
fmtEOL,
6465
profiledString,
6466
compileString
6467
);
6468
}
6469
#endif // ifdef TR_HOST_S390
6470
6471
// work around spill issue on this method
6472
#if defined(TR_HOST_S390)
6473
#pragma option_override(TR::CompilationInfo::compile(J9VMThread *, TR_MethodToBeCompiled *, bool), "OPT(SPILL,256)")
6474
#endif
6475
6476
#if defined(J9VM_INTERP_AOT_RUNTIME_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))
6477
TR_MethodMetaData *
6478
TR::CompilationInfoPerThreadBase::installAotCachedMethod(
6479
J9VMThread *vmThread,
6480
const void *aotCachedMethod,
6481
J9Method *method,
6482
TR_FrontEnd *fe,
6483
TR::Options *options,
6484
TR_ResolvedMethod *compilee,
6485
TR_MethodToBeCompiled *entry,
6486
TR::Compilation *compiler
6487
)
6488
{
6489
// This function assumes that compilation monitor is released coming in. This is to allow relocations
6490
// to be able to grow code caches. We also assume the queue slot monitor to be released coming in.
6491
6492
if (entry)
6493
TR_ASSERT(method == entry->getMethodDetails().getMethod(), "assertion failure");
6494
6495
// We need to perform the relocation for the method in the shared classes cache
6496
TR::CodeCache *aotMCCRuntimeCodeCache = NULL;
6497
6498
const J9JITDataCacheHeader *cacheEntry = static_cast<const J9JITDataCacheHeader *>(aotCachedMethod);
6499
if (entry)
6500
TR_ASSERT(entry->_oldStartPC == 0, "assertion failure"); // we only locate first time compilations
6501
6502
TR_MethodMetaData *metaData;
6503
int32_t returnCode = 0;
6504
6505
if (_compInfo.getPersistentInfo()->isRuntimeInstrumentationEnabled())
6506
{
6507
reloRuntime()->setIsLoading();
6508
reloRuntime()->initializeHWProfilerRecords(compiler);
6509
}
6510
6511
metaData = reloRuntime()->prepareRelocateAOTCodeAndData(vmThread,
6512
fe,
6513
aotMCCRuntimeCodeCache,
6514
cacheEntry,
6515
method,
6516
false,
6517
options,
6518
compiler,
6519
compilee);
6520
setMetadata(metaData);
6521
returnCode = reloRuntime()->returnCode();
6522
6523
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
6524
TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH,
6525
"prepareRelocateAOTCodeAndData results: j9method=%p metaData=%p returnCode=%d method=%s",
6526
method, metaData, returnCode, compiler->signature());
6527
6528
if (_compInfo.getPersistentInfo()->isRuntimeInstrumentationEnabled())
6529
{
6530
reloRuntime()->resetIsLoading();
6531
}
6532
6533
if (metaData)
6534
{
6535
UDATA reloTime = 0;
6536
6537
if (TrcEnabled_Trc_JIT_AotLoadEnd)
6538
{
6539
PORT_ACCESS_FROM_JITCONFIG(_jitConfig);
6540
reloTime = j9time_usec_clock() - reloRuntime()->reloStartTime();
6541
6542
Trc_JIT_AotLoadEnd(vmThread, compiler->signature(),
6543
metaData->startPC, metaData->endWarmPC, metaData->startColdPC, metaData->endPC,
6544
reloTime, method, metaData, _compInfo.getMethodQueueSize(),
6545
TR::CompilationInfo::getMethodBytecodeSize(method),
6546
0);
6547
}
6548
6549
if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileEnd))
6550
{
6551
if (reloTime == 0)
6552
{
6553
PORT_ACCESS_FROM_JITCONFIG(_jitConfig);
6554
reloTime = j9time_usec_clock() - reloRuntime()->reloStartTime();
6555
}
6556
6557
TR_VerboseLog::CriticalSection vlogLock;
6558
TR_VerboseLog::write(TR_Vlog_COMP, "(AOT load) ");
6559
CompilationInfo::printMethodNameToVlog(method);
6560
TR_VerboseLog::write(" @ " POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT, metaData->startPC, metaData->endWarmPC);
6561
TR_VerboseLog::write(" Q_SZ=%d Q_SZI=%d QW=%d j9m=%p bcsz=%u", _compInfo.getMethodQueueSize(), _compInfo.getNumQueuedFirstTimeCompilations(),
6562
_compInfo.getQueueWeight(), method, _compInfo.getMethodBytecodeSize(method));
6563
6564
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
6565
{
6566
TR_VerboseLog::write(" time=%dus", (uint32_t)reloTime);
6567
}
6568
if (entry)
6569
TR_VerboseLog::write(" compThreadID=%d", getCompThreadId());
6570
6571
TR_VerboseLog::writeLine("");
6572
}
6573
6574
#if defined(TR_HOST_S390)
6575
if (TR::Options::getVerboseOption(TR_VerboseMMap))
6576
{
6577
TR_J9VMBase *vm = TR_J9VMBase::get(_jitConfig, vmThread);
6578
TR_ResolvedMethod *compilee = vm->createResolvedMethod(compiler->trMemory(), (TR_OpaqueMethodBlock *)method);
6579
outputVerboseMMapEntries(compilee, metaData, "AOT ", "load");
6580
}
6581
#endif
6582
6583
if (J9_EVENT_IS_HOOKED(_jitConfig->javaVM->hookInterface, J9HOOK_VM_DYNAMIC_CODE_LOAD))
6584
{
6585
OMR::CodeCacheMethodHeader *ccMethodHeader;
6586
ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(_jitConfig->javaVM->hookInterface, vmThread, method, (U_8*)metaData->startPC, metaData->endWarmPC - metaData->startPC, "JIT warm body", metaData);
6587
if (metaData->startColdPC)
6588
{
6589
// Register the cold code section too
6590
//
6591
ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(_jitConfig->javaVM->hookInterface, vmThread, method, (U_8*)metaData->startColdPC, metaData->endPC - metaData->startColdPC, "JIT cold body", metaData);
6592
}
6593
ccMethodHeader = getCodeCacheMethodHeader((char *)metaData->startPC, 32, metaData);
6594
if (ccMethodHeader && (metaData->bodyInfo != NULL))
6595
{
6596
J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get((void *)metaData->startPC);
6597
if (linkageInfo->isRecompMethodBody())
6598
{
6599
ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(_jitConfig->javaVM->hookInterface, vmThread, method, (U_8 *)((char*)ccMethodHeader->_eyeCatcher+4), metaData->startPC - (UDATA)((char*)ccMethodHeader->_eyeCatcher+4), "JIT method header", metaData);
6600
}
6601
}
6602
}
6603
6604
++_compInfo._statNumMethodsFromSharedCache;
6605
}
6606
else // relocation failed
6607
{
6608
if (entry)
6609
{
6610
entry->_compErrCode = returnCode;
6611
entry->setAotCodeToBeRelocated(NULL); // reset if relocation failed
6612
entry->_tryCompilingAgain = _compInfo.shouldRetryCompilation(entry, compiler); // this will set entry->_doNotUseAotCodeFromSharedCache = true;
6613
6614
// Feature [Defect 172216/180384]: Implement hints for failed AOT validations. The idea is that the failed validations are due to the
6615
// fact that AOT methods are loaded at a lower count than when they were compiled so the JVM is given less opportunity to resolve things.
6616
// The new hint tells us that a previous relocation failed a validation so specify a higher scount for the next run to give it more chance
6617
// to resolve things.
6618
switch (returnCode)
6619
{
6620
case compilationAotValidateFieldFailure:
6621
case compilationAotStaticFieldReloFailure:
6622
case compilationAotClassReloFailure:
6623
if ((options->getInitialBCount() != 0) &&
6624
(options->getInitialCount() != 0))
6625
{
6626
TR_J9SharedCache *sc = (TR_J9SharedCache *) (compiler->fej9()->sharedCache());
6627
sc->addHint(method, TR_HintFailedValidation);
6628
}
6629
break;
6630
}
6631
}
6632
}
6633
return metaData;
6634
}
6635
#endif // defined(J9VM_INTERP_AOT_RUNTIME_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))
6636
6637
//--------------- queueAOTUpgrade ----------
6638
// The entry currently being processed will be cloned with the clone being an upgrade
6639
// request (which will be performed at cold).
6640
// The j9method currently being compiled, must have been compiled successfully because we use its startPC.
6641
// This routine must be called with compilationMonitor in hand.
6642
// This routine is normally invoked by the compilation thread.
6643
// I think we can avoid scanning the queue for a duplicate because such a duplicate cannot exist
6644
// long as the original is still being processed.
6645
//-----------------------------------------
6646
void TR::CompilationInfo::queueForcedAOTUpgrade(TR_MethodToBeCompiled *originalEntry, uint16_t hints, TR_FrontEnd *fe)
6647
{
6648
#if defined(J9VM_INTERP_AOT_RUNTIME_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390))
6649
6650
TR_ASSERT(!originalEntry->isDLTCompile(), "No DLTs allowed in queueForcedAOTUpgrade"); // no DLT here
6651
TR_ASSERT(originalEntry->_compInfoPT && originalEntry->_compInfoPT->_methodBeingCompiled == originalEntry, "assertion failure");
6652
// This must be an AOT load
6653
if (!TR::Options::getCmdLineOptions()->allowRecompilation())
6654
return;
6655
6656
// TODO: if this is already available, pass it as a parameter
6657
TR_PersistentMethodInfo *methodInfo = TR::Recompilation::getMethodInfoFromPC(originalEntry->_newStartPC);
6658
if (!methodInfo)
6659
return;
6660
6661
// If quickstart and we are in startup phase, do not perform the
6662
// upgrade hints for some methods that we know are memory expensive
6663
if (TR::Options::isQuickstartDetected() && // TODO: we may want to apply the same logic for server mode as well
6664
_jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP)
6665
{
6666
if (hints & TR_HintLargeMemoryMethodC)
6667
return; // Don't want to increase the footprint
6668
}
6669
6670
// Search for an empty entry in the methodPool.
6671
TR_MethodToBeCompiled *cur = getCompilationQueueEntry();
6672
if (!cur)
6673
return;
6674
6675
// must create a new optimization plan
6676
TR_Hotness hotness = cold;
6677
bool doProfiling = false;
6678
if (hints & TR_HintScorching)
6679
{
6680
hotness = veryHot;
6681
doProfiling = !TR::Options::getCmdLineOptions()->getOption(TR_DisableProfiling) &&
6682
!methodInfo->profilingDisabled();
6683
}
6684
else if (hints & TR_HintHot)
6685
{
6686
hotness = hot;
6687
}
6688
else // See if we should upgrade at warm
6689
{
6690
// Do not upgrade at warm if the compilation is known to take a lot of memory or CPU
6691
// and we are in startup phase
6692
if (_jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP || !(hints & (TR_HintLargeMemoryMethodW | TR_HintLargeCompCPUW)))
6693
{
6694
if (!TR::Options::isQuickstartDetected())
6695
hotness = warm;
6696
else if (TR::Options::getCmdLineOptions()->getOption(TR_UpgradeBootstrapAtWarm))// This is a JIT option because it pertains to JIT compilations
6697
{
6698
// To reduce affect on short applications like tomcat
6699
// upgrades to warm should be performed only outside the grace period
6700
//if (getPersistentInfo()->getElapsedTime() >= (uint64_t)getPersistentInfo()->getClassLoadingPhaseGracePeriod())
6701
{
6702
TR_OpaqueMethodBlock *method = (TR_OpaqueMethodBlock *) originalEntry->getMethodDetails().getMethod();
6703
TR_J9VMBase *fej9 = (TR_J9VMBase *)fe;
6704
if (fej9->isClassLibraryMethod(method))
6705
hotness = warm;
6706
}
6707
}
6708
}
6709
}
6710
TR_OptimizationPlan *plan = TR_OptimizationPlan::alloc(hotness, doProfiling, true);
6711
if (!plan) // OOM
6712
{
6713
cur->_freeTag = ENTRY_INITIALIZED; // entry must appear as being initialized
6714
6715
// put back into the pool
6716
recycleCompilationEntry(cur);
6717
return;
6718
}
6719
6720
// Do not mark this compilation as un upgrade; otherwise we would try again to store
6721
// a hint in the shared cache when the upgrade is complete
6722
//
6723
cur->initialize(originalEntry->getMethodDetails(), originalEntry->_newStartPC, CP_ASYNC_BELOW_NORMAL, plan);
6724
cur->_jitStateWhenQueued = getPersistentInfo()->getJitState();
6725
6726
J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(originalEntry->_newStartPC);
6727
linkageInfo->setIsBeingRecompiled(); // mark that we try to compile it
6728
6729
methodInfo->setNextCompileLevel(plan->getOptLevel(), plan->insertInstrumentation());
6730
methodInfo->setReasonForRecompilation(TR_PersistentMethodInfo::RecompDueToForcedAOTUpgrade);
6731
_statNumForcedAotUpgrades++;
6732
6733
cur->_entryTime = getPersistentInfo()->getElapsedTime(); // cheaper version
6734
incrementMethodQueueSize(); // one more method added to the queue
6735
// No need to increment _numQueuedFirstTimeCompilations because this is a recompilation
6736
6737
// Must determine the entry weight; let's use something simpler
6738
// because we know the opt level can be either cold or warm
6739
// and we know this is not JNI or other thunk
6740
//
6741
uint8_t entryWeight; // must be less than 256
6742
switch (hotness)
6743
{
6744
case cold: entryWeight = COLD_WEIGHT; break;
6745
case warm:
6746
{
6747
J9Method *method = originalEntry->getMethodDetails().getMethod();
6748
J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
6749
if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))
6750
entryWeight = WARM_LOOPY_WEIGHT;
6751
else
6752
entryWeight = WARM_LOOPLESS_WEIGHT;
6753
}
6754
break;
6755
case hot: entryWeight = HOT_WEIGHT; break;
6756
case veryHot: entryWeight = VERY_HOT_WEIGHT; break;
6757
default: entryWeight = THUNKS_WEIGHT;
6758
} // end switch
6759
6760
cur->_weight = entryWeight;
6761
_queueWeight += (int32_t)entryWeight; // increase queue weight
6762
6763
cur->_async = true;
6764
6765
// Do not activate any new compilation thread
6766
6767
// Instead of searching for a matching entry, just queue this entry
6768
// We can away with scanning the queue for duplicates because the original method is still
6769
// at the head of the queue
6770
//
6771
queueEntry(cur);
6772
//fprintf(stderr, "Forcefully upgraded j9method %p (entry=%p)\n", cur->_method, cur);
6773
#endif // #if defined(J9VM_INTERP_AOT_RUNTIME_SUPPORT) && defined(J9VM_OPT_SHARED_CLASSES) && (defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390))
6774
}
6775
6776
6777
// This method is executed by compilation threads at the end of a compilation
6778
// and needs to be executed with the compQueueMonitor in hand.
6779
// Prerequisites: getCompilation() and getMetadata() return valid answers
6780
void
6781
TR::CompilationInfoPerThreadBase::generatePerfToolEntry()
6782
{
6783
#if defined(LINUX)
6784
TR_ASSERT(getCompilation() && getMetadata(), "generatePerfToolEntry() must be executed only for successful compilations");
6785
// At this point we have the compilationQueueMonitor so we don't run into concurrency issues
6786
static bool firstAttempt = true;
6787
if (firstAttempt)
6788
{
6789
firstAttempt = false;
6790
uintptr_t jvmPid = getCompilation()->fej9()->getProcessID();
6791
static const int maxPerfFilenameSize = 15 + sizeof(jvmPid)* 3; // "/tmp/perf-%ld.map"
6792
char perfFilename[maxPerfFilenameSize] = { 0 };
6793
6794
bool truncated = TR::snprintfTrunc(perfFilename, maxPerfFilenameSize, "/tmp/perf-%ld.map", jvmPid);
6795
if (!truncated)
6796
{
6797
TR::CompilationInfoPerThreadBase::_perfFile = j9jit_fopen(perfFilename, "a", true);
6798
}
6799
if (!getPerfFile()) // couldn't open the file
6800
{
6801
if (TR::Options::getJITCmdLineOptions()->getVerboseOption(TR_VerboseCompFailure))
6802
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE, "t=%u WARNING: Cannot open perf tool file: %s",
6803
(uint32_t)_compInfo.getPersistentInfo()->getElapsedTime(), perfFilename); // even if snprintf failed above we should still be ok.
6804
// Do we want a message without verbose log being specified?
6805
}
6806
}
6807
if (getPerfFile())
6808
{
6809
j9jit_fprintf(getPerfFile(), "%p %lX %s_%s\n", getMetadata()->startPC, getMetadata()->endWarmPC - getMetadata()->startPC,
6810
getCompilation()->signature(), getCompilation()->getHotnessName(getCompilation()->getMethodHotness()));
6811
// If there is a cold section, add another line
6812
if (getMetadata()->startColdPC)
6813
{
6814
j9jit_fprintf(getPerfFile(), "%p %lX %s_%s\n", getMetadata()->startColdPC, getMetadata()->endPC - getMetadata()->startColdPC,
6815
getCompilation()->signature(), getCompilation()->getHotnessName(getCompilation()->getMethodHotness())); // should we change the name of the method?
6816
}
6817
// Flushing degrades performance, but ensures that we have the data
6818
// written even if the JVM is abruptly terminated
6819
j9jit_fflush(getPerfFile());
6820
}
6821
#endif
6822
}
6823
6824
const void*
6825
TR::CompilationInfoPerThreadBase::findAotBodyInSCC(J9VMThread *vmThread, const J9ROMMethod *romMethod)
6826
{
6827
#if defined(J9VM_INTERP_AOT_RUNTIME_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))
6828
#if defined(J9VM_OPT_JITSERVER)
6829
TR_ASSERT(!TR::CompilationInfo::getStream(), "This function should not be called at the server because SCC does not exist at the server.");
6830
#endif /* defined(J9VM_OPT_JITSERVER) */
6831
UDATA flags = 0;
6832
const void *aotCachedMethod = vmThread->javaVM->sharedClassConfig->findCompiledMethodEx1(vmThread, romMethod, &flags);
6833
if (!(flags & J9SHR_AOT_METHOD_FLAG_INVALIDATED))
6834
return aotCachedMethod; // possibly NULL
6835
else
6836
#endif
6837
return NULL;
6838
}
6839
6840
bool
6841
TR::CompilationInfoPerThreadBase::isMethodIneligibleForAot(J9Method *method)
6842
{
6843
const J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
6844
const J9ROMClass *romClass = J9_CLASS_FROM_METHOD(method)->romClass;
6845
J9UTF8 *className = J9ROMCLASS_CLASSNAME(romClass);
6846
6847
// Don't AOT-compile anything in j/l/i for now
6848
if (strncmp(utf8Data(className), "java/lang/invoke/", sizeof("java/lang/invoke/") - 1) == 0)
6849
return true;
6850
6851
if (J9UTF8_LENGTH(className) == 36 &&
6852
0 == memcmp(utf8Data(className), "com/ibm/rmi/io/FastPathForCollocated", 36))
6853
{
6854
J9UTF8 *utf8 = J9ROMMETHOD_NAME(romMethod);
6855
if (J9UTF8_LENGTH(utf8) == 21 &&
6856
0 == memcmp(J9UTF8_DATA(utf8), "isVMDeepCopySupported", 21))
6857
return true;
6858
}
6859
return false;
6860
}
6861
6862
#if defined(J9VM_OPT_JITSERVER)
6863
6864
bool
6865
TR::CompilationInfoPerThreadBase::isMemoryCheapCompilation(uint32_t bcsz, TR_Hotness optLevel)
6866
{
6867
if (optLevel > warm)
6868
{
6869
return false;
6870
}
6871
if (optLevel == warm && bcsz > 6) // For bcsz >= 7, scratch_mem can reach 7.5 MB which is deemed too much
6872
{
6873
return false;
6874
}
6875
// Look at the available resources and decide whether we can afford a local compilation
6876
// Ideally, we should consider network latency too, but that is too complicated
6877
//
6878
bool incompleteInfo = true;
6879
uint64_t freePhysicalMemorySizeB = _compInfo.computeAndCacheFreePhysicalMemory(incompleteInfo);
6880
// If memory information is not available, perform all compilations remotely for safety
6881
if (freePhysicalMemorySizeB == OMRPORT_MEMINFO_NOT_AVAILABLE || incompleteInfo)
6882
{
6883
return false;
6884
}
6885
// For very small amounts of free memory, send everything remotely
6886
if (freePhysicalMemorySizeB < 10 * 1024 * 1024)
6887
{
6888
return false;
6889
}
6890
if (freePhysicalMemorySizeB < 20 * 1024 * 1024) // 10MB <= freeMem < 20MB
6891
{
6892
// Very small methods at cold (expected to take 1MB max)
6893
return (optLevel <= cold) && (bcsz <= 4);
6894
}
6895
if (freePhysicalMemorySizeB < 100 * 1024 * 1024) // 20MB <= freeMem < 100MB
6896
{
6897
// All methods at noOpt, very small methods at cold/warm and medium sized methods at cold (expected to take 2.5MB max)
6898
return (optLevel < cold) || (bcsz <= 4) || (optLevel == cold && bcsz <= 31);
6899
}
6900
// freeMem >= 100MB
6901
// All methods at noOpt/cold and small methods at warm (expected to take 6MB max)
6902
return true; // Large methods at warm have already been filtered out above
6903
}
6904
6905
bool
6906
TR::CompilationInfoPerThreadBase::isCPUCheapCompilation(uint32_t bcsz, TR_Hotness optLevel)
6907
{
6908
double cpuEntitlement = _compInfo.getJvmCpuEntitlement();
6909
if (cpuEntitlement < 100.0)
6910
{
6911
return false;
6912
}
6913
if (cpuEntitlement < 150.0) // [100, 150)
6914
{
6915
// Keep local some noOpt/cold compilations
6916
if (optLevel >= warm || bcsz >= 32)
6917
{
6918
return false;
6919
}
6920
if (bcsz <= 7) // Small methods at noOpt/cold should be local
6921
{
6922
return true;
6923
}
6924
// If we have CPU available we could keep local even medium sized cold compilations
6925
CpuUtilization *cpuUtil = _compInfo.getCpuUtil();
6926
if (cpuUtil->isFunctional() &&
6927
_compInfo.getPersistentInfo()->getElapsedTime() >= TR::Options::_classLoadingPhaseInterval && // For first 0.5 sec we don't have valid data
6928
cpuUtil->getCpuIdle() >= 15 && // There is idle CPU to use
6929
cpuUtil->getVmCpuUsage() + 15 <= cpuEntitlement) // I am allowed to use 15% more CPU
6930
return true;
6931
else
6932
return false;
6933
}
6934
if (cpuEntitlement < 350.0) // [150, 350)
6935
{
6936
// Medium sized methods at noOpt/cold
6937
return (optLevel <= cold) && (bcsz <= 31);
6938
}
6939
6940
// CPU Entitlement >= 350%
6941
// All noOpt/cold methods and small warm methods
6942
return (optLevel <= cold) || (bcsz <= 5);
6943
}
6944
6945
bool
6946
TR::CompilationInfoPerThreadBase::cannotPerformRemoteComp()
6947
{
6948
return !JITServer::ClientStream::isServerCompatible(OMRPORT_FROM_J9PORT(_jitConfig->javaVM->portLibrary)) ||
6949
(!JITServerHelpers::isServerAvailable() && !JITServerHelpers::shouldRetryConnection(OMRPORT_FROM_J9PORT(_jitConfig->javaVM->portLibrary))) ||
6950
(TR::Compiler->target.cpu.isPower() && _jitConfig->inlineFieldWatches); // Power codegen is missing some FieldWatch relocation support
6951
}
6952
6953
bool
6954
TR::CompilationInfoPerThreadBase::preferLocalComp(const TR_MethodToBeCompiled *entry)
6955
{
6956
// As a heuristic, cold compilations could be performed locally because
6957
// they are supposed to be cheap with respect to memory and CPU, but
6958
// only if we think we have enough resources
6959
//
6960
if (TR::Options::getCmdLineOptions()->getOption(TR_EnableJITServerHeuristics))
6961
{
6962
TR_Hotness optLevel = entry->_optimizationPlan->getOptLevel();
6963
J9Method *method = entry->getMethodDetails().getMethod();
6964
uint32_t bcsz = TR::CompilationInfo::getMethodBytecodeSize(method);
6965
return isMemoryCheapCompilation(bcsz, optLevel) && isCPUCheapCompilation(bcsz, optLevel);
6966
}
6967
return false;
6968
}
6969
6970
void
6971
TR::CompilationInfoPerThreadBase::enterPerClientAllocationRegion()
6972
{
6973
// To use per-client memory, this thread must have a cached pointer to the client data
6974
ClientSessionData *clientData = getClientData();
6975
if (clientData && clientData->usesPerClientMemory())
6976
{
6977
_perClientPersistentMemory = clientData->persistentMemory();
6978
if (_compiler)
6979
_compiler->switchToPerClientMemory();
6980
}
6981
}
6982
6983
void
6984
TR::CompilationInfoPerThreadBase::exitPerClientAllocationRegion()
6985
{
6986
if (_compiler)
6987
_compiler->switchToGlobalMemory();
6988
_perClientPersistentMemory = NULL;
6989
}
6990
6991
void
6992
TR::CompilationInfoPerThreadBase::downgradeLocalCompilationIfLowPhysicalMemory(TR_MethodToBeCompiled *entry)
6993
{
6994
TR_ASSERT_FATAL(_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT,
6995
"Must be called on JITServer client");
6996
6997
J9Method *method = entry->getMethodDetails().getMethod();
6998
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableJITServerBufferedExpensiveCompilations) &&
6999
TR::Options::getCmdLineOptions()->allowRecompilation() &&
7000
!TR::CompilationInfo::isCompiled(method) && // do not downgrade recompilations
7001
(entry->_optimizationPlan->getOptLevel() >= warm ||
7002
// AOT compilations that are upgraded back to cheap-warm should be considered expensive
7003
(entry->_useAotCompilation && !TR::Options::getAOTCmdLineOptions()->getOption(TR_DisableAotAtCheapWarm))))
7004
{
7005
// Downgrade a forced local compilation, if the available client memory is low.
7006
bool incomplete;
7007
uint64_t freePhysicalMemorySizeB = _compInfo.computeAndCacheFreePhysicalMemory(incomplete, 10);
7008
int32_t numActiveThreads = _compInfo.getNumCompThreadsActive();
7009
if (freePhysicalMemorySizeB != OMRPORT_MEMINFO_NOT_AVAILABLE &&
7010
freePhysicalMemorySizeB <= (uint64_t)TR::Options::getSafeReservePhysicalMemoryValue() + (numActiveThreads + 4) * TR::Options::getScratchSpaceLowerBound())
7011
{
7012
if (TR::Options::isAnyVerboseOptionSet(
7013
TR_VerboseJITServer,
7014
TR_VerboseCompilationDispatch,
7015
TR_VerbosePerformance,
7016
TR_VerboseCompFailure))
7017
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "t=%6u Downgraded a forced local compilation to cold due to low memory: j9method=%p",
7018
(uint32_t)_compInfo.getPersistentInfo()->getElapsedTime(), method);
7019
entry->_optimizationPlan->setOptLevel(cold);
7020
entry->_optimizationPlan->setOptLevelDowngraded(true);
7021
entry->_optimizationPlan->setDisableGCR(); // disable GCR to prevent aggressive recompilation
7022
entry->_optimizationPlan->setUseSampling(false); // disable sampling to prevent spontaneous recompilation
7023
entry->setShouldUpgradeOutOfProcessCompilation(); // ask for an upgrade if the server becomes available
7024
}
7025
}
7026
}
7027
#endif /* defined(J9VM_OPT_JITSERVER) */
7028
7029
/**
7030
* @brief TR::CompilationInfoPerThreadBase::preCompilationTasks
7031
* @param vmThread Pointer to the current J9VMThread (input)
7032
* @param entry Pointer to the TR_MethodToBeCompiled entry (input)
7033
* @param method Pointer to the J9Method (input)
7034
* @param aotCachedMethod Pointer to a pointer to the AOT code to be relocated (if it exists) (output)
7035
* @param trMemory Reference to the TR_Memory associated with this compilation (input)
7036
* @param canDoRelocatableCompile Reference to a bool; indicates if the current compilation can be AOT compiled (output)
7037
* @param eligibleForRelocatableCompile Reference to a bool; Indicates if the current compilation is eligible for AOT (output)
7038
* @param reloRuntime Pointer to a TR_RelocationRuntime; NULL if JVM does not have AOT support (input)
7039
*
7040
* This method is used to perform a set of tasks needed before attempting a compilation.
7041
*
7042
* This method can throw an exception.
7043
*/
7044
void
7045
TR::CompilationInfoPerThreadBase::preCompilationTasks(J9VMThread * vmThread,
7046
TR_MethodToBeCompiled *entry,
7047
J9Method *method,
7048
const void **aotCachedMethod,
7049
TR_Memory &trMemory,
7050
bool &canDoRelocatableCompile,
7051
bool &eligibleForRelocatableCompile,
7052
TR_RelocationRuntime *reloRuntime)
7053
{
7054
TR_J9VMBase *fe = TR_J9VMBase::get(_jitConfig, vmThread);
7055
if (NULL == fe)
7056
throw std::bad_alloc();
7057
7058
// Check to see if we find an AOT version in the shared cache
7059
//
7060
entry->setAotCodeToBeRelocated(NULL); // make sure decision to load AOT comes from below and not previous compilation/relocation pass
7061
entry->_doAotLoad = false;
7062
7063
#if defined(J9VM_INTERP_AOT_RUNTIME_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))
7064
if (entry->_methodIsInSharedCache == TR_yes // possible AOT load
7065
&& !TR::CompilationInfo::isCompiled(method)
7066
&& !entry->_doNotUseAotCodeFromSharedCache
7067
&& !TR::Options::getAOTCmdLineOptions()->getOption(TR_NoLoadAOT)
7068
&& !(_jitConfig->runtimeFlags & J9JIT_TOSS_CODE)
7069
&& !_jitConfig->inlineFieldWatches)
7070
{
7071
// Determine whether the compilation filters allows me to relocate
7072
// Filters should not be applied to out-of-process compilations
7073
// because decisions on what needs to be compiled are done at the client
7074
//
7075
TR_Debug *debug = TR::Options::getDebug();
7076
bool canRelocateMethod = true;
7077
if (debug && !entry->isOutOfProcessCompReq())
7078
{
7079
setCompilationShouldBeInterrupted(0); // zero the flag because createResolvedMethod calls
7080
// acquire/releaseVMaccessIfNeeded and may see the flag set by previous compilation
7081
TR_FilterBST *filter = NULL;
7082
7083
TR_ResolvedMethod *resolvedMethod = fe->createResolvedMethod(&trMemory, (TR_OpaqueMethodBlock *)method);
7084
if (!debug->methodCanBeRelocated(&trMemory, resolvedMethod, filter) ||
7085
!debug->methodCanBeCompiled(&trMemory, resolvedMethod, filter))
7086
canRelocateMethod = false;
7087
}
7088
7089
if (canRelocateMethod && !entry->_oldStartPC)
7090
{
7091
// Find the AOT body in the SCC
7092
//
7093
*aotCachedMethod = findAotBodyInSCC(vmThread, entry->getMethodDetails().getRomMethod(fe));
7094
7095
// Validate the class chain of the class of the method being AOT loaded
7096
if (*aotCachedMethod && !fe->sharedCache()->classMatchesCachedVersion(J9_CLASS_FROM_METHOD(method)))
7097
{
7098
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
7099
{
7100
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,
7101
"Failed to validate the class chain of the class of method %p",
7102
method);
7103
}
7104
*aotCachedMethod = NULL;
7105
canRelocateMethod = false;
7106
entry->_doNotUseAotCodeFromSharedCache = true;
7107
}
7108
7109
if (*aotCachedMethod)
7110
{
7111
#ifdef COMPRESS_AOT_DATA
7112
TR_AOTMethodHeader *aotMethodHeader = (TR_AOTMethodHeader*)(((J9JITDataCacheHeader*)*aotCachedMethod) + 1);
7113
if (aotMethodHeader->flags & TR_AOTMethodHeader_CompressedMethodInCache)
7114
{
7115
/**
7116
* For each AOT compiled method we store in the shareclass cache we have following layout.
7117
* ---------------------------------------------------------------------------------------
7118
* | CompiledMethodWrapper | J9JITDataCacheHeader | AOTMethodHeader | Metadata | Codedata|
7119
* ---------------------------------------------------------------------------------------
7120
* When we compile and store a method, it stores J9RomMethod for the method in the CompiledMethodWrapper along side
7121
* size of metadata and codedata in the cache. Now when we request a method from shared class cache
7122
* it returns address that points to J9JITDataCacheHeader. As while decompressing the data, we need information about
7123
* the size of original data (We get that information from AOTMethodHeader) and size of deflated data in the cache (Which is stored in
7124
* CompiledMethodWrapper)
7125
* So to access data size in shared class cache, we need to access CompiledMethodWrapper.
7126
*/
7127
CompiledMethodWrapper *wrapper = ((CompiledMethodWrapper*)(*aotCachedMethod)) - 1;
7128
int sizeOfCompressedDataInCache = wrapper->dataLength;
7129
int originalDataSize = aotMethodHeader->compileMethodDataSize + aotMethodHeader->compileMethodCodeSize;
7130
void *originalData = trMemory.allocateHeapMemory(originalDataSize);
7131
int aotMethodHeaderSize = sizeof(J9JITDataCacheHeader) + sizeof(TR_AOTMethodHeader);
7132
memcpy(originalData, *aotCachedMethod, aotMethodHeaderSize);
7133
if (inflateBuffer((U_8 *)(*aotCachedMethod) + aotMethodHeaderSize, sizeOfCompressedDataInCache - aotMethodHeaderSize, (U_8*)(originalData)+aotMethodHeaderSize, originalDataSize - aotMethodHeaderSize) == DECOMPRESSION_FAILED)
7134
{
7135
if (TR::Options::getVerboseOption(TR_VerboseAOTCompression))
7136
{
7137
J9UTF8 *className;
7138
J9UTF8 *name;
7139
J9UTF8 *signature;
7140
getClassNameSignatureFromMethod(method, className, name, signature);
7141
TR_VerboseLog::writeLineLocked(TR_Vlog_AOTCOMPRESSION, "!%.*s.%.*s%.*s : Decompression of method data failed - Compressed Method Size = %d bytes, Stored original method size = %d bytes",
7142
J9UTF8_LENGTH(className), (char *)J9UTF8_DATA(className),
7143
J9UTF8_LENGTH(name), (char *)J9UTF8_DATA(name),
7144
J9UTF8_LENGTH(signature), (char *)J9UTF8_DATA(signature),
7145
sizeOfCompressedDataInCache, originalDataSize);
7146
}
7147
// If we can not inflate the method data, JIT compile the method.
7148
canRelocateMethod = false;
7149
*aotCachedMethod = NULL;
7150
entry->_doNotUseAotCodeFromSharedCache = true;
7151
}
7152
else
7153
{
7154
if (TR::Options::getVerboseOption(TR_VerboseAOTCompression))
7155
{
7156
J9UTF8 *className;
7157
J9UTF8 *name;
7158
J9UTF8 *signature;
7159
getClassNameSignatureFromMethod(method, className, name, signature);
7160
TR_VerboseLog::writeLineLocked(TR_Vlog_AOTCOMPRESSION, "%.*s.%.*s%.*s : Decompression of method data Successful - Compressed Method Size = %d bytes, Stored original method size = %d bytes",
7161
J9UTF8_LENGTH(className), (char *)J9UTF8_DATA(className),
7162
J9UTF8_LENGTH(name), (char *)J9UTF8_DATA(name),
7163
J9UTF8_LENGTH(signature), (char *)J9UTF8_DATA(signature),
7164
sizeOfCompressedDataInCache, originalDataSize);
7165
}
7166
*aotCachedMethod = originalData;
7167
}
7168
}
7169
if (canRelocateMethod)
7170
{
7171
// All conditions are met for doing an AOT load. Mark this fact on the entry.
7172
entry->_doAotLoad = true;
7173
entry->setAotCodeToBeRelocated(*aotCachedMethod);
7174
reloRuntime->setReloStartTime(getTimeWhenCompStarted());
7175
}
7176
#else // data compression not supported
7177
// All conditions are met for doing an AOT load. Mark this fact on the entry.
7178
entry->_doAotLoad = true;
7179
entry->setAotCodeToBeRelocated(*aotCachedMethod);
7180
reloRuntime->setReloStartTime(getTimeWhenCompStarted());
7181
#endif
7182
}
7183
}
7184
else if (entry->_oldStartPC)
7185
{
7186
J9JITExceptionTable *oldMetaData = jitConfig->jitGetExceptionTableFromPC(vmThread, (UDATA)entry->_oldStartPC);
7187
if (oldMetaData)
7188
{
7189
TR_PersistentJittedBodyInfo *oldBodyInfo = (TR_PersistentJittedBodyInfo *)oldMetaData->bodyInfo;
7190
TR_ASSERT(oldBodyInfo && oldBodyInfo->getIsInvalidated(), "entry is interpreted and has a non-NULL _oldStartPC but the old body has not been invalidated.");
7191
}
7192
}
7193
}
7194
#if defined(J9VM_OPT_JITSERVER)
7195
bool cannotDoRemoteCompilation = cannotPerformRemoteComp();
7196
#endif /* defined(J9VM_OPT_JITSERVER) */
7197
7198
if (!entry->isAotLoad()) // We don't/can't relocate this method
7199
{
7200
if (TR::Options::getCmdLineOptions()->getOption(TR_ActivateCompThreadWhenHighPriReqIsBlocked))
7201
{
7202
// AOT loads that failed may be retried as JIT compilations
7203
// Such requests inherit the high priority of the AOT load
7204
// Now that this request is out of the queue we can safely change its
7205
// priority to a lower value so that when another AOT load comes along
7206
// a secondary compilation thread will be activated
7207
7208
// Is this a JIT retrial of a failed AOT load?
7209
if (entry->_methodIsInSharedCache == TR_yes && // possible AOT load
7210
entry->_doNotUseAotCodeFromSharedCache && // transformed into a JIT request
7211
entry->_compilationAttemptsLeft < MAX_COMPILE_ATTEMPTS) // because it failed previously
7212
{
7213
// Lower priority to CP_ASYNC_NORMAL
7214
if (entry->_priority > CP_ASYNC_NORMAL)
7215
entry->_priority = CP_ASYNC_NORMAL;
7216
}
7217
}
7218
7219
// Determine if we need to perform an AOT compilation
7220
//
7221
if (entry->isOutOfProcessCompReq())
7222
{
7223
// Since all of the preliminary checks have already been done at the client,
7224
// eligibleForRelocatableCompile should be true at the server side if the client
7225
// requests AOT.
7226
eligibleForRelocatableCompile = entry->_useAotCompilation;
7227
}
7228
else
7229
{
7230
TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();
7231
eligibleForRelocatableCompile =
7232
7233
// Shared Classes Enabled
7234
TR::Options::sharedClassCache()
7235
7236
// Unsupported compilations
7237
&& !entry->isJNINative()
7238
&& !details.isNewInstanceThunk()
7239
&& !details.isMethodHandleThunk()
7240
&& !entry->isDLTCompile()
7241
7242
// Only generate AOT compilations for first time compiles
7243
&& !TR::CompilationInfo::isCompiled(method)
7244
7245
// If using a loadLimit/loadLimitFile, don't do an AOT compilation
7246
// for a method body that's already in the SCC
7247
&& entry->_methodIsInSharedCache != TR_yes
7248
7249
// See eclipse-openj9/openj9#11879 for details
7250
&& (!TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug)
7251
|| !entry->_oldStartPC)
7252
7253
// Eligibility checks
7254
&& !entry->_doNotUseAotCodeFromSharedCache
7255
&& fe->sharedCache()->isROMClassInSharedCache(J9_CLASS_FROM_METHOD(method)->romClass)
7256
&& !isMethodIneligibleForAot(method)
7257
&& (!TR::Options::getAOTCmdLineOptions()->getOption(TR_AOTCompileOnlyFromBootstrap)
7258
|| fe->isClassLibraryMethod((TR_OpaqueMethodBlock *)method), true)
7259
7260
// Ensure we can generate a class chain for the class of the
7261
// method to be compiled
7262
&& (NULL != fe->sharedCache()->rememberClass(J9_CLASS_FROM_METHOD(method)))
7263
7264
// Do not perform AOT compilation if field watch is enabled; there
7265
// is no benefit to having an AOT body with field watch as it increases
7266
// the validation complexity, and in case the fields being watched changes,
7267
// the AOT body cannot be loaded
7268
&& !_jitConfig->inlineFieldWatches;
7269
}
7270
7271
bool sharedClassTest = eligibleForRelocatableCompile &&
7272
!TR::Options::getAOTCmdLineOptions()->getOption(TR_NoStoreAOT);
7273
7274
bool isSecondAOTRun =
7275
!TR::Options::getAOTCmdLineOptions()->getOption(TR_NoAotSecondRunDetection) &&
7276
TR::Options::sharedClassCache() &&
7277
_compInfo.numMethodsFoundInSharedCache() >= TR::Options::_aotMethodThreshold &&
7278
_compInfo._statNumAotedMethods <= TR::Options::_aotMethodCompilesThreshold;
7279
7280
if (!TR::Options::canJITCompile() && isSecondAOTRun) // detect second AOT run
7281
{
7282
if (!TR::Options::getAOTCmdLineOptions()->getOption(TR_ForceAOT))
7283
TR::CompilationInfo::disableAOTCompilations();
7284
TR::Options::getCmdLineOptions()->setOption(TR_DisableInterpreterProfiling, true);
7285
}
7286
7287
// Decide if we want an AOT vm or not
7288
if (sharedClassTest)
7289
{
7290
if (TR::Options::getAOTCmdLineOptions()->getOption(TR_ForceAOT) || entry->isOutOfProcessCompReq())
7291
{
7292
canDoRelocatableCompile = true;
7293
}
7294
else // Use AOT heuristics
7295
{
7296
// Heuristic: generate AOT only for downgraded compilations in the first run
7297
if ((!isSecondAOTRun && entry->_optimizationPlan->isOptLevelDowngraded()) ||
7298
entry->getMethodDetails().isJitDumpAOTMethod())
7299
{
7300
canDoRelocatableCompile = true;
7301
}
7302
else
7303
{
7304
#if defined(J9VM_OPT_JITSERVER)
7305
// We also want AOT compilations for JITServer clients that are attached to a
7306
// JITServer with an AOT cache, because those can be served relatively fast
7307
if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT &&
7308
_compInfo.getPersistentInfo()->getJITServerUseAOTCache() && // Ideally we would check if the options allow us to use the AOT cache for this method
7309
!cannotDoRemoteCompilation) // Make sure remote compilations are possible (no strong guarantees)
7310
{
7311
if (!preferLocalComp(entry))
7312
{
7313
// Even if this compilation is too expensive to be performed locally,
7314
// we may still want to refrain from generating too many remote AOT
7315
// compilations, because of the negative effect of GCR. Smaller methods
7316
// can be jitted remotely (no AOT) because the server would not save too
7317
// much CPU by using its AOT cache.
7318
//
7319
J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
7320
if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ||
7321
TR::CompilationInfo::getMethodBytecodeSize(method) >= TR::Options::_smallMethodBytecodeSizeThresholdForJITServerAOTCache)
7322
{
7323
canDoRelocatableCompile = true;
7324
}
7325
}
7326
}
7327
#endif /* defined(J9VM_OPT_JITSERVER) */
7328
}
7329
}
7330
}
7331
}
7332
#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))
7333
7334
// If we are allowed to do relocatable compilations, just do it
7335
if (canDoRelocatableCompile)
7336
{
7337
entry->_useAotCompilation = true;
7338
#if defined(J9VM_OPT_JITSERVER)
7339
if (entry->isOutOfProcessCompReq())
7340
{
7341
_vm = TR_J9VMBase::get(_jitConfig, vmThread, TR_J9VMBase::J9_SHARED_CACHE_SERVER_VM);
7342
}
7343
else
7344
#endif /* defined(J9VM_OPT_JITSERVER) */
7345
{
7346
_vm = TR_J9VMBase::get(_jitConfig, vmThread, TR_J9VMBase::AOT_VM);
7347
#if defined(J9VM_OPT_JITSERVER)
7348
if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)
7349
{
7350
if (cannotDoRemoteCompilation)
7351
downgradeLocalCompilationIfLowPhysicalMemory(entry);
7352
else // AOT compilations are more expensive, so they should all be done remotely
7353
entry->setRemoteCompReq();
7354
}
7355
#endif /* defined(J9VM_OPT_JITSERVER) */
7356
}
7357
}
7358
else if (entry->isOutOfProcessCompReq())
7359
{
7360
// JIT compilation on the server side.
7361
// Its _vm and entry->_useAotCompilation have been set in TR::CompilationInfoPerThreadRemote::processEntry
7362
TR_ASSERT(!entry->_useAotCompilation, "Client requests AOT compilation but server cannot do remote AOT compilation\n");
7363
}
7364
else
7365
{
7366
// This is used for JIT compilations and AOT loads on the client side or non-JITServer
7367
_vm = TR_J9VMBase::get(_jitConfig, vmThread);
7368
entry->_useAotCompilation = false;
7369
#if defined(J9VM_OPT_JITSERVER)
7370
// When both canDoRelocatableCompile and TR::Options::canJITCompile() are false,
7371
// remote compilation request should not be used.
7372
if ((_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT) &&
7373
TR::Options::canJITCompile())
7374
{
7375
bool forcedLocal = false;
7376
bool doLocalCompilation = entry->isAotLoad() || cannotDoRemoteCompilation || preferLocalComp(entry);
7377
7378
// If this is a remote sync compilation, change it to a local sync compilation.
7379
// After the local compilation is completed successfully, a remote async compilation
7380
// will be scheduled in compileOnSeparateThread().
7381
TR::IlGeneratorMethodDetails & details = entry->getMethodDetails();
7382
if (!doLocalCompilation &&
7383
!entry->_async &&
7384
!entry->isJNINative() &&
7385
entry->_optimizationPlan->getOptLevel() > cold &&
7386
!details.isNewInstanceThunk() &&
7387
!details.isMethodHandleThunk() &&
7388
(TR::Options::getCmdLineOptions()->getOption(TR_EnableJITServerHeuristics) ||
7389
_compInfo.getPersistentInfo()->isLocalSyncCompiles()) &&
7390
!TR::Options::getCmdLineOptions()->getOption(TR_DisableUpgradingColdCompilations) &&
7391
TR::Options::getCmdLineOptions()->allowRecompilation())
7392
{
7393
doLocalCompilation = true;
7394
entry->_origOptLevel = entry->_optimizationPlan->getOptLevel();
7395
entry->_optimizationPlan->setOptLevel(cold);
7396
entry->_optimizationPlan->setOptLevelDowngraded(true);
7397
7398
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
7399
TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH, "Changed the remote sync compilation to a local sync cold compilation: j9method=%p",
7400
entry->getMethodDetails().getMethod());
7401
}
7402
7403
if (!doLocalCompilation)
7404
{
7405
entry->setRemoteCompReq();
7406
}
7407
else if (cannotDoRemoteCompilation)
7408
{
7409
downgradeLocalCompilationIfLowPhysicalMemory(entry);
7410
}
7411
}
7412
#endif /* defined(J9VM_OPT_JITSERVER) */
7413
}
7414
}
7415
7416
/**
7417
* @brief TR::CompilationInfoPerThreadBase::postCompilationTasks
7418
* @param vmThread Pointer to the current J9VMThread (input)
7419
* @param entry Pointer to the TR_MethodToBeCompiled entry (input)
7420
* @param method Pointer to the J9Method (input)
7421
* @param aotCachedMethod Pointer to the AOT code to be relocated (if it exists) (input)
7422
* @param metaData Pointer to the TR_MethodMetaData created on a successful compile (input)
7423
* @param canDoRelocatableCompile Indicates if the current compilation could be AOT compiled (input)
7424
* @param eligibleForRelocatableCompile Indicates if the current compilation was eligible for AOT (input)
7425
* @param reloRuntime Pointer to a TR_RelocationRuntime; NULL if JVM does not have AOT support (input)
7426
* @return StartPC of the compiled body, NULL if the compilation failed
7427
*
7428
* This method is used to perform a set of tasks needed after attempting a compilation; it handles
7429
* successful and failed compilations, performing the appropriate clean up needed.
7430
*
7431
* IMPORTANT: Because this method is called from both the try and catch blocks in
7432
* TR::CompilationInfoPerThreadBase::compile, an exception should never escape from this method.
7433
* Calls to this method could be guarded with a try/catch, but that defeats this
7434
* method's purpose - an escaped exception here would prevent necessary cleanup.
7435
*/
7436
void *
7437
TR::CompilationInfoPerThreadBase::postCompilationTasks(J9VMThread * vmThread,
7438
TR_MethodToBeCompiled *entry,
7439
J9Method *method,
7440
const void *aotCachedMethod,
7441
TR_MethodMetaData *metaData,
7442
bool canDoRelocatableCompile,
7443
bool eligibleForRelocatableCompile,
7444
TR_RelocationRuntime *reloRuntime)
7445
{
7446
#if defined(J9VM_OPT_JITSERVER)
7447
// JITServer cleanup tasks
7448
if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
7449
{
7450
((TR::CompilationInfoPerThread*)this)->getClassesThatShouldNotBeNewlyExtended()->clear();
7451
}
7452
else if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)
7453
{
7454
if (entry->isRemoteCompReq())
7455
{
7456
TR::ClassTableCriticalSection commit(_vm);
7457
7458
// clear bit for this compilation
7459
_compInfo.resetCHTableUpdateDone(getCompThreadId());
7460
7461
// freshen up newlyExtendedClasses
7462
auto newlyExtendedClasses = _compInfo.getNewlyExtendedClasses();
7463
for (auto it = newlyExtendedClasses->begin(); it != newlyExtendedClasses->end();)
7464
{
7465
it->second &= _compInfo.getCHTableUpdateDone();
7466
if (it->second)
7467
++it;
7468
else
7469
it = newlyExtendedClasses->erase(it);
7470
}
7471
}
7472
else // client executing a compilation locally
7473
{
7474
// The bit for this compilation thread should be 0 because we never sent any updates to the server
7475
TR_ASSERT((_compInfo.getCHTableUpdateDone() & (1 << getCompThreadId())) == 0,
7476
"For local compilations _chTableUpdateFlags should not have the bit set for this comp ID");
7477
}
7478
}
7479
#endif /* defined(J9VM_OPT_JITSERVER) */
7480
7481
void *startPC = NULL;
7482
#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))
7483
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableUpdateAOTBytesSize) &&
7484
metaData && // Compilation succeeded
7485
!canDoRelocatableCompile && // Non-AOT Compilation
7486
eligibleForRelocatableCompile && // Was eligible for AOT Compilation
7487
TR::Options::getAOTCmdLineOptions()->getOption(TR_NoStoreAOT) && // AOT Disabled
7488
TR_J9SharedCache::isSharedCacheDisabledBecauseFull(&_compInfo) == TR_yes) // AOT Compilation Disabled because SCC is full
7489
{
7490
// If the current compilation could have been an AOT compilation
7491
// had there been space in the SCC, send the code size to the VM
7492
// so that they can suggest an appropriate size to the user for a
7493
// subsequent run
7494
int32_t codeSize = _compInfo.calculateCodeSize(metaData);
7495
_compInfo.increaseUnstoredBytes(codeSize, 0);
7496
}
7497
#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))
7498
7499
// We may want to track the CPU time spent by compilation threads periodically
7500
if (_onSeparateThread)
7501
{
7502
TR::CompilationInfoPerThread *cipt = (TR::CompilationInfoPerThread*)this;
7503
if (cipt->getCompThreadCPU().update() && // returns true if an update happened
7504
cipt->getCompThreadCPU().isFunctional())
7505
{
7506
int32_t CPUmillis = cipt->getCompThreadCPU().getCpuTime() / 1000000;
7507
// May issue a trace point if enabled
7508
Trc_JIT_CompCPU(vmThread, getCompThreadId(), CPUmillis);
7509
7510
// May issue a message in the vlog if requested
7511
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
7512
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "t=%6u CPU time spent so far in compThread:%d = %d ms",
7513
(uint32_t)_compInfo.getPersistentInfo()->getElapsedTime(), getCompThreadId(), CPUmillis);
7514
}
7515
}
7516
7517
// If compilation failed, we must delete any assumptions that might still exist in persistent memory
7518
if (_compiler && metaData == 0) // compilation failed
7519
{
7520
// We may, or may not have metadata
7521
if (getMetadata())
7522
{
7523
getMetadata()->runtimeAssumptionList = NULL;
7524
}
7525
}
7526
7527
if (_compiler)
7528
{
7529
// The KOT needs to survive at least until we're done committing virtual guards and we must not be holding the
7530
// comp monitor prior to freeing the KOT because it requires VM access.
7531
if (_compiler->getKnownObjectTable())
7532
_compiler->freeKnownObjectTable();
7533
}
7534
7535
#if defined(J9VM_OPT_JITSERVER)
7536
// Do not acquire the compilation monitor on the server, because we do not need
7537
// it until compilationEnd returns and we do not want to send message from
7538
// outOfProcessCompilationEnd while holding the monitor
7539
if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() != JITServer::SERVER)
7540
#endif
7541
{
7542
// Re-acquire the compilation monitor so that we can update the J9Method.
7543
//
7544
_compInfo.debugPrint(vmThread, "\tacquiring compilation monitor\n");
7545
_compInfo.acquireCompMonitor(vmThread);
7546
_compInfo.debugPrint(vmThread, "+CM\n");
7547
if (_onSeparateThread)
7548
{
7549
// Acquire the queue slot monitor now
7550
//
7551
_compInfo.debugPrint(vmThread, "\tre-acquiring queue-slot monitor\n");
7552
entry->acquireSlotMonitor(vmThread);
7553
_compInfo.debugPrint(vmThread, "+AM-", entry);
7554
}
7555
}
7556
7557
if (TR::CompilationInfo::shouldAbortCompilation(entry, _compInfo.getPersistentInfo()))
7558
{
7559
metaData = 0;
7560
}
7561
else if (TR::CompilationInfo::shouldRetryCompilation(entry, _compiler))
7562
{
7563
startPC = entry->_oldStartPC; // startPC == oldStartPC means compilation failure
7564
entry->_tryCompilingAgain = true;
7565
}
7566
else // compilation will not be retried, either because it succeeded or because we don't want to
7567
{
7568
TR_PersistentJittedBodyInfo *bodyInfo;
7569
void *extra = NULL;
7570
// JITServer: Can not acquire the jitted body info on the server
7571
if (!entry->isOutOfProcessCompReq() && entry->isDLTCompile() && !startPC &&
7572
(extra = TR::CompilationInfo::getPCIfCompiled(method)) && // DLT compilation that failed too many times
7573
(bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(extra))) // do not use entry->_oldStartPC which is probably 0. Use the most up-to-date startPC
7574
{
7575
bodyInfo->getMethodInfo()->setHasFailedDLTCompRetrials(true);
7576
}
7577
7578
startPC = TR::CompilationInfo::compilationEnd(
7579
vmThread,
7580
entry->getMethodDetails(),
7581
jitConfig,
7582
metaData ? reinterpret_cast<void *>(metaData->startPC) : 0,
7583
entry->_oldStartPC,
7584
_vm,
7585
entry,
7586
_compiler);
7587
7588
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
7589
TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH, "CompilationEnd returning startPC=%p metadata=%p", startPC, metaData);
7590
// AOT compilations can fail on purpose because we want to load
7591
// the AOT body later on. This case is signalled by having a metaData != 0
7592
// but a startPC == entry->_oldStartPC == 0
7593
// For remote compilations at the JITClient we replenish the invocation count in remoteCompilationEnd
7594
if (metaData && !entry->_oldStartPC && !startPC && !entry->isOutOfProcessCompReq() && !entry->isRemoteCompReq())
7595
{
7596
TR_ASSERT(canDoRelocatableCompile, "compilationEnd() can fail only for relocating AOT compilations\n");
7597
TR_ASSERT(!entry->_oldStartPC, "We expect compilationEnd() to fail only for AOT compilations which are first time compilations\n");
7598
7599
TR::CompilationInfo::replenishInvocationCount(method, _compiler);
7600
}
7601
7602
if (!metaData && !entry->_oldStartPC && // First time compilation failed
7603
!entry->isOutOfProcessCompReq())
7604
{
7605
// If we didn't compile the method because filters disallowed it,
7606
// then do not consider this compilation a failure
7607
TR_VlogTag vlogTag = (entry->_compErrCode == compilationRestrictedMethod) ? TR_Vlog_INFO : TR_Vlog_FAILURE;
7608
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompFailure, TR_VerbosePerformance))
7609
{
7610
TR_VerboseLog::CriticalSection vlogLock;
7611
TR_VerboseLog::write(vlogTag, "Method ");
7612
CompilationInfo::printMethodNameToVlog(method);
7613
TR_VerboseLog::writeLine(" will continue as interpreted");
7614
}
7615
if (entry->_compErrCode != compilationRestrictedMethod && // do not look at methods excluded by filters
7616
entry->_compErrCode != compilationExcessiveSize) // do not look at failures due to code cache size
7617
{
7618
int32_t numSeriousFailures = _compInfo.incNumSeriousFailures();
7619
if (numSeriousFailures > TR::Options::_seriousCompFailureThreshold)
7620
{
7621
// Generate a trace point
7622
Trc_JIT_ManyCompFailures(vmThread, numSeriousFailures);
7623
}
7624
}
7625
}
7626
7627
if (entry->isAotLoad() && entry->_oldStartPC == 0 && startPC != 0) // AOT load that succeeded
7628
{
7629
// We know this is a first time compilation (otherwise we would not attempt an AOT load)
7630
// Before grabbing the compilation monitor and loading the AOT body
7631
// let's check the AOT hints (optimistically assuming that the AOT load will succeed)
7632
if (_onSeparateThread && entry->_async && // KEN need to pass in onSeparateThread?
7633
(TR::Options::getAOTCmdLineOptions()->getEnableSCHintFlags() & (TR_HintUpgrade | TR_HintHot | TR_HintScorching)))
7634
{
7635
// read all hints at once because we may rely on more than just one type
7636
uint16_t hints = _vm->sharedCache()->getAllEnabledHints(method) & (TR_HintUpgrade | TR_HintHot | TR_HintScorching);
7637
// Now let's see if we need to schedule an AOT upgrade
7638
if (hints)
7639
{
7640
// must do this before queueing for an upgrade
7641
entry->_newStartPC = startPC;
7642
7643
static char *disableQueueLPQAOTUpgrade = feGetEnv("TR_DisableQueueLPQAOTUpgrade");
7644
if (TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableSymbolValidationManager)
7645
&& !disableQueueLPQAOTUpgrade)
7646
{
7647
_compInfo.getLowPriorityCompQueue().addUpgradeReqToLPQ(getMethodBeingCompiled());
7648
}
7649
else
7650
{
7651
_compInfo.queueForcedAOTUpgrade(entry, hints, _vm);
7652
}
7653
}
7654
}
7655
}
7656
7657
// Check conditions for adding to JProfiling queue.
7658
// TODO: How should be AOT loads treated?
7659
if (_addToJProfilingQueue &&
7660
entry->_oldStartPC == 0 && startPC != 0)// Must be a first time compilation that succeeded
7661
{
7662
// Add request to JProfiling Queue
7663
TR::IlGeneratorMethodDetails details(method);
7664
getCompilationInfo()->getJProfilingCompQueue().createCompReqAndQueueIt(details, startPC);
7665
}
7666
7667
7668
if (entry->_compErrCode == compilationOK && _vm->isAOT_DEPRECATED_DO_NOT_USE())
7669
_compInfo._statNumAotedMethods++;
7670
}
7671
7672
// compilation success can be detected by checking startPC && startPC != _oldStartPC
7673
7674
if (TR::Options::getAOTCmdLineOptions()->getOption(TR_EnableAOTRelocationTiming) && entry->isAotLoad())
7675
{
7676
PORT_ACCESS_FROM_JITCONFIG(jitConfig);
7677
UDATA reloTime = j9time_usec_clock() - reloRuntime->reloStartTime();
7678
// We have the comp monitor, so the add does not run into sync issues
7679
_compInfo.setAotRelocationTime(_compInfo.getAotRelocationTime() + reloTime);
7680
}
7681
7682
// Check to see if we need to print compilation information for perf tool on Linux
7683
if (TR::Options::getCmdLineOptions()->getOption(TR_PerfTool) && _compiler &&
7684
startPC != 0 && startPC != entry->_oldStartPC)
7685
{
7686
generatePerfToolEntry();
7687
}
7688
7689
if (_compiler)
7690
{
7691
// Unreserve the code cache used for this compilation
7692
//
7693
// NOTE: Although unintuitive, it is possible to reach here without an allocated
7694
// CodeGenerator. This can happen during AOT loads. See the OMR::Compilation
7695
// constructor for details.
7696
//
7697
if (_compiler->cg() && _compiler->cg()->getCodeCache())
7698
{
7699
#if defined(J9VM_OPT_JITSERVER)
7700
// For JITServer we should wipe this method from the code cache
7701
if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
7702
_compiler->cg()->getCodeCache()->resetCodeCache();
7703
#endif /* defined(J9VM_OPT_JITSERVER) */
7704
_compiler->cg()->getCodeCache()->unreserve();
7705
_compiler->cg()->setCodeCache(0);
7706
}
7707
// Unreserve the data cache
7708
TR_DataCache *dataCache = (TR_DataCache*)_compiler->getReservedDataCache();
7709
if (dataCache)
7710
{
7711
// For AOT compilation failures with an error code of compilationAotCacheFullReloFailure
7712
// that are going to be retried we want to keep the reservation
7713
if (entry->_tryCompilingAgain && entry->_compErrCode == compilationAotCacheFullReloFailure)
7714
{
7715
TR_ASSERT(canDoRelocatableCompile, "Only AOT compilations can fail with compilationAotCacheFullReloFailure. entry=%p\n", entry);
7716
_reservedDataCache = dataCache;
7717
}
7718
else
7719
{
7720
TR_DataCacheManager::getManager()->makeDataCacheAvailable(dataCache);
7721
_compiler->setReservedDataCache(NULL);
7722
}
7723
}
7724
}
7725
// Safety net for when the compiler object cannot be created and we have
7726
// a dataCache reservation from the previous compilation.
7727
// If we don't intend to retry this compilation, release the cached dataCache
7728
if (_reservedDataCache && !entry->_tryCompilingAgain)
7729
{
7730
TR_DataCacheManager::getManager()->makeDataCacheAvailable(_reservedDataCache);
7731
_reservedDataCache = NULL;
7732
}
7733
7734
#if defined(J9VM_OPT_JITSERVER)
7735
if (_compiler
7736
&& _compiler->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER
7737
&& !entry->_optimizationPlan->isLogCompilation())
7738
{
7739
_compiler->getOptions()->closeLogFileForClientOptions();
7740
}
7741
#endif /* defined(J9VM_OPT_JITSERVER) */
7742
7743
if (_compiler)
7744
{
7745
_compiler->~Compilation();
7746
}
7747
7748
setCompilation(NULL);
7749
7750
_vm = NULL;
7751
_addToJProfilingQueue = false;
7752
7753
#if defined(J9VM_OPT_JITSERVER)
7754
if (_compInfo.getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
7755
{
7756
// Re-acquire the compilation monitor now that the last message has been sent
7757
//
7758
_compInfo.debugPrint(vmThread, "\tacquiring compilation monitor\n");
7759
_compInfo.acquireCompMonitor(vmThread);
7760
_compInfo.debugPrint(vmThread, "+CM\n");
7761
// Acquire the queue slot monitor now
7762
//
7763
_compInfo.debugPrint(vmThread, "\tre-acquiring queue-slot monitor\n");
7764
entry->acquireSlotMonitor(vmThread);
7765
_compInfo.debugPrint(vmThread, "+AM-", entry);
7766
}
7767
#endif
7768
7769
return startPC;
7770
}
7771
7772
7773
/**
7774
* @brief TR::CompilationInfoPerThreadBase::compile
7775
* @param vmThread Pointer to the current J9VMThread (input)
7776
* @param entry Pointer to the method to be compiled entry (input)
7777
* @param scratchSegmentProvider Reference to a J9::J9SegmentProvider (input)
7778
* @return StartPC of the compiled body, NULL if the compilation failed
7779
*
7780
* This is the top level method used to compile a Java method.
7781
* The compilation thread has VM access when it enters this method though
7782
* wrappedCompile() may release VM access.
7783
*/
7784
void *
7785
TR::CompilationInfoPerThreadBase::compile(J9VMThread * vmThread,
7786
TR_MethodToBeCompiled *entry,
7787
J9::J9SegmentProvider &scratchSegmentProvider)
7788
{
7789
TR_ASSERT(!_compiler, "The previous compilation was not properly cleared.");
7790
7791
{
7792
PORT_ACCESS_FROM_JITCONFIG(jitConfig);
7793
setTimeWhenCompStarted(j9time_usec_clock());
7794
}
7795
7796
TR_MethodMetaData *metaData = NULL;
7797
void *startPC = NULL;
7798
const void *aotCachedMethod = NULL;
7799
J9Method *method = entry->getMethodDetails().getMethod();
7800
bool canDoRelocatableCompile = false;
7801
bool eligibleForRelocatableCompile = false;
7802
bool eligibleForRemoteCompile = false;
7803
_qszWhenCompStarted = getCompilationInfo()->getMethodQueueSize();
7804
7805
TR_RelocationRuntime *reloRuntime = NULL;
7806
#if defined(J9VM_INTERP_AOT_RUNTIME_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))
7807
reloRuntime = entry->_compInfoPT->reloRuntime();
7808
#endif
7809
7810
UDATA oldState = vmThread->omrVMThread->vmState;
7811
vmThread->omrVMThread->vmState = J9VMSTATE_JIT | J9VMSTATE_MINOR;
7812
vmThread->jitMethodToBeCompiled = method;
7813
7814
try
7815
{
7816
TR::RawAllocator rawAllocator(vmThread->javaVM);
7817
J9::SystemSegmentProvider defaultSegmentProvider(
7818
1 << 16,
7819
(0 != scratchSegmentProvider.getPreferredSegmentSize()) ? scratchSegmentProvider.getPreferredSegmentSize()
7820
: 1 << 24,
7821
TR::Options::getScratchSpaceLimit(),
7822
scratchSegmentProvider,
7823
rawAllocator
7824
);
7825
TR::DebugSegmentProvider debugSegmentProvider(
7826
1 << 16,
7827
rawAllocator
7828
);
7829
TR::SegmentAllocator &regionSegmentProvider =
7830
TR::Options::getCmdLineOptions()->getOption(TR_EnableScratchMemoryDebugging) ?
7831
static_cast<TR::SegmentAllocator &>(debugSegmentProvider) :
7832
static_cast<TR::SegmentAllocator &>(defaultSegmentProvider);
7833
TR::Region dispatchRegion(regionSegmentProvider, rawAllocator);
7834
7835
// Initialize JITServer's trMemory with per-client persistent memory, since
7836
// we are guaranteed to be inside a per-client allocation region here.
7837
TR_Memory trMemory(*TR::Compiler->persistentMemory(), dispatchRegion);
7838
7839
preCompilationTasks(vmThread, entry,
7840
method, &aotCachedMethod, trMemory,
7841
canDoRelocatableCompile, eligibleForRelocatableCompile,
7842
reloRuntime);
7843
7844
CompileParameters compParam(
7845
this,
7846
_vm,
7847
vmThread,
7848
reloRuntime,
7849
entry->_optimizationPlan,
7850
regionSegmentProvider,
7851
dispatchRegion,
7852
trMemory,
7853
TR::CompileIlGenRequest(entry->getMethodDetails())
7854
);
7855
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
7856
TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH,
7857
"Compilation thread executing compile(): j9method=%p isAotLoad=%d canDoRelocatableCompile=%d eligibleForRelocatableCompile=%d isRemoteCompReq=%d _doNotUseAotCodeFromSharedCache=%d AOTfe=%d isDLT=%d",
7858
method, entry->isAotLoad(), canDoRelocatableCompile, eligibleForRelocatableCompile, entry->isRemoteCompReq(), entry->_doNotUseAotCodeFromSharedCache, _vm->isAOT_DEPRECATED_DO_NOT_USE(), entry->isDLTCompile());
7859
7860
if (
7861
(TR::Options::canJITCompile()
7862
|| canDoRelocatableCompile
7863
|| entry->isAotLoad()
7864
|| entry->isRemoteCompReq()
7865
)
7866
#if defined(TR_HOST_ARM)
7867
&& !TR::Options::getCmdLineOptions()->getOption(TR_FullSpeedDebug)
7868
#endif
7869
)
7870
{
7871
// Compile the method
7872
//
7873
7874
PORT_ACCESS_FROM_JITCONFIG(jitConfig);
7875
_compInfo.debugPrint("\tcompiling method", entry->getMethodDetails(), vmThread);
7876
7877
U_32 flags = J9PORT_SIG_FLAG_MAY_RETURN |
7878
J9PORT_SIG_FLAG_SIGSEGV | J9PORT_SIG_FLAG_SIGFPE |
7879
J9PORT_SIG_FLAG_SIGILL | J9PORT_SIG_FLAG_SIGBUS | J9PORT_SIG_FLAG_SIGTRAP;
7880
7881
uintptr_t result = 0;
7882
7883
// Attempt to request a compilation, while guarding against any crashes that occur
7884
// inside the compile request. For log compilations, simply return.
7885
//
7886
uintptr_t protectedResult = 0;
7887
if (entry->getMethodDetails().isJitDumpMethod())
7888
{
7889
TR::CompilationInfoPerThreadBase::UninterruptibleOperation jitDumpRecompilation(*this);
7890
7891
protectedResult = j9sig_protect(wrappedCompile, static_cast<void*>(&compParam),
7892
jitDumpSignalHandler,
7893
vmThread, flags, &result);
7894
}
7895
else
7896
{
7897
protectedResult = j9sig_protect(wrappedCompile, static_cast<void*>(&compParam),
7898
jitSignalHandler,
7899
vmThread, flags, &result);
7900
}
7901
7902
metaData = (protectedResult == 0) ? reinterpret_cast<TR_MethodMetaData *>(result) : NULL;
7903
}
7904
else
7905
{
7906
entry->_compErrCode = compilationRestrictedMethod;
7907
}
7908
7909
// This method has to be called from within the try block,
7910
// otherwise, the TR_Memory, TR::Region, and TR::SegmentAllocator
7911
// objects go out of scope and get destroyed.
7912
startPC = postCompilationTasks(vmThread, entry, method,
7913
aotCachedMethod, metaData,
7914
canDoRelocatableCompile, eligibleForRelocatableCompile,
7915
reloRuntime);
7916
}
7917
catch (const std::exception &e)
7918
{
7919
entry->_compErrCode = compilationFailure;
7920
7921
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseCompFailure, TR_VerbosePerformance))
7922
{
7923
try
7924
{
7925
throw;
7926
}
7927
catch (const J9::JITShutdown)
7928
{
7929
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: JIT Shutdown signaled>");
7930
}
7931
catch (const std::bad_alloc &e)
7932
{
7933
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: out of scratch memory>");
7934
}
7935
catch (const std::exception &e)
7936
{
7937
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: compilation aborted>");
7938
}
7939
}
7940
7941
Trc_JIT_outOfMemory(vmThread);
7942
7943
// Compilation object has already been deallocated by this point
7944
// due to heap memory region going out of scope
7945
TR_ASSERT_FATAL(getCompilation() == NULL, "Compilation must be deallocated and NULL by this point");
7946
7947
// This method has to be called from within the catch block,
7948
// since moving it outside would result in it getting invoked
7949
// twice on a successful compilation.
7950
startPC = postCompilationTasks(vmThread, entry, method,
7951
aotCachedMethod, metaData,
7952
canDoRelocatableCompile, eligibleForRelocatableCompile,
7953
reloRuntime);
7954
}
7955
7956
7957
vmThread->omrVMThread->vmState = oldState;
7958
vmThread->jitMethodToBeCompiled = NULL;
7959
7960
return startPC;
7961
}
7962
7963
// static method
7964
TR_MethodMetaData *
7965
TR::CompilationInfoPerThreadBase::wrappedCompile(J9PortLibrary *portLib, void * opaqueParameters)
7966
{
7967
CompileParameters * p = static_cast<CompileParameters *>(opaqueParameters);
7968
TR::Compilation * volatile compiler = 0;
7969
TR::Options *options = 0;
7970
TR_ResolvedMethod *compilee = 0;
7971
7972
TR::CompilationInfoPerThreadBase *that = p->_compilationInfo; // static method, no this
7973
TR_J9VMBase *vm = p->_vm;
7974
J9VMThread *vmThread = p->_vmThread;
7975
7976
TR_RelocationRuntime *reloRuntime = p->_reloRuntime;
7977
7978
J9JITConfig *jitConfig = that->_jitConfig;
7979
bool reducedWarm = false;
7980
7981
TR::SegmentAllocator &scratchSegmentProvider = p->_scratchSegmentProvider;
7982
7983
// cleanup the compilationShouldBeInterrupted flag.
7984
that->setCompilationShouldBeInterrupted(0);
7985
that->setMetadata(NULL);
7986
7987
try
7988
{
7989
if (that->_methodBeingCompiled->isDLTCompile())
7990
{
7991
TR_J9SharedCache *sc = (TR_J9SharedCache *) (vm->sharedCache());
7992
if (sc)
7993
sc->addHint(that->_methodBeingCompiled->getMethodDetails().getMethod(), TR_HintDLT);
7994
}
7995
7996
InterruptibleOperation generatingCompilationObject(*that);
7997
TR::IlGeneratorMethodDetails & details = that->_methodBeingCompiled->getMethodDetails();
7998
TR_OpaqueMethodBlock *method = (TR_OpaqueMethodBlock *) details.getMethod();
7999
8000
// Create the compilee
8001
if (details.isMethodHandleThunk())
8002
{
8003
J9::MethodHandleThunkDetails &mhDetails = static_cast<J9::MethodHandleThunkDetails &>(details);
8004
compilee = vm->createMethodHandleArchetypeSpecimen(p->trMemory(), method, mhDetails.getHandleRef());
8005
TR_ASSERT(compilee, "Cannot queue a thunk compilation for a MethodHandle without a suitable archetype");
8006
}
8007
else if (details.isNewInstanceThunk())
8008
{
8009
J9::NewInstanceThunkDetails &niDetails = static_cast<J9::NewInstanceThunkDetails &>(details);
8010
compilee = vm->createResolvedMethod(p->trMemory(), method, NULL, (TR_OpaqueClassBlock *) niDetails.classNeedingThunk());
8011
}
8012
else
8013
{
8014
compilee = vm->createResolvedMethod(p->trMemory(), method);
8015
}
8016
8017
if (that->_methodBeingCompiled->_optimizationPlan->isUpgradeRecompilation())
8018
{
8019
// TR_ASSERT(that->_methodBeingCompiled->_oldStartPC, "upgrade recompilations must have some oldstartpc");
8020
// In JITServer mode, it doesn't have to.
8021
TR_PersistentJittedBodyInfo *bodyInfo = ((TR_ResolvedJ9Method*)compilee)->getExistingJittedBodyInfo();
8022
if (bodyInfo->getIsAotedBody() || bodyInfo->getHotness() <= cold)
8023
{
8024
TR_J9SharedCache *sc = (TR_J9SharedCache *) (vm->sharedCache());
8025
if (sc)
8026
sc->addHint(that->_methodBeingCompiled->getMethodDetails().getMethod(), TR_HintUpgrade);
8027
}
8028
}
8029
8030
// See if this method can be compiled and check it against the method
8031
// filters to see if compilation is to be suppressed.
8032
8033
TR_FilterBST *filterInfo = NULL;
8034
// JITServer: methodCanBeCompiled check should have been done on the client, skip it on the server.
8035
if (!that->_methodBeingCompiled->isOutOfProcessCompReq() && !that->methodCanBeCompiled(p->trMemory(), vm, compilee, filterInfo))
8036
{
8037
that->_methodBeingCompiled->_compErrCode = compilationRestrictedMethod;
8038
8039
TR::Options *options = TR::Options::getJITCmdLineOptions();
8040
if (vm->isAOT_DEPRECATED_DO_NOT_USE())
8041
options = TR::Options::getAOTCmdLineOptions();
8042
if (options->getVerboseOption(TR_VerboseCompileExclude))
8043
{
8044
TR_VerboseLog::writeLineLocked(TR_Vlog_COMPFAIL, "%s j9m=%p cannot be translated compThreadID=%d",
8045
compilee->signature(p->trMemory()), method, that->getCompThreadId());
8046
}
8047
Trc_JIT_noAttemptToJit(vmThread, compilee->signature(p->trMemory()));
8048
8049
compilee = 0;
8050
}
8051
else if (jitConfig->runtimeFlags & (J9JIT_CODE_CACHE_FULL | J9JIT_DATA_CACHE_FULL))
8052
{
8053
// Optimization to disable future first time compilations from reaching the queue
8054
that->getCompilationInfo()->getPersistentInfo()->setDisableFurtherCompilation(true);
8055
8056
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseCompFailure, TR_VerbosePerformance))
8057
{
8058
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF,"t=%6u <WARNING: JIT CACHES FULL> Disable further compilation",
8059
(uint32_t)that->getCompilationInfo()->getPersistentInfo()->getElapsedTime());
8060
}
8061
if (jitConfig->runtimeFlags & J9JIT_CODE_CACHE_FULL)
8062
Trc_JIT_cacheFull(vmThread);
8063
if (jitConfig->runtimeFlags & J9JIT_DATA_CACHE_FULL)
8064
Trc_JIT_dataCacheFull(vmThread);
8065
that->_methodBeingCompiled->_compErrCode = compilationExcessiveSize;
8066
compilee = 0;
8067
}
8068
else
8069
{
8070
int32_t optionSetIndex = filterInfo ? filterInfo->getOptionSet() : 0;
8071
int32_t lineNumber = filterInfo ? filterInfo->getLineNumber() : 0;
8072
8073
TR_ASSERT(p->_optimizationPlan, "Must have an optimization plan");
8074
8075
#if defined(J9VM_OPT_JITSERVER)
8076
// If the options come from a remote party, skip the setup options process
8077
8078
if (that->_methodBeingCompiled->isOutOfProcessCompReq())
8079
{
8080
auto compInfoPTRemote = static_cast<TR::CompilationInfoPerThreadRemote *>(that);
8081
TR_ASSERT_FATAL(compInfoPTRemote->getClientOptions(), "client options must be set for an out-of-process compilation");
8082
options = TR::Options::unpackOptions(compInfoPTRemote->getClientOptions(), compInfoPTRemote->getClientOptionsSize(), that, vm, p->trMemory());
8083
if (!p->_optimizationPlan->isLogCompilation())
8084
{
8085
options->setLogFileForClientOptions();
8086
}
8087
else
8088
{
8089
// For JitDump compilations, set the log file to the jitdump file,
8090
// which has already been created by a thread running JitDump
8091
TR::Options::findOrCreateDebug();
8092
options->setLogFile(p->_optimizationPlan->getLogCompilation());
8093
}
8094
// The following is a hack to prevent the JITServer from allocating
8095
// a sentinel entry for the list of runtime assumptions kept in the compiler object
8096
options->setOption(TR_DisableFastAssumptionReclamation);
8097
}
8098
else
8099
#endif /* defined(J9VM_OPT_JITSERVER) */
8100
{
8101
#if defined(J9VM_OPT_JITSERVER)
8102
// JITServer: we want to suppress log file for client mode
8103
// Client will get the log files from server.
8104
if (that->_methodBeingCompiled->isRemoteCompReq())
8105
{
8106
TR::Options::suppressLogFileBecauseDebugObjectNotCreated();
8107
}
8108
TR_ASSERT(!that->_methodBeingCompiled->isOutOfProcessCompReq(), "JITServer should not change options passed by client");
8109
#endif /* defined(J9VM_OPT_JITSERVER) */
8110
8111
bool aotCompilationReUpgradedToWarm = false;
8112
if (that->_methodBeingCompiled->_useAotCompilation)
8113
{
8114
// In some circumstances AOT compilations are performed at warm
8115
if ((TR::Options::getCmdLineOptions()->getAggressivityLevel() == TR::Options::AGGRESSIVE_AOT ||
8116
that->getCompilationInfo()->importantMethodForStartup((J9Method*)method) ||
8117
(!TR::Compiler->target.cpu.isPower() && // Temporary change until we figure out the AOT bug on PPC
8118
!TR::Options::getAOTCmdLineOptions()->getOption(TR_DisableAotAtCheapWarm))) &&
8119
p->_optimizationPlan->isOptLevelDowngraded() &&
8120
p->_optimizationPlan->getOptLevel() == cold // Is this test really needed?
8121
#if defined(J9VM_OPT_JITSERVER)
8122
// Do not reupgrade a compilation that was downgraded due to low memory
8123
&& (TR::Options::getCmdLineOptions()->getOption(TR_DisableJITServerBufferedExpensiveCompilations) ||
8124
!that->_methodBeingCompiled->shouldUpgradeOutOfProcessCompilation())
8125
#endif
8126
)
8127
{
8128
p->_optimizationPlan->setOptLevel(warm);
8129
p->_optimizationPlan->setOptLevelDowngraded(false);
8130
aotCompilationReUpgradedToWarm = true;
8131
}
8132
}
8133
8134
8135
TR_PersistentCHTable *cht = that->_compInfo.getPersistentInfo()->getPersistentCHTable();
8136
if (cht && !cht->isActive())
8137
p->_optimizationPlan->setDisableCHOpts();
8138
8139
// Set up options for this compilation. An option subset might apply
8140
// to the method, either via an option set index in the limitfile or
8141
// via a regular expression that matches the method.
8142
//
8143
options = new (p->trMemory(), heapAlloc) TR::Options(
8144
p->trMemory(),
8145
optionSetIndex,
8146
lineNumber,
8147
compilee,
8148
that->_methodBeingCompiled->_oldStartPC,
8149
p->_optimizationPlan,
8150
(vm->isAOT_DEPRECATED_DO_NOT_USE() || that->_methodBeingCompiled->isAotLoad()),
8151
that->getCompThreadId());
8152
// JITServer TODO determine if we care to support annotations
8153
if (that->_methodBeingCompiled->isRemoteCompReq())
8154
{
8155
options->setOption(TR_EnableAnnotations,false);
8156
8157
// This option is used to generate SIMD instructions on Z. Currently the infrastructure
8158
// to support the relocation of some of those instructions is not available. Thus we disable
8159
// this option for remote compilations.
8160
options->setOption(TR_DisableSIMDArrayTranslate);
8161
8162
// Infrastructure to support the TOC is currently not available for Remote Compilations. We disable the feature
8163
// here so that the codegen doesn't generate TOC enabled code as it won't be valid on the client JVM.
8164
options->setOption(TR_DisableTOC);
8165
}
8166
// Determine if known annotations exist and if so, keep annotations enabled
8167
if (!that->_methodBeingCompiled->isAotLoad() && !vm->isAOT_DEPRECATED_DO_NOT_USE() && options->getOption(TR_EnableAnnotations))
8168
{
8169
if (!TR_AnnotationBase::scanForKnownAnnotationsAndRecord(&that->_compInfo, details.getMethod(), vmThread->javaVM, vm))
8170
options->setOption(TR_EnableAnnotations,false);
8171
}
8172
8173
if (vm->canUseSymbolValidationManager() && options->getOption(TR_EnableSymbolValidationManager))
8174
{
8175
options->setOption(TR_UseSymbolValidationManager);
8176
options->setOption(TR_DisableKnownObjectTable);
8177
}
8178
else if (!vm->canUseSymbolValidationManager())
8179
{
8180
// disable SVM in case it was enabled explicitly with -Xjit:useSymbolValidationManager
8181
options->setOption(TR_UseSymbolValidationManager, false);
8182
}
8183
8184
// Adjust Options for AOT compilation
8185
if (vm->isAOT_DEPRECATED_DO_NOT_USE())
8186
{
8187
// Disable dynamic literal pool for AOT because of an unresolved data snippet patching issue in which
8188
// the "Address Of Ref. Instruction" in the unresolved data snippet points to the wrong load instruction
8189
options->setOption(TR_DisableOnDemandLiteralPoolRegister);
8190
8191
options->setOption(TR_DisableIPA);
8192
options->setOption(TR_DisableEDO);
8193
options->setDisabled(OMR::invariantArgumentPreexistence, true);
8194
options->setOption(TR_DisableHierarchyInlining);
8195
if (options->getInitialBCount() == 0 || options->getInitialCount() == 0)
8196
options->setOption(TR_DisableDelayRelocationForAOTCompilations, true);
8197
8198
// Perform less inlining if we artificially upgraded this AOT compilation to warm
8199
if (aotCompilationReUpgradedToWarm)
8200
options->setInlinerOptionsForAggressiveAOT();
8201
8202
TR_ASSERT(vm->isAOT_DEPRECATED_DO_NOT_USE(), "assertion failure");
8203
8204
// Do not delay relocations for JITServer client when server side AOT caching is used (gives better performance)
8205
// Testing the presence of the deserializer is sufficient, because the deserializer
8206
// is only created at the client and only if server side AOT caching is enabled
8207
#if defined(J9VM_OPT_JITSERVER)
8208
if (that->getCompilationInfo()->getJITServerAOTDeserializer())
8209
options->setOption(TR_DisableDelayRelocationForAOTCompilations);
8210
#endif /* defined(J9VM_OPT_JITSERVER) */
8211
}
8212
8213
if (that->_methodBeingCompiled->_optimizationPlan->disableCHOpts())
8214
options->disableCHOpts();
8215
8216
if (that->_methodBeingCompiled->_optimizationPlan->disableGCR())
8217
options->setOption(TR_DisableGuardedCountingRecompilations);
8218
8219
if (that->_methodBeingCompiled->_optimizationPlan->getDisableEDO())
8220
options->setOption(TR_DisableEDO);
8221
8222
if (options->getOption(TR_DisablePrexistenceDuringGracePeriod))
8223
{
8224
if (that->getCompilationInfo()->getPersistentInfo()->getElapsedTime() < that->getCompilationInfo()->getPersistentInfo()->getClassLoadingPhaseGracePeriod())
8225
options->setDisabled(OMR::invariantArgumentPreexistence, true);
8226
}
8227
8228
// RI Based Reduced Warm Compilation
8229
if (p->_optimizationPlan->isHwpDoReducedWarm())
8230
{
8231
options->setLocalAggressiveAOT();
8232
}
8233
8234
// The following tweaks only apply for java compilations
8235
if (!that->_methodBeingCompiled->isAotLoad()) // exclude AOT loads
8236
{
8237
J9Method *method = details.getMethod();
8238
// See if we need to profile first level compilations and if we can do it, change the optimization plan
8239
//
8240
if(options->getOption(TR_FirstLevelProfiling) &&
8241
!that->_methodBeingCompiled->isDLTCompile() && // filter out DLTs
8242
!that->_methodBeingCompiled->isJNINative() &&
8243
!that->_methodBeingCompiled->getMethodDetails().isNewInstanceThunk() &&
8244
that->_methodBeingCompiled->_oldStartPC == 0 && // first time compilations
8245
TR::CompilationController::getCompilationStrategy()->enableSwitchToProfiling() &&
8246
options->canJITCompile() &&
8247
!options->getOption(TR_DisableProfiling) &&
8248
!options->getOption(TR_NoRecompile) &&
8249
options->allowRecompilation() && // don't do it for fixed opt level
8250
p->_optimizationPlan->isOptLevelDowngraded()) // only for classLoadPhase
8251
// should we do it for bootstrap classes?
8252
{
8253
p->_optimizationPlan->setInsertInstrumentation(true);
8254
p->_optimizationPlan->setUseSampling(false);
8255
options->setOption(TR_QuickProfile); // to reduce the frequency/count for profiling to 100/2
8256
}
8257
8258
// Check if user allows us to do samplingJProfiling.
8259
// If so, enable it programmatically on a method by method basis
8260
//
8261
if (!options->getOption(TR_DisableSamplingJProfiling))
8262
{
8263
// Check other preconditions
8264
if (!TR::CompilationInfo::isCompiled((J9Method*)method) &&
8265
// GCR is needed for moving away from profiling
8266
!options->getOption(TR_DisableGuardedCountingRecompilations) &&
8267
// recompilation must be allowed to move away from profiling
8268
options->allowRecompilation() && !options->getOption(TR_NoRecompile) &&
8269
// exclude newInstance, methodHandle
8270
(details.isOrdinaryMethod() || (details.isMethodInProgress() && options->getOption(TR_UseSamplingJProfilingForDLT))) &&
8271
// exclude natives
8272
!TR::CompilationInfo::isJNINative((J9Method*)method))
8273
// TODO: should we prevent SamplingJProfiling for AOT bodies?
8274
{
8275
// Check which heuristic is enabled
8276
if (options->getOption(TR_UseSamplingJProfilingForAllFirstTimeComps))
8277
{
8278
// Enable SamplingJprofiling
8279
options->setDisabled(OMR::samplingJProfiling, false);
8280
}
8281
if (options->getOption(TR_UseSamplingJProfilingForLPQ) &&
8282
that->_methodBeingCompiled->_reqFromSecondaryQueue)
8283
{
8284
// Enable SamplingJProfiling
8285
options->setDisabled(OMR::samplingJProfiling, false);
8286
// May want adjust the GCR count;
8287
// TODO: Estimate the initial invocation count and subtract the current
8288
// invocation count; this is how many invocations I am missing.
8289
// Complication: interpreter sampling may have decremented the invocation count further.
8290
options->setGCRCount(500); // add 500 more invocations
8291
}
8292
if (options->getOption(TR_UseSamplingJProfilingForDLT) &&
8293
(details.isMethodInProgress() || p->_optimizationPlan->isInducedByDLT()))
8294
{
8295
// Enable SamplingJProfiling
8296
options->setDisabled(OMR::samplingJProfiling, false);
8297
}
8298
if (options->getOption(TR_UseSamplingJProfilingForInterpSampledMethods))
8299
{
8300
int32_t skippedCount = that->getCompilationInfo()->getInterpSamplTrackingInfo()->findAndDelete(method);
8301
if (skippedCount > 0)
8302
{
8303
// Enable SamplingJProfiling
8304
options->setDisabled(OMR::samplingJProfiling, false);
8305
// Determine the count
8306
// Determine entry weight
8307
J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
8308
if (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod))
8309
{
8310
// Don't set a count too high for loopy methods
8311
options->setGCRCount(std::min(250, skippedCount));
8312
}
8313
else
8314
{
8315
options->setGCRCount(std::min(1000, skippedCount));
8316
}
8317
//fprintf(stderr, "skipped count=%d\n", skippedCount);
8318
}
8319
}
8320
8321
// When using SamplingJProfiling downgrade to cold to avoid overhead
8322
//
8323
if (!options->isDisabled(OMR::samplingJProfiling) &&
8324
// Check whether we are allowed to downgrade
8325
!options->getOption(TR_DontDowngradeToCold))
8326
{
8327
p->_optimizationPlan->setOptLevel(cold);
8328
p->_optimizationPlan->setDowngradedDueToSamplingJProfiling(true);
8329
options->setOptLevel(cold);
8330
// TODO: should we disable sampling to prevent upgrades before the method collects enough profiling info?
8331
}
8332
}
8333
}
8334
8335
bool doJProfile = false;
8336
if (that->_methodBeingCompiled->_reqFromJProfilingQueue)
8337
{
8338
doJProfile = true;
8339
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
8340
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Processing req from JPQ", (uint32_t)that->getCompilationInfo()->getPersistentInfo()->getElapsedTime());
8341
}
8342
else
8343
{
8344
// Is this request a candidate for JProfiling?
8345
if (TR_JProfilingQueue::isJProfilingCandidate(that->_methodBeingCompiled, options, vm))
8346
{
8347
static char *disableFilterOnJProfiling = feGetEnv("TR_DisableFilterOnJProfiling");
8348
// Apply the filter based on time
8349
if (disableFilterOnJProfiling)
8350
{
8351
doJProfile = true;
8352
}
8353
else if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP ||
8354
that->getCompilationInfo()->getPersistentInfo()->getJitState() == STARTUP_STATE)
8355
{
8356
// We want to JProfile this method, but maybe not just now
8357
if (that->getCompilationInfo()->canProcessJProfilingRequest())
8358
{
8359
doJProfile = true;
8360
}
8361
else
8362
{
8363
that->_addToJProfilingQueue = true;
8364
// Since we are going to recompile this method based on
8365
// the JProfiling queue, disable any GCR recompilation
8366
options->setOption(TR_DisableGuardedCountingRecompilations);
8367
}
8368
}
8369
}
8370
}
8371
8372
// JProfiling may be enabled if TR_EnableJProfilingInProfilingCompilations is set and its a profiling compilation.
8373
// See optimizer/JProfilingBlock.cpp
8374
if (!doJProfile)
8375
{
8376
options->setOption(TR_EnableJProfiling, false);
8377
}
8378
else // JProfiling bodies should not use GCR trees
8379
{
8380
options->setOption(TR_DisableGuardedCountingRecompilations);
8381
}
8382
8383
if (that->_methodBeingCompiled->_oldStartPC != 0)
8384
{
8385
TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(that->_methodBeingCompiled->_oldStartPC);
8386
if (bodyInfo)
8387
{
8388
TR_PersistentMethodInfo *methodInfo = bodyInfo->getMethodInfo();
8389
if (methodInfo->getReasonForRecompilation() == TR_PersistentMethodInfo::RecompDueToInlinedMethodRedefinition)
8390
methodInfo->incrementNumberOfInlinedMethodRedefinition();
8391
if (methodInfo->getNumberOfInlinedMethodRedefinition() >= 2)
8392
options->setOption(TR_DisableNextGenHCR);
8393
}
8394
}
8395
8396
// Strategy tweaks during STARTUP and IDLE
8397
//
8398
if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP ||
8399
that->getCompilationInfo()->getPersistentInfo()->getJitState() == IDLE_STATE)
8400
{
8401
// Disable idiomRecognition during startup of -Xquickstart runs to save memory
8402
if (TR::Options::isQuickstartDetected())
8403
options->setDisabled(OMR::idiomRecognition, true);
8404
8405
if (options->getOptLevel() < warm)
8406
{
8407
if (!vm->isAOT_DEPRECATED_DO_NOT_USE())
8408
{
8409
// Adjust DumbInliner cutoff parameter as to make it more conservative in constrained situations
8410
// For AOT we can be more aggressive because the cost is payed only during first run
8411
options->setDumbInlinerBytecodeSizeCutoff(that->getCompilationInfo()->computeDynamicDumbInlinerBytecodeSizeCutoff(options));
8412
// Disable rematerialization to cut on compilation costs
8413
if (!options->getOption(TR_DisableJava8StartupHeuristics))
8414
options->setDisabled(OMR::rematerialization, true);
8415
}
8416
// Increase the trivial inliner max size for 'important methods' (could be bootstrap methods)
8417
// We could filter by AOT only, or quickstart only
8418
//if (that->getCompilationInfo()->importantMethodForStartup(method))
8419
// options->setTrivialInlinerMaxSize(40);
8420
}
8421
8422
// Disable NextGenHCR during Startup Phase, if any of the
8423
// following is true:
8424
//
8425
// - TR_DisableNextGenHCRDuringStartup has been specified, or
8426
// - this is a DLT compile, or
8427
// - optLevel is warm or lower, unless
8428
// TR_EnableStartupNextGenHCRAtAllOpts has been specified
8429
//
8430
static char *disableNextGenHCRDuringStartup = feGetEnv("TR_DisableNextGenHCRDuringStartup");
8431
static char *enableStartupNextGenHCRAtAllOpts = feGetEnv("TR_EnableStartupNextGenHCRAtAllOpts");
8432
if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP
8433
&& (disableNextGenHCRDuringStartup
8434
|| that->_methodBeingCompiled->isDLTCompile()
8435
|| (options->getOptLevel() <= warm
8436
&& !enableStartupNextGenHCRAtAllOpts)))
8437
{
8438
options->setOption(TR_DisableNextGenHCR);
8439
}
8440
8441
// Do not allow switching to profiling if this is a big app
8442
//
8443
if (that->getCompilationInfo()->getPersistentInfo()->getNumLoadedClasses() >= TR::Options::_bigAppThreshold)
8444
p->_optimizationPlan->setDoNotSwitchToProfiling(true);
8445
8446
// Disable optServer for some classes of compilations during STARTUP and IDLE
8447
//
8448
if (!options->getOption(TR_NoOptServer) && !options->getOption(TR_DisableSelectiveNoOptServer) && !options->getOption(TR_Server))
8449
{
8450
if (that->_methodBeingCompiled->_oldStartPC == 0) // first time compilations
8451
{
8452
// sync requests during startup in an asynchronous environment
8453
if (that->_methodBeingCompiled->_priority >= CP_SYNC_MIN &&
8454
that->getCompilationInfo()->asynchronousCompilation())
8455
{
8456
options->setOption(TR_NoOptServer);
8457
reducedWarm = true;
8458
}
8459
// all first time compilations during startup
8460
else if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP &&
8461
details.isOrdinaryMethod() &&
8462
!options->getOption(TR_DisableNoServerDuringStartup))
8463
{
8464
options->setOption(TR_NoOptServer);
8465
reducedWarm = true;
8466
// These guys should be compiled with GCR hooks so that we get the throughput back
8467
options->setInsertGCRTrees();
8468
}
8469
8470
}
8471
else // recompilation requests
8472
{
8473
// Upgrades from cold need to be cheaper in startup or idle mode
8474
if (p->_optimizationPlan->isUpgradeRecompilation())
8475
{
8476
options->setOption(TR_NoOptServer);
8477
}
8478
else // recompilations triggered through GCR need to be cheaper
8479
{
8480
// Note that we may have a warm compilation with NoOptServer that has embedded
8481
// GCR trees to recompile without NoOptServer (thus better generated code)
8482
// We want to make sure that the recompilation uses server mode in that case
8483
//
8484
TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(that->_methodBeingCompiled->_oldStartPC);
8485
if (bodyInfo->getMethodInfo()->getReasonForRecompilation() == TR_PersistentMethodInfo::RecompDueToGCR)
8486
{
8487
if (bodyInfo->getHotness() < options->getOptLevel()) // prevent warm+NoOptServer --> warm+NoOptServer transitions
8488
{
8489
options->setOption(TR_NoOptServer);
8490
}
8491
}
8492
}
8493
}
8494
}
8495
} // Strategy tweaks during STARTUP and IDLE
8496
else
8497
{
8498
// Tweak inlining aggressiveness based on time. Only for non-AOT warm compilations and only in Xtune:virtualized mode.
8499
if (options->getOption(TR_VaryInlinerAggressivenessWithTime))
8500
{
8501
int32_t inlAggr = that->getCompilationInfo()->getPersistentInfo()->getInliningAggressiveness();
8502
if (inlAggr != 100 && options->getOptLevel() == warm && !vm->isAOT_DEPRECATED_DO_NOT_USE() &&
8503
TR::Options::getCmdLineOptions()->getAggressivityLevel() == TR::Options::AGGRESSIVE_AOT)
8504
{
8505
options->setInlinerCGBorderFrequency(9800 - 8 * inlAggr);
8506
options->setInlinerCGColdBorderFrequency(7500 - 25 * inlAggr);
8507
options->setInlinerCGVeryColdBorderFrequency(5000 - 35 * inlAggr);
8508
options->setInlinerBorderFrequency(9000 - 30 * inlAggr);
8509
options->setInlinerVeryColdBorderFrequency(5500 - 40 * inlAggr);
8510
if (inlAggr < 25)
8511
options->setOption(TR_NoOptServer);
8512
}
8513
}
8514
}
8515
// Do not try any GRA savings at hot and above or if AOT
8516
if (options->getOption(TR_EnableGRACostBenefitModel))
8517
{
8518
if (options->getOptLevel() > warm || vm->isAOT_DEPRECATED_DO_NOT_USE())
8519
options->setOption(TR_EnableGRACostBenefitModel, false);
8520
}
8521
8522
// Disable AOT w/ SVM during startup
8523
if (jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP)
8524
{
8525
static char *dontDisableSVMDuringStartup = feGetEnv("TR_DontDisableSVMDuringStartup");
8526
if (!dontDisableSVMDuringStartup)
8527
options->setOption(TR_UseSymbolValidationManager, false);
8528
}
8529
8530
// See if we need to insert GCR trees
8531
if (!details.supportsInvalidation() ||
8532
options->getOptLevel() >= hot) // Workaround for a bug with GCR inserted in hot bodies. See #4549 for details.
8533
{ // Upgrades hot-->scorching should be done through sampling, not GCR
8534
options->setOption(TR_DisableGuardedCountingRecompilations);
8535
}
8536
else if (vm->isAOT_DEPRECATED_DO_NOT_USE() || (options->getOptLevel() < warm &&
8537
!(that->_methodBeingCompiled->_jitStateWhenQueued == IDLE_STATE && that->getCompilationInfo()->getPersistentInfo()->getJitState() == IDLE_STATE)))
8538
{
8539
options->setInsertGCRTrees(); // This is a recommendation not a directive
8540
}
8541
// Disable some expensive optimizations
8542
if (options->getOptLevel() <= warm && !options->getOption(TR_EnableExpensiveOptsAtWarm))
8543
{
8544
options->setOption(TR_DisableStoreSinking);
8545
}
8546
} // end of compilation strategy tweaks for Java
8547
8548
8549
// If we are at the last retrial and the automatic logging feature is turned on
8550
// set TR_TraceAll options to generate a full log file for this compilation
8551
// (just in case it fails again). Note that the log file must be specified.
8552
//
8553
if (options->getOption(TR_EnableLastCompilationRetrialLogging) &&
8554
(that->_methodBeingCompiled->_compilationAttemptsLeft == 1))
8555
{
8556
if (options->getLogFile() != NULL)
8557
options->setOption(TR_TraceAll);
8558
}
8559
8560
TR_ASSERT(TR::comp() == NULL, "there seems to be a current TLS TR::Compilation object %p for this thread. At this point there should be no current TR::Compilation object", TR::comp());
8561
8562
// Under -Xtune:throughput we allow huge methods for compilations above warm
8563
if (TR::Options::getAggressivityLevel() == TR::Options::TR_AggresivenessLevel::AGGRESSIVE_THROUGHPUT &&
8564
options->getOptLevel() > warm &&
8565
!options->getOption(TR_ProcessHugeMethods))
8566
{
8567
static char *dontAcceptHugeMethods = feGetEnv("TR_DontAcceptHugeMethods");
8568
if (!dontAcceptHugeMethods)
8569
{
8570
options->setOption(TR_ProcessHugeMethods);
8571
}
8572
}
8573
}
8574
8575
uint64_t proposedScratchMemoryLimit = static_cast<uint64_t>(TR::Options::getScratchSpaceLimit());
8576
8577
// Finally, set JitDump specific options as the last step of options adjustments
8578
if (details.isJitDumpMethod() && options->getDebug())
8579
{
8580
auto jitDumpDetails = static_cast<J9::JitDumpMethodDetails&>(details);
8581
if (jitDumpDetails.getOptionsFromOriginalCompile() != NULL)
8582
{
8583
// We have the original `TR::Options` from the crashed compilation. The above logic which adjusts
8584
// various options is timing sensitive, and can be dependent on the VM state (startup vs not), which
8585
// can drastically change how the compilation looks (ex. is NextGenHCR enabled, is SVM to be used).
8586
//
8587
// Ideally we would just copy construct the current options from the original crashed compile, however
8588
// this is currently not possible. Although a copy constructor exists, it is not a good idea to use it
8589
// here due to a number of problems:
8590
//
8591
// 1. The non-copy constructor takes care of initializing tracing, among other things, which may have
8592
// not been active on the original compilation. There is currently no easy way for us to reinitialize
8593
// such logic.
8594
//
8595
// 2. Options can be set at any point during the compilation, and decisions to set options can be based
8596
// off of whether other options are set or not. This is very problematic. For example during the
8597
// original compilation we may have set option A at some point X during the compilation thus changing
8598
// the value of that option from that point onward. This means that if we were to copy construct the
8599
// set of options from the original compile right here for the JitDump compilation then option A
8600
// would yield a different value from the start of the compilation until point X.
8601
//
8602
// This should eventually be improved if the options framework is ever simplified to contain only option
8603
// values, not things like optimization plans, start PCs, compile thread IDs, etc.
8604
//
8605
// Because of this limitation we do our best to only copy options which are known to be timing sensitive
8606
// and that could change between the JitDump compilation and the original compilation. This is not a
8607
// silver bullet, and should be updated as we encounter more sources of non-determinism for JitDump
8608
// recompilation.
8609
8610
TR::Options* optionsFromOriginalCompile = jitDumpDetails.getOptionsFromOriginalCompile();
8611
8612
options->setOption(TR_UseSymbolValidationManager, optionsFromOriginalCompile->getOption(TR_UseSymbolValidationManager));
8613
options->setOption(TR_DisableGuardedCountingRecompilations, optionsFromOriginalCompile->getOption(TR_DisableGuardedCountingRecompilations));
8614
options->setOption(TR_DisableNextGenHCR, optionsFromOriginalCompile->getOption(TR_DisableNextGenHCR));
8615
}
8616
8617
options->setOption(TR_TraceAll);
8618
options->setOption(TR_EnableParanoidOptCheck);
8619
8620
// Tracing higher optimization level compilations may put us past the allocation limit and result in an
8621
// std::bad_alloc exception being thrown. To maximize our chances of getting a trace log we artificially
8622
// inflate the scratch space memory for JitDump compilations.
8623
proposedScratchMemoryLimit = UINT_MAX;
8624
8625
// Trace crashing optimization or the codegen depending on where we crashed
8626
UDATA vmState = that->_compInfo.getVMStateOfCrashedThread();
8627
if ((vmState & J9VMSTATE_JIT_CODEGEN) == J9VMSTATE_JIT_CODEGEN)
8628
{
8629
options->setOption(TR_TraceCG);
8630
options->setOption(TR_TraceRA);
8631
}
8632
else if ((vmState & J9VMSTATE_JIT_OPTIMIZER) == J9VMSTATE_JIT_OPTIMIZER)
8633
{
8634
OMR::Optimizations opt = static_cast<OMR::Optimizations>((vmState & 0xFF00) >> 8);
8635
if (0 < opt && opt < OMR::numOpts)
8636
{
8637
options->enableTracing(opt);
8638
}
8639
8640
// Enable additional tracing which are not part of standard optimizer tracing infrastructure
8641
switch (opt)
8642
{
8643
case OMR::Optimizations::inlining:
8644
case OMR::Optimizations::targetedInlining:
8645
case OMR::Optimizations::trivialInlining:
8646
{
8647
options->setOption(TR_DebugInliner);
8648
break;
8649
}
8650
default:
8651
break;
8652
}
8653
}
8654
}
8655
8656
// In JITServer, we would like to use JITClient's processor info for the compilation
8657
// The following code effectively replaces the cpu with client's cpu through the getProcessorDescription() that has JITServer support
8658
TR::Environment target = TR::Compiler->target;
8659
#if defined(J9VM_OPT_JITSERVER)
8660
if (that->_methodBeingCompiled->isOutOfProcessCompReq())
8661
{
8662
// Customize target.cpu based on the processor description fetched from the client
8663
OMRProcessorDesc JITClientProcessorDesc = that->getClientData()->getOrCacheVMInfo(that->_methodBeingCompiled->_stream)->_processorDescription;
8664
target.cpu = TR::CPU::customize(JITClientProcessorDesc);
8665
}
8666
else
8667
#endif /* defined(J9VM_OPT_JITSERVER) */
8668
{
8669
if (vm->needRelocatableTarget())
8670
{
8671
target = TR::Compiler->relocatableTarget;
8672
}
8673
}
8674
compiler = new (p->trMemory(), heapAlloc) TR::Compilation(
8675
that->getCompThreadId(),
8676
vmThread,
8677
vm,
8678
compilee,
8679
p->_ilGenRequest,
8680
*options,
8681
p->_dispatchRegion,
8682
p->trMemory(),
8683
p->_optimizationPlan,
8684
reloRuntime,
8685
&target);
8686
8687
#if defined(J9VM_OPT_JITSERVER)
8688
// JITServer TODO: put info in optPlan so that compilation constructor can do this
8689
if (that->_methodBeingCompiled->isRemoteCompReq())
8690
{
8691
compiler->setRemoteCompilation();
8692
// Create the KOT by default at the client if it's a remote compilation.
8693
// getOrCreateKnownObjectTable() checks if TR_DisableKnownObjectTable is set or not.
8694
compiler->getOrCreateKnownObjectTable();
8695
}
8696
else if (that->_methodBeingCompiled->isOutOfProcessCompReq())
8697
{
8698
compiler->setOutOfProcessCompilation();
8699
// Create the KOT by default at the server as long as it is not disabled at the client.
8700
compiler->getOrCreateKnownObjectTable();
8701
compiler->setClientData(that->getClientData());
8702
compiler->setStream(that->_methodBeingCompiled->_stream);
8703
auto compInfoPTRemote = static_cast<TR::CompilationInfoPerThreadRemote *>(that);
8704
compiler->setAOTCacheStore(compInfoPTRemote->isAOTCacheStore());
8705
}
8706
#endif /* defined(J9VM_OPT_JITSERVER) */
8707
8708
p->trMemory()->setCompilation(compiler);
8709
that->setCompilation(compiler);
8710
8711
TR_ASSERT(TR::comp() == compiler, "the TLS TR::Compilation object %p for this thread does not match the one %p just created.", TR::comp(), compiler);
8712
8713
#ifdef MCT_DEBUG
8714
fprintf(stderr, "Created new compiler %p ID=%d\n", compiler, compiler->getCompThreadID());
8715
#endif
8716
if (compiler)
8717
{
8718
bool isJSR292 = TR::CompilationInfo::isJSR292(details.getMethod());
8719
8720
// Check if the method to be compiled is a JSR292 method
8721
if (isJSR292)
8722
{
8723
/* Set options */
8724
compiler->getOptions()->setOption(TR_Server);
8725
compiler->getOptions()->setOption(TR_ProcessHugeMethods);
8726
8727
// Try to increase scratch space limit for JSR292 compilations
8728
proposedScratchMemoryLimit *= TR::Options::getScratchSpaceFactorWhenJSR292Workload();
8729
8730
#if defined(J9VM_OPT_OPENJDK_METHODHANDLE)
8731
// Allow larger methods to be inlined into scorching bodies for JSR292 methods.
8732
//
8733
compiler->getOptions()->setBigCalleeScorchingOptThreshold(1024);
8734
#endif
8735
}
8736
// Under -Xtune:throughput, increase the scratch space limit for hot/scorching compilations
8737
else if (TR::Options::getAggressivityLevel() == TR::Options::TR_AggresivenessLevel::AGGRESSIVE_THROUGHPUT &&
8738
compiler->getOptions()->getOptLevel() > warm &&
8739
TR::Options::getScratchSpaceLimitForHotCompilations() > proposedScratchMemoryLimit) // Make sure we don't decrease the value proposed so far
8740
{
8741
proposedScratchMemoryLimit = TR::Options::getScratchSpaceLimitForHotCompilations();
8742
}
8743
#if defined(J9VM_OPT_JITSERVER)
8744
else if (compiler->isOutOfProcessCompilation())
8745
{
8746
// We want to increase the scratch memory if it's a out of process compilation
8747
proposedScratchMemoryLimit *= TR::Options::getScratchSpaceFactorWhenJITServerWorkload();
8748
// However, this new limit must not be larger than the half the free physical memory
8749
8750
}
8751
#endif
8752
8753
// Check if the method to be compiled is a Thunk Archetype
8754
if (details.isMethodHandleThunk())
8755
{
8756
compiler->getOptions()->setAllowRecompilation(false);
8757
options->setOption(TR_DisableOSR);
8758
options->setOption(TR_EnableOSR, false);
8759
}
8760
8761
// Disable recompilation for sync compiles in FSD mode. An app thread that blocks
8762
// on compilation releases VM Access. If class redefinition occurs during a
8763
// recompilation, the application thread can no longer OSR out to the interpreter;
8764
// it is forced to return to the oldStartPC (to jump to a helper) which may not
8765
// necessarily be valid.
8766
if (compiler->getOption(TR_FullSpeedDebug) && !that->_compInfo.asynchronousCompilation())
8767
{
8768
compiler->getOptions()->setAllowRecompilation(false);
8769
}
8770
8771
// Check to see if there is sufficient physical memory available for this compilation
8772
if (compiler->getOption(TR_EnableSelfTuningScratchMemoryUsageBeforeCompile))
8773
{
8774
bool incompleteInfo = false;
8775
// Abort the compile if we don't have at least getScratchSpaceLowerBound()
8776
// available, plus some safe reserve
8777
// TODO: we may want to use a lower value for third parameter below if the
8778
// compilation is deemed cheap (JNI, thunks, cold small method)
8779
uint64_t physicalLimit = that->_compInfo.computeFreePhysicalLimitAndAbortCompilationIfLow(compiler,
8780
incompleteInfo,
8781
TR::Options::getScratchSpaceLowerBound());
8782
// If we were able to get the memory information
8783
if (physicalLimit != OMRPORT_MEMINFO_NOT_AVAILABLE)
8784
{
8785
// If the proposed scratch space limit is greater than the available
8786
// physical memory, we need to lower the scratch space limit.
8787
#if defined(J9VM_OPT_JITSERVER)
8788
// Moreover, for JITServer do not allow a single compilation to consume
8789
// more than half of the free physical memory
8790
if (compiler->isOutOfProcessCompilation())
8791
physicalLimit = std::max(physicalLimit >> 1, static_cast<uint64_t>(TR::Options::getScratchSpaceLowerBound()));
8792
#endif
8793
if (proposedScratchMemoryLimit > physicalLimit)
8794
{
8795
if (incompleteInfo)
8796
{
8797
// If we weren't able to get all the memory information
8798
// only lower the limit for JSR292 compilations,
8799
// but not beyond the default value for scratch memory
8800
if (isJSR292)
8801
{
8802
proposedScratchMemoryLimit = (physicalLimit >= scratchSegmentProvider.allocationLimit()
8803
? physicalLimit
8804
: scratchSegmentProvider.allocationLimit());
8805
}
8806
}
8807
else // We have complete memory information
8808
{
8809
proposedScratchMemoryLimit = physicalLimit;
8810
}
8811
}
8812
}
8813
}
8814
8815
// Cap the limit for JIT to 4GB
8816
size_t proposedCapped = proposedScratchMemoryLimit > UINT_MAX ? UINT_MAX : (size_t)proposedScratchMemoryLimit;
8817
scratchSegmentProvider.setAllocationLimit(proposedCapped);
8818
}
8819
8820
if (debug("traceInfo") && optionSetIndex > 0)
8821
{
8822
if (compiler->getOutFile() != NULL)
8823
diagnostic("Forced Option Set %d\n", optionSetIndex);
8824
}
8825
}
8826
}
8827
catch (const std::exception &e)
8828
{
8829
// TODO: we must handle OOM cases when we abort the compilation right from the start.
8830
// Or eliminate the code that throws (or the code could also look at how the expensive the compilation is)
8831
try
8832
{
8833
throw;
8834
}
8835
#if defined(J9VM_OPT_JITSERVER)
8836
catch (const JITServer::StreamFailure &e)
8837
{
8838
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
8839
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "<EARLY TRANSLATION FAILURE: JITServer stream failure>");
8840
that->_methodBeingCompiled->_compErrCode = compilationStreamFailure;
8841
Trc_JITServerStreamFailure(vmThread, that->getCompThreadId(), __FUNCTION__, "", "", e.what());
8842
}
8843
catch (const JITServer::StreamInterrupted &e)
8844
{
8845
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
8846
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "<EARLY TRANSLATION FAILURE: compilation interrupted by JITClient>");
8847
that->_methodBeingCompiled->_compErrCode = compilationStreamInterrupted;
8848
Trc_JITServerStreamInterrupted(vmThread, that->getCompThreadId(), __FUNCTION__, "", "", e.what());
8849
}
8850
#endif /* defined(J9VM_OPT_JITSERVER) */
8851
catch (const J9::JITShutdown)
8852
{
8853
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseCompFailure, TR_VerbosePerformance))
8854
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: JIT Shutdown signaled>");
8855
that->_methodBeingCompiled->_compErrCode = compilationFailure;
8856
}
8857
catch (const std::bad_alloc &e)
8858
{
8859
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseCompFailure, TR_VerbosePerformance))
8860
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: out of scratch memory>");
8861
that->_methodBeingCompiled->_compErrCode = compilationFailure;
8862
Trc_JIT_outOfMemory(vmThread);
8863
}
8864
catch (const std::exception &e)
8865
{
8866
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseCompFailure, TR_VerbosePerformance))
8867
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,"<EARLY TRANSLATION FAILURE: compilation aborted>");
8868
that->_methodBeingCompiled->_compErrCode = compilationFailure;
8869
}
8870
8871
if (compiler)
8872
{
8873
// The KOT needs to survive at least until we're done committing virtual guards and we must not be holding the
8874
// comp monitor prior to freeing the KOT because it requires VM access.
8875
if (compiler->getKnownObjectTable())
8876
compiler->freeKnownObjectTable();
8877
8878
compiler->~Compilation();
8879
}
8880
8881
compiler = NULL;
8882
p->trMemory()->setCompilation(NULL);
8883
that->setCompilation(NULL);
8884
}
8885
8886
TR_MethodMetaData * metaData = NULL;
8887
8888
if (compiler)
8889
{
8890
if (compiler->getRecompilationInfo())
8891
{
8892
// if the compiler is created successfully and the method supports recompilation, we can set this field on the bodyInfo
8893
TR_PersistentJittedBodyInfo *bodyInfo = compiler->getRecompilationInfo()->getJittedBodyInfo();
8894
if (bodyInfo)
8895
{
8896
bodyInfo->setStartPCAfterPreviousCompile(that->_methodBeingCompiled->_oldStartPC);
8897
if (reducedWarm && options->getOptLevel() == warm)
8898
bodyInfo->setReducedWarm();
8899
}
8900
}
8901
8902
const char *hotnessString = compiler->getHotnessName(compiler->getMethodHotness());
8903
8904
Trc_JIT_compileStart(vmThread, hotnessString, compiler->signature());
8905
8906
TR_ASSERT(compiler->getMethodHotness() != unknownHotness, "Trying to compile at unknown hotness level");
8907
8908
metaData = that->compile(vmThread, compiler, compilee, *vm, p->_optimizationPlan, scratchSegmentProvider);
8909
8910
}
8911
8912
try
8913
{
8914
// Store hints in the SCC
8915
TR_J9SharedCache *sc = (TR_J9SharedCache *) (vm->sharedCache());
8916
if (metaData && !that->_methodBeingCompiled->isDLTCompile() &&
8917
!that->_methodBeingCompiled->isAotLoad() && sc) // skip AOT loads
8918
{
8919
J9Method *method = that->_methodBeingCompiled->getMethodDetails().getMethod();
8920
TR_J9VMBase *fej9 = (TR_J9VMBase *)(compiler->fej9());
8921
if (!fej9->isAOT_DEPRECATED_DO_NOT_USE())
8922
{
8923
bool isEDOCompilation = false;
8924
TR_CatchBlockProfileInfo * profileInfo = TR_CatchBlockProfileInfo::get(compiler);
8925
if (profileInfo && profileInfo->getCatchCounter() >= TR_CatchBlockProfileInfo::EDOThreshold)
8926
{
8927
isEDOCompilation = true;
8928
sc->addHint(method, TR_HintEDO);
8929
}
8930
8931
// There is the possibility that a hot/scorching compilation happened outside
8932
// startup and with hints we move this expensive compilation during startup
8933
// thus affecting startup time
8934
// To minimize risk, add hot/scorching hints only if we are in startup mode
8935
if (TR::Compiler->vm.isVMInStartupPhase(jitConfig))
8936
{
8937
TR_Hotness hotness = that->_methodBeingCompiled->_optimizationPlan->getOptLevel();
8938
if (hotness == hot)
8939
{
8940
if (!isEDOCompilation)
8941
sc->addHint(method, TR_HintHot);
8942
}
8943
else if (hotness == scorching)
8944
{
8945
sc->addHint(method, TR_HintScorching);
8946
}
8947
// We also want to add a hint about methods compiled (not AOTed) during startup
8948
// In subsequent runs we should give such method lower counts the idea being
8949
// that if I take the time to compile method, why not do it sooner
8950
sc->addHint(method, TR_HintMethodCompiledDuringStartup);
8951
}
8952
}
8953
8954
// If this is a cold/warm compilation that takes too much memory
8955
// add a hint to avoid queuing a forced upgrade
8956
// Look only during startup to avoid creating too many hints.
8957
// If SCC is larger we could store hints for more methods
8958
//
8959
if (TR::Compiler->vm.isVMInStartupPhase(jitConfig))
8960
{
8961
if (scratchSegmentProvider.regionBytesAllocated() > TR::Options::_memExpensiveCompThreshold)
8962
{
8963
TR_Hotness hotness = that->_methodBeingCompiled->_optimizationPlan->getOptLevel();
8964
if (hotness <= cold)
8965
{
8966
sc->addHint(method, TR_HintLargeMemoryMethodC);
8967
}
8968
else if (hotness == warm)
8969
{
8970
sc->addHint(method, TR_HintLargeMemoryMethodW);
8971
}
8972
}
8973
8974
if (that->getCompilationInfo()->getMethodQueueSize() - that->getQszWhenCompStarted() > TR::Options::_cpuExpensiveCompThreshold)
8975
{
8976
TR_Hotness hotness = that->_methodBeingCompiled->_optimizationPlan->getOptLevel();
8977
if (hotness <= cold)
8978
{
8979
sc->addHint(method, TR_HintLargeCompCPUC);
8980
}
8981
else if (hotness == warm)
8982
{
8983
sc->addHint(method, TR_HintLargeCompCPUW);
8984
}
8985
}
8986
}
8987
}
8988
}
8989
#if defined(J9VM_OPT_JITSERVER)
8990
catch (const JITServer::StreamFailure &e)
8991
{
8992
// Stream failure here means it was produced by one of the calls to sc->addHint
8993
// Fail the compilation here since attempting to finish it will result
8994
// in another StreamFailure
8995
that->_methodBeingCompiled->_compErrCode = compilationStreamFailure;
8996
metaData = NULL; // indicate that the compilation has failed for postCompilationTasks
8997
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
8998
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d JITServer StreamFailure: %s", that->getCompThreadId(), e.what());
8999
Trc_JITServerStreamFailure(vmThread, that->getCompThreadId(), __FUNCTION__, compiler->signature(), compiler->getHotnessName(), e.what());
9000
}
9001
#endif /* defined(J9VM_OPT_JITSERVER) */
9002
catch (const std::exception &e)
9003
{
9004
// Catch-all case to handle any potential failures not related to JITServer
9005
// At this point we have compiled method successfuly but failed to add hints.
9006
// We will ignore this exception and continue hoping that compilation can be finished.
9007
}
9008
return metaData;
9009
}
9010
9011
static bool
9012
foundJ9SharedDataForMethod(TR_OpaqueMethodBlock *method, TR::Compilation *comp, J9JITConfig *jitConfig)
9013
{
9014
unsigned char buffer[1000];
9015
uint32_t length = 1000;
9016
J9SharedDataDescriptor descriptor;
9017
if (!TR::Options::sharedClassCache())
9018
return false;
9019
J9SharedClassConfig * scConfig = jitConfig->javaVM->sharedClassConfig;
9020
descriptor.address = buffer;
9021
descriptor.length = length;
9022
descriptor.type = J9SHR_ATTACHED_DATA_TYPE_JITPROFILE;
9023
descriptor.flags = J9SHR_ATTACHED_DATA_NO_FLAGS;
9024
J9VMThread *vmThread = ((TR_J9VM *)comp->fej9())->getCurrentVMThread();
9025
J9ROMMethod * romMethod = comp->fej9()->getROMMethodFromRAMMethod((J9Method *)method);
9026
IDATA dataIsCorrupt;
9027
void *store = (void *)scConfig->findAttachedData(vmThread, romMethod, &descriptor, &dataIsCorrupt);
9028
if (store != (void *)descriptor.address) // a stronger check, as found can be error value
9029
return false;
9030
return store ? true : false;
9031
}
9032
9033
// Helper function to perform AOT Load process
9034
TR_MethodMetaData *
9035
TR::CompilationInfoPerThreadBase::performAOTLoad(
9036
J9VMThread * vmThread,
9037
TR::Compilation * compiler,
9038
TR_ResolvedMethod * compilee,
9039
TR_J9VMBase *vm,
9040
J9Method * method
9041
)
9042
{
9043
TR_FilterBST *filterInfo = NULL;
9044
TR_ASSERT(methodCanBeCompiled(compiler->trMemory(), vm, compilee, filterInfo), "This should already have failed in wrappedCompile");
9045
9046
// Perform an AOT load
9047
//
9048
// Load the AOT body using a non shared cache VM (don't use vm because it's J9SharedCacheVM for the compile)
9049
TR_J9VMBase *loadvm = TR_J9VMBase::get(jitConfig, vmThread);
9050
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
9051
{
9052
TR_VerboseLog::writeLineLocked(
9053
TR_Vlog_DISPATCH,
9054
"Loading previously AOT compiled body for %s @ %s",
9055
compiler->signature(),
9056
compiler->getHotnessName()
9057
);
9058
}
9059
9060
#if defined(OSX) && defined(AARCH64)
9061
pthread_jit_write_protect_np(0);
9062
#endif
9063
TR_MethodMetaData *metaData = installAotCachedMethod(
9064
vmThread,
9065
_methodBeingCompiled->_aotCodeToBeRelocated,
9066
method,
9067
loadvm,
9068
compiler->getOptions(),
9069
compilee,
9070
_methodBeingCompiled,
9071
compiler
9072
);
9073
#if defined(OSX) && defined(AARCH64)
9074
pthread_jit_write_protect_np(1);
9075
#endif
9076
9077
_methodBeingCompiled->_newStartPC = metaData ? reinterpret_cast<void *>(metaData->startPC) : 0;
9078
9079
if (!metaData) // Failed to relocate!
9080
{
9081
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
9082
{
9083
TR_VerboseLog::writeLineLocked(
9084
TR_Vlog_DISPATCH,
9085
"Failed to load previously AOT compiled body for %s @ %s",
9086
compiler->signature(),
9087
compiler->getHotnessName()
9088
);
9089
}
9090
9091
compiler->failCompilation<J9::AOTRelocationFailed>("Failed to relocate");
9092
}
9093
else
9094
{
9095
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
9096
{
9097
TR_VerboseLog::writeLineLocked(
9098
TR_Vlog_DISPATCH,
9099
"Successfully loaded previously AOT compiled body for %s @ %s",
9100
compiler->signature(),
9101
compiler->getHotnessName()
9102
);
9103
}
9104
// if we delayed relocation, persist iprofiler info here
9105
if (!compiler->getOption(TR_DisableDelayRelocationForAOTCompilations))
9106
{
9107
TR_SharedCache *sc = compiler->fej9()->sharedCache();
9108
if (sc && !foundJ9SharedDataForMethod(compilee->getPersistentIdentifier(), compiler, _jitConfig))
9109
{
9110
sc->persistIprofileInfo(NULL, compilee, compiler);
9111
TR_MethodMetaData *metaData = _methodBeingCompiled->_compInfoPT->getMetadata();
9112
U_32 numCallSites = getNumInlinedCallSites(metaData);
9113
TR::StackMemoryRegion stackMemoryRegion(*compiler->trMemory());
9114
for (int32_t i = 0; i < numCallSites; i++)
9115
{
9116
U_8 * inlinedCallSite = getInlinedCallSiteArrayElement(metaData, i);
9117
TR_OpaqueMethodBlock* j9method = (TR_OpaqueMethodBlock *)getInlinedMethod(inlinedCallSite);
9118
if(!isPatchedValue((J9Method *)j9method))
9119
{
9120
TR_ResolvedJ9Method resolvedj9method = TR_ResolvedJ9Method(j9method, compiler->fej9(), compiler->trMemory());
9121
TR_ResolvedMethod *method = &resolvedj9method;
9122
sc->persistIprofileInfo(NULL, method, compiler);
9123
}
9124
}
9125
}
9126
}
9127
}
9128
return metaData;
9129
}
9130
9131
// This routine should only be called from wrappedCompile
9132
TR_MethodMetaData *
9133
TR::CompilationInfoPerThreadBase::compile(
9134
J9VMThread * vmThread,
9135
TR::Compilation * compiler,
9136
TR_ResolvedMethod * compilee,
9137
TR_J9VMBase &vm,
9138
TR_OptimizationPlan *optimizationPlan,
9139
TR::SegmentAllocator const &scratchSegmentProvider
9140
)
9141
{
9142
9143
PORT_ACCESS_FROM_JAVAVM(_jitConfig->javaVM);
9144
J9JavaVM *javaVM = _jitConfig->javaVM;
9145
9146
TR_MethodMetaData * metaData = NULL;
9147
9148
if (_methodBeingCompiled->_priority >= CP_SYNC_MIN)
9149
++_compInfo._numSyncCompilations;
9150
else
9151
++_compInfo._numAsyncCompilations;
9152
9153
if (_methodBeingCompiled->isDLTCompile())
9154
compiler->setDltBcIndex(static_cast<J9::MethodInProgressDetails &>(_methodBeingCompiled->getMethodDetails()).getByteCodeIndex());
9155
9156
bool volatile haveLockedClassUnloadMonitor = false; // used for compilation without VM access
9157
9158
try
9159
{
9160
InterruptibleOperation compilingMethodBody(*this);
9161
9162
TR::IlGeneratorMethodDetails & details = _methodBeingCompiled->getMethodDetails();
9163
J9Method *method = details.getMethod();
9164
9165
TRIGGER_J9HOOK_JIT_COMPILING_START(_jitConfig->hookInterface, vmThread, method);
9166
9167
// Prepare compilation
9168
//
9169
if (_jitConfig->tracingHook)
9170
compiler->setDebug(
9171
((TR_CreateDebug_t)_jitConfig->tracingHook)(compiler)
9172
);
9173
if (!_methodBeingCompiled->isRemoteCompReq()) // remote compilations are performed elsewhere
9174
{
9175
// Print compiling method
9176
//
9177
struct CompilationTrace
9178
{
9179
CompilationTrace(TR::Compilation &compiler) : _compiler(compiler)
9180
{
9181
TR_ASSERT(_compiler.getHotnessName(_compiler.getMethodHotness()), "expected to have a hotness string");
9182
if (_compiler.getOutFile() != NULL && _compiler.getOption(TR_TraceAll))
9183
{
9184
traceMsg(&_compiler, "<compile\n");
9185
traceMsg(&_compiler, "\tmethod=\"%s\"\n", _compiler.signature());
9186
traceMsg(&_compiler, "\thotness=\"%s\"\n", _compiler.getHotnessName(_compiler.getMethodHotness()));
9187
traceMsg(&_compiler, "\tisProfilingCompile=%d", _compiler.isProfilingCompilation());
9188
#if defined(J9VM_OPT_JITSERVER)
9189
if (_compiler.isOutOfProcessCompilation() && TR::compInfoPT->getClientData()) // using jitserver && client JVM
9190
{
9191
traceMsg(&_compiler, "\n");
9192
traceMsg(&_compiler, "\tclientID=%" OMR_PRIu64, TR::compInfoPT->getClientData()->getClientUID());
9193
}
9194
#endif /* defined(J9VM_OPT_JITSERVER) */
9195
traceMsg(&_compiler, ">\n");
9196
}
9197
}
9198
~CompilationTrace() throw()
9199
{
9200
if (_compiler.getOutFile() != NULL && _compiler.getOption(TR_TraceAll))
9201
traceMsg(&_compiler, "</compile>\n\n");
9202
}
9203
private:
9204
TR::Compilation &_compiler;
9205
};
9206
CompilationTrace compilationTrace(*compiler);
9207
}
9208
9209
if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileStart))
9210
{
9211
char compilationTypeString[15]={0};
9212
TR::snprintfNoTrunc(compilationTypeString, sizeof(compilationTypeString), "%s%s",
9213
vm.isAOT_DEPRECATED_DO_NOT_USE() ? "AOT " : "",
9214
compiler->isProfilingCompilation() ? "profiled " : ""
9215
);
9216
bool incomplete;
9217
uint64_t freePhysicalMemorySizeB = _compInfo.computeAndCacheFreePhysicalMemory(incomplete);
9218
9219
if (freePhysicalMemorySizeB != OMRPORT_MEMINFO_NOT_AVAILABLE)
9220
{
9221
TR_VerboseLog::writeLineLocked(
9222
TR_Vlog_COMPSTART,
9223
"(%s%s) Compiling %s %s %s j9m=%p %s t=%llu compThreadID=%d memLimit=%zu KB freePhysicalMemory=%llu MB",
9224
compilationTypeString,
9225
compiler->getHotnessName(compiler->getMethodHotness()),
9226
compiler->signature(),
9227
compiler->isDLT() ? "DLT" : "",
9228
details.name(),
9229
method,
9230
_methodBeingCompiled->isRemoteCompReq() ? "remote" : "",
9231
_compInfo.getPersistentInfo()->getElapsedTime(),
9232
compiler->getCompThreadID(),
9233
scratchSegmentProvider.allocationLimit() >> 10,
9234
freePhysicalMemorySizeB >> 20
9235
);
9236
}
9237
else
9238
{
9239
TR_VerboseLog::writeLineLocked(
9240
TR_Vlog_COMPSTART,
9241
"(%s%s) Compiling %s %s %s j9m=%p t=%llu compThreadID=%d memLimit=%zu KB",
9242
compilationTypeString,
9243
compiler->getHotnessName(compiler->getMethodHotness()),
9244
compiler->signature(),
9245
compiler->isDLT() ? "DLT" : "",
9246
details.name(),
9247
method,
9248
_compInfo.getPersistentInfo()->getElapsedTime(),
9249
compiler->getCompThreadID(),
9250
scratchSegmentProvider.allocationLimit() >> 10
9251
);
9252
}
9253
}
9254
9255
// Precompile option appears in HRT documentation
9256
//
9257
if (TR::Options::getVerboseOption(TR_VerbosePrecompile))
9258
{
9259
TR_VerboseLog::writeLineLocked(TR_Vlog_PRECOMP,"%s", compiler->signature());
9260
}
9261
9262
if (
9263
_methodBeingCompiled->_oldStartPC
9264
&& compiler->getOption(TR_FailPreXRecompile)
9265
&& TR::Recompilation::getJittedBodyInfoFromPC(_methodBeingCompiled->_oldStartPC)->getIsInvalidated()
9266
)
9267
{
9268
compiler->failCompilation<TR::CompilationException>("TR_FailPreXRecompile option");
9269
}
9270
9271
// If we want to compile without VM access, now it's the time to release it
9272
// For the JITClient we must not enter this path. The class unload monitor
9273
// will not be acquired/released and we'll only release VMaccess when
9274
// waiting for a reply from the server
9275
if (!compiler->getOption(TR_DisableNoVMAccess) &&
9276
!_methodBeingCompiled->_aotCodeToBeRelocated &&
9277
!_methodBeingCompiled->isRemoteCompReq())
9278
{
9279
#if defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
9280
bool doAcquireClassUnloadMonitor = true;
9281
#else
9282
bool doAcquireClassUnloadMonitor = compiler->getOption(TR_EnableHCR) || compiler->getOption(TR_FullSpeedDebug);
9283
#endif
9284
if (doAcquireClassUnloadMonitor)
9285
{
9286
_compInfo.debugPrint(NULL, "\tcompilation thread acquiring class unload monitor\n");
9287
TR::MonitorTable::get()->readAcquireClassUnloadMonitor(getCompThreadId());
9288
haveLockedClassUnloadMonitor = true;
9289
}
9290
releaseVMAccess(vmThread);
9291
// GC can go ahead now.
9292
}
9293
9294
// The inlineFieldWatches flag is set when Field Watch is actually triggered at runtime.
9295
// When it happens, all the methods on stack are decompiled and those in
9296
// the compilation queue are invalidated. Set the option here to guarantee the
9297
// mode is detected at the right moment so that all methods compiled after respect the
9298
// data watch point.
9299
//
9300
if (_jitConfig->inlineFieldWatches)
9301
compiler->setOption(TR_EnableFieldWatch);
9302
9303
// Compile the method
9304
//
9305
9306
// For local AOT and JITServer we need to reserve a data cache to ensure contiguous memory
9307
// For TOSS_CODE we need to reserve a data cache so that we know what dataCache
9308
// to reset when throwing the data away
9309
//
9310
if ((_jitConfig->runtimeFlags & J9JIT_TOSS_CODE)
9311
|| _methodBeingCompiled->isOutOfProcessCompReq()
9312
#if defined(J9VM_INTERP_AOT_COMPILE_SUPPORT)
9313
|| (vm.isAOT_DEPRECATED_DO_NOT_USE() && !_methodBeingCompiled->isRemoteCompReq())
9314
#endif //endif J9VM_INTERP_AOT_COMPILE_SUPPORT
9315
)
9316
{
9317
// Need to reserve a data cache
9318
// if this is a retrial we may already have a data cache that is reserved
9319
// by the previous compilation; check this scenario first
9320
//
9321
if (_reservedDataCache)
9322
{
9323
TR_ASSERT(_methodBeingCompiled->_compilationAttemptsLeft < MAX_COMPILE_ATTEMPTS, "reserved dataCache for a brand new compilation\n");
9324
compiler->setReservedDataCache(_reservedDataCache);
9325
_reservedDataCache = NULL; // we don't need this field anymore; It is only used to pass
9326
// the information about reserved data caches from one retrial
9327
// to the next
9328
}
9329
else
9330
{
9331
// TODO: find an appropriate datacache size
9332
TR_DataCache *dataCache = TR_DataCacheManager::getManager()->reserveAvailableDataCache(vmThread, 4*1024);
9333
compiler->setReservedDataCache(dataCache);
9334
if (!dataCache)
9335
{
9336
compiler->failCompilation<J9::DataCacheError>("Cannot reserve dataCache");
9337
}
9338
}
9339
9340
TR_DataCache *dataCache = (TR_DataCache*)compiler->getReservedDataCache();
9341
dataCache->setAllocationMark();
9342
}
9343
else // non AOT, non TOSS_CODE
9344
{
9345
// Safety net; cancel the reservations from previous compilations
9346
if (_reservedDataCache)
9347
{
9348
TR_ASSERT(_methodBeingCompiled->_compilationAttemptsLeft < MAX_COMPILE_ATTEMPTS, "Reserved dcache must be saved only for a comp retrial");
9349
TR_DataCacheManager::getManager()->makeDataCacheAvailable(_reservedDataCache);
9350
_reservedDataCache = NULL;
9351
}
9352
}
9353
9354
if ((vm.isAOT_DEPRECATED_DO_NOT_USE() && !_methodBeingCompiled->isRemoteCompReq()) || _methodBeingCompiled->isOutOfProcessCompReq())
9355
{
9356
TR_DataCache *dataCache = (TR_DataCache*)compiler->getReservedDataCache();
9357
TR_ASSERT(dataCache, "Must have a reserved dataCache for AOT compilations");
9358
compiler->setAotMethodDataStart((uint32_t *)dataCache->getCurrentHeapAlloc());
9359
9360
// First allocate a TR_AOTMethodHeader
9361
//
9362
TR_AOTMethodHeader *cacheEntryAOTMethodHeader = pointer_cast<TR_AOTMethodHeader *>(vm.allocateRelocationData(compiler, sizeof(struct TR_AOTMethodHeader)));
9363
TR_ASSERT(cacheEntryAOTMethodHeader, "Must have cacheEntryAOTMethodHeader or throw an exception");
9364
memset(cacheEntryAOTMethodHeader, 0, sizeof(struct TR_AOTMethodHeader));
9365
// Go back to find the J9JITDataCacheHeader
9366
J9JITDataCacheHeader *cacheEntry = pointer_cast<J9JITDataCacheHeader *>(cacheEntryAOTMethodHeader) - 1;
9367
9368
// the size is set up by allocateRelocationData which also does the rounding;
9369
cacheEntry->type = J9_JIT_DCE_AOT_METHOD_HEADER;
9370
compiler->setAotMethodDataStart(cacheEntry);
9371
cacheEntryAOTMethodHeader->majorVersion = TR_AOTMethodHeader_MajorVersion; // AOT code and data major version
9372
cacheEntryAOTMethodHeader->minorVersion = TR_AOTMethodHeader_MinorVersion; // AOT code and data minor version
9373
}
9374
9375
intptr_t rtn = 0;
9376
9377
if (_methodBeingCompiled->isAotLoad())
9378
{
9379
metaData = performAOTLoad(vmThread, compiler, compilee, &vm, method);
9380
}
9381
#if defined(J9VM_OPT_JITSERVER)
9382
else if (_methodBeingCompiled->isRemoteCompReq()) // JITServer Client Mode
9383
{
9384
metaData = remoteCompile(vmThread, compiler, compilee, method, details, this);
9385
}
9386
#endif /* defined(J9VM_OPT_JITSERVER) */
9387
else // non-jitserver, non-aot-load
9388
{
9389
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
9390
{
9391
TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH, "Compiling %s @ %s", compiler->signature(), compiler->getHotnessName());
9392
}
9393
9394
if (compiler->getOption(TR_AlwaysSafeFatal))
9395
{
9396
TR_ASSERT_SAFE_FATAL(false, "alwaysSafeFatal set");
9397
TR_VerboseLog::writeLineLocked(
9398
TR_Vlog_INFO,
9399
"Bypassed TR_ASSERT_SAFE_FATAL %s @ %s",
9400
compiler->signature(),
9401
compiler->getHotnessName()
9402
);
9403
}
9404
9405
if (compiler->getOption(TR_AlwaysFatalAssert))
9406
{
9407
TR_ASSERT_FATAL(false, "alwaysFatalAssert set");
9408
}
9409
9410
if (vm.isAOT_DEPRECATED_DO_NOT_USE() &&
9411
compiler->getOption(TR_UseSymbolValidationManager))
9412
compiler->getSymbolValidationManager()->populateWellKnownClasses();
9413
9414
rtn = compiler->compile();
9415
9416
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch) && !rtn)
9417
{
9418
TR_VerboseLog::writeLineLocked(
9419
TR_Vlog_DISPATCH,
9420
"Successfully created compiled body [" POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT "] for %s @ %s",
9421
compiler->cg()->getCodeStart(),
9422
compiler->cg()->getCodeEnd(),
9423
compiler->signature(),
9424
compiler->getHotnessName());
9425
}
9426
}
9427
9428
// Re-acquire VM access if needed
9429
//
9430
if (!compiler->getOption(TR_DisableNoVMAccess))
9431
{
9432
#if !defined(J9VM_GC_DYNAMIC_CLASS_UNLOADING)
9433
if (compiler->getOption(TR_EnableHCR) || compiler->getOption(TR_FullSpeedDebug))
9434
#endif
9435
{
9436
if (haveLockedClassUnloadMonitor)
9437
{
9438
TR::MonitorTable::get()->readReleaseClassUnloadMonitor(getCompThreadId());
9439
haveLockedClassUnloadMonitor = false; // Need this because an exception might happen during createMethodMetadata
9440
} // and on the exception path we check haveLockedClassUnloadMonitor
9441
// Here the GC/HCR might happen
9442
}
9443
if (!_methodBeingCompiled->isRemoteCompReq() && !(vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS))
9444
acquireVMAccessNoSuspend(vmThread);
9445
9446
// The GC could have unloaded some classes when we released the classUnloadMonitor, or HCR could have kicked in
9447
//
9448
if (compilationShouldBeInterrupted())
9449
{
9450
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
9451
{
9452
TR_VerboseLog::writeLineLocked(
9453
TR_Vlog_DISPATCH,
9454
"Interrupting compilation of %s @ %s",
9455
compiler->signature(),
9456
compiler->getHotnessName()
9457
);
9458
}
9459
compiler->failCompilation<TR::CompilationInterrupted>("Compilation interrupted");
9460
}
9461
}
9462
9463
if (rtn != COMPILATION_SUCCEEDED)
9464
{
9465
TR_ASSERT(false, "Compiler returned non zero return code %d\n", rtn);
9466
compiler->failCompilation<TR::CompilationException>("Compilation Failure");
9467
}
9468
9469
if (TR::Options::getVerboseOption(TR_VerboseCompYieldStats))
9470
{
9471
if (compiler->getMaxYieldInterval() > TR::Options::_compYieldStatsThreshold)
9472
{
9473
TR_VerboseLog::CriticalSection vlogLock;
9474
compiler->printCompYieldStats();
9475
}
9476
}
9477
9478
_methodBeingCompiled->_compErrCode = compilationOK;
9479
if (!_methodBeingCompiled->isAotLoad()
9480
#if defined(J9VM_OPT_JITSERVER)
9481
&& !_methodBeingCompiled->isRemoteCompReq()
9482
#endif /* defined(J9VM_OPT_JITSERVER) */
9483
)
9484
{
9485
class TraceMethodMetadata
9486
{
9487
public:
9488
TraceMethodMetadata(TR::Compilation &compiler) :
9489
_compiler(compiler),
9490
_trace(compiler.getOutFile() != NULL && compiler.getOption(TR_TraceAll))
9491
{
9492
if (_trace)
9493
traceMsg(&_compiler, "<metadata>\n");
9494
}
9495
~TraceMethodMetadata()
9496
{
9497
if (_trace)
9498
traceMsg(&_compiler, "</metadata>\n");
9499
}
9500
private:
9501
TR::Compilation &_compiler;
9502
const bool _trace;
9503
};
9504
9505
TraceMethodMetadata traceMetadata(*compiler);
9506
9507
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
9508
{
9509
TR_VerboseLog::writeLineLocked(
9510
TR_Vlog_DISPATCH,
9511
"Creating metadata for %s @ %s",
9512
compiler->signature(),
9513
compiler->getHotnessName()
9514
);
9515
}
9516
9517
metaData = createMethodMetaData(vm, compilee, compiler);
9518
if (!metaData)
9519
{
9520
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
9521
{
9522
TR_VerboseLog::writeLineLocked(
9523
TR_Vlog_DISPATCH,
9524
"Failed to create metadata for %s @ %s",
9525
compiler->signature(),
9526
compiler->getHotnessName()
9527
);
9528
}
9529
compiler->failCompilation<J9::MetaDataCreationFailure>("Metadata creation failure");
9530
}
9531
9532
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
9533
{
9534
TR_VerboseLog::writeLineLocked(
9535
TR_Vlog_DISPATCH,
9536
"Successfully created metadata [" POINTER_PRINTF_FORMAT "] for %s @ %s",
9537
metaData,
9538
compiler->signature(),
9539
compiler->getHotnessName()
9540
);
9541
}
9542
9543
9544
#if defined(OSX) && defined(AARCH64)
9545
pthread_jit_write_protect_np(0);
9546
#endif
9547
// Put a metaData pointer into the Code Cache Header(s).
9548
//
9549
uint8_t *warmMethodHeader = compiler->cg()->getBinaryBufferStart() - sizeof(OMR::CodeCacheMethodHeader);
9550
memcpy( warmMethodHeader + offsetof(OMR::CodeCacheMethodHeader, _metaData), &metaData, sizeof(metaData) );
9551
if ( metaData->startColdPC )
9552
{
9553
uint8_t *coldMethodHeader = reinterpret_cast<uint8_t *>(metaData->startColdPC) - sizeof(OMR::CodeCacheMethodHeader);
9554
memcpy( coldMethodHeader + offsetof(OMR::CodeCacheMethodHeader, _metaData), &metaData, sizeof(metaData) );
9555
}
9556
9557
// FAR: should we do postpone this copying until after CHTable commit?
9558
metaData->runtimeAssumptionList = *(compiler->getMetadataAssumptionList());
9559
9560
// We don't need to delete the metadataAssumptionList from the compilation object,
9561
// and in fact it would be wrong to do so because code during chtable.commit is
9562
// expecting something in the compiler object
9563
}
9564
#if defined(OSX) && defined(AARCH64)
9565
pthread_jit_write_protect_np(1);
9566
#endif
9567
9568
setMetadata(metaData);
9569
9570
if (compiler->getOption(TR_BreakAfterCompile))
9571
{
9572
fprintf(stderr, "\n=== Finished compiling %s at %p ===\n", compiler->signature(), (void *)metaData->startPC);
9573
TR::Compiler->debug.breakPoint();
9574
}
9575
9576
if (metaData &&
9577
compiler->getPersistentInfo()->isRuntimeInstrumentationEnabled())
9578
{
9579
// This must be called after createMethodMetaData because TR_PersistentJittedBodyInfo can change in that function.
9580
_compInfo.getHWProfiler()->registerRecords(metaData, compiler);
9581
}
9582
9583
TR_CHTable *chTable = compiler->getCHTable();
9584
if (chTable && !chTable->canSkipCommit(compiler))
9585
{
9586
TR::ClassTableCriticalSection chTableCommit(&vm);
9587
TR_ASSERT(!chTableCommit.acquiredVMAccess(), "We should have already acquired VM access at this point.");
9588
if (chTable->commit(compiler) == false)
9589
{
9590
// If we created a TR_PersistentMethodInfo, fix the next compilation level
9591
// because if we retry the compilation we will fail an assume later on
9592
// due to discrepancy in compilation level.
9593
if (metaData->startPC)
9594
{
9595
TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(reinterpret_cast<void *>(metaData->startPC));
9596
if (bodyInfo)
9597
{
9598
bodyInfo->getMethodInfo()->setNextCompileLevel(bodyInfo->getHotness(), false);
9599
}
9600
}
9601
9602
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerbosePerformance, TR_VerboseCompFailure))
9603
{
9604
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE, "Failure while committing chtable for %s", compiler->signature());
9605
}
9606
9607
if (!compiler->fej9()->isAOT_DEPRECATED_DO_NOT_USE())
9608
{
9609
TR_J9SharedCache *sc = (TR_J9SharedCache *) (compiler->fej9()->sharedCache());
9610
if (sc)
9611
sc->addHint(compiler->getCurrentMethod(), TR_HintFailedCHTable);
9612
}
9613
compiler->failCompilation<J9::CHTableCommitFailure>("CHTable commit failure");
9614
}
9615
}
9616
9617
// As the body is finished, mark its profile info as active so that the JProfiler thread will inspect it
9618
if (compiler->getRecompilationInfo())
9619
{
9620
TR_PersistentJittedBodyInfo *bodyInfo = compiler->getRecompilationInfo()->getJittedBodyInfo();
9621
if (bodyInfo && bodyInfo->getProfileInfo())
9622
{
9623
bodyInfo->getProfileInfo()->setActive();
9624
}
9625
}
9626
9627
logCompilationSuccess(vmThread, vm, method, scratchSegmentProvider, compilee, compiler, metaData, optimizationPlan);
9628
9629
TRIGGER_J9HOOK_JIT_COMPILING_END(_jitConfig->hookInterface, vmThread, method);
9630
}
9631
catch (const std::exception &e)
9632
{
9633
const char *exceptionName;
9634
9635
#if defined(J9ZOS390)
9636
// Compiling with -Wc,lp64 results in a crash on z/OS when trying
9637
// to call the what() virtual method of the exception.
9638
exceptionName = "std::exception";
9639
#else
9640
exceptionName = e.what();
9641
#endif
9642
9643
printCompFailureInfo(compiler, exceptionName);
9644
processException(vmThread, scratchSegmentProvider, compiler, haveLockedClassUnloadMonitor, exceptionName);
9645
metaData = 0;
9646
}
9647
9648
// At this point the compilation has either succeeded and compilation cannot be
9649
// interrupted anymore, or it has failed. In either case _compilationShouldBeinterrupted flag
9650
// is not needed anymore
9651
setCompilationShouldBeInterrupted(0);
9652
9653
// We should not have the classTableMutex at this point
9654
TR_ASSERT_FATAL(!TR::MonitorTable::get()->getClassTableMutex()->owned_by_self(),
9655
"Should not still own classTableMutex");
9656
9657
// Increment the number of JIT compilations (either successful or not)
9658
// performed by this compilation thread
9659
//
9660
incNumJITCompilations();
9661
9662
return metaData;
9663
}
9664
9665
#if defined(JIT_METHODHANDLE_TRANSLATED)
9666
// TODO: Remove this once the VM supplies this declaration
9667
extern J9_CFUNC void jitMethodHandleTranslated (J9VMThread *currentThread, j9object_t methodHandle, j9object_t arg, void *jitEntryPoint, void *intrpEntryPoint);
9668
#endif
9669
9670
9671
// static method
9672
void *
9673
TR::CompilationInfo::compilationEnd(J9VMThread * vmThread, TR::IlGeneratorMethodDetails & details, J9JITConfig *jitConfig, void *startPC,
9674
void *oldStartPC, TR_FrontEnd *fe, TR_MethodToBeCompiled *entry, TR::Compilation *comp)
9675
{
9676
// This method is only called with both VMAccess and CompilationMutex in hand.
9677
// Performs some necessary updates once a compilation has been attempted
9678
//
9679
PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);
9680
TR_DataCache *dataCache = NULL;
9681
TR::CompilationInfo *compInfo = TR::CompilationInfo::get();
9682
9683
bool isJITServerMode = false;
9684
#if defined(J9VM_OPT_JITSERVER)
9685
isJITServerMode = compInfo->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER;
9686
#endif /* defined(J9VM_OPT_JITSERVER) */
9687
9688
if (details.isNewInstanceThunk())
9689
{
9690
if (isJITServerMode)
9691
{
9692
#if defined(J9VM_OPT_JITSERVER)
9693
if (startPC) // compilation succeeded
9694
{
9695
outOfProcessCompilationEnd(entry, comp);
9696
}
9697
else if (entry)
9698
{
9699
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
9700
{
9701
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
9702
"compThreadID=%d has failed to compile a new instance thunk", entry->_compInfoPT->getCompThreadId());
9703
}
9704
Trc_JITServerFailedToCompileNewInstanceThunk(vmThread, entry->_compInfoPT->getCompThreadId());
9705
int8_t compErrCode = entry->_compErrCode;
9706
if (compErrCode != compilationStreamInterrupted && compErrCode != compilationStreamFailure)
9707
entry->_stream->writeError(compErrCode);
9708
}
9709
#endif /* defined(J9VM_OPT_JITSERVER) */
9710
}
9711
else
9712
{
9713
J9::NewInstanceThunkDetails &mhDetails = static_cast<J9::NewInstanceThunkDetails &>(details);
9714
J9Class *clazz = mhDetails.classNeedingThunk();
9715
if (startPC)
9716
jitNewInstanceMethodTranslated(vmThread, clazz, startPC);
9717
else
9718
jitNewInstanceMethodTranslateFailed(vmThread, clazz);
9719
}
9720
9721
if (((jitConfig->runtimeFlags & J9JIT_TOSS_CODE) || isJITServerMode) && comp)
9722
{
9723
if (jitConfig->runtimeFlags & J9JIT_TOSS_CODE)
9724
jitConfig->codeCache->heapAlloc = jitConfig->codeCache->heapBase;
9725
9726
dataCache = (TR_DataCache*)comp->getReservedDataCache();
9727
if (dataCache)
9728
{
9729
dataCache->resetAllocationToMark();
9730
// TODO: make sure we didn't allocate a new dataCache (the mark was set in the old cache)
9731
TR_DataCacheManager::getManager()->makeDataCacheAvailable(dataCache);
9732
comp->setReservedDataCache(NULL);
9733
}
9734
}
9735
9736
return startPC;
9737
}
9738
9739
if (details.isMethodInProgress())
9740
{
9741
#if defined(J9VM_OPT_JITSERVER)
9742
if (isJITServerMode)
9743
{
9744
if (startPC) // compilation succeeded
9745
{
9746
outOfProcessCompilationEnd(entry, comp);
9747
}
9748
else if (entry) // failure
9749
{
9750
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
9751
{
9752
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
9753
"compThreadID=%d has failed to compile a DLT method", entry->_compInfoPT->getCompThreadId());
9754
}
9755
Trc_JITServerFailedToCompileDLT(vmThread, entry->_compInfoPT->getCompThreadId());
9756
int8_t compErrCode = entry->_compErrCode;
9757
if (compErrCode != compilationStreamInterrupted && compErrCode != compilationStreamFailure)
9758
entry->_stream->writeError(compErrCode);
9759
}
9760
}
9761
else // local compilation
9762
#endif /* defined(J9VM_OPT_JITSERVER) */
9763
{
9764
if (startPC) // compilation succeeded
9765
{
9766
#ifdef J9VM_JIT_DYNAMIC_LOOP_TRANSFER
9767
J9::MethodInProgressDetails & dltDetails = static_cast<J9::MethodInProgressDetails &>(details);
9768
TR::CompilationInfo *compInfo = TR::CompilationInfo::get();
9769
compInfo->insertDLTRecord(dltDetails.getMethod(), dltDetails.getByteCodeIndex(), startPC);
9770
jitMarkMethodReadyForDLT(vmThread, dltDetails.getMethod());
9771
#endif // ifdef J9VM_JIT_DYNAMIC_LOOP_TRANSFER
9772
}
9773
}
9774
9775
if (((jitConfig->runtimeFlags & J9JIT_TOSS_CODE) || isJITServerMode) && comp)
9776
{
9777
if (jitConfig->runtimeFlags & J9JIT_TOSS_CODE)
9778
jitConfig->codeCache->heapAlloc = jitConfig->codeCache->heapBase;
9779
9780
dataCache = (TR_DataCache *)comp->getReservedDataCache();
9781
if (dataCache)
9782
{
9783
dataCache->resetAllocationToMark();
9784
// TODO: make sure we didn't allocate a new dataCache (the mark was set in the old cache)
9785
TR_DataCacheManager::getManager()->makeDataCacheAvailable(dataCache);
9786
comp->setReservedDataCache(NULL);
9787
}
9788
}
9789
return startPC;
9790
}
9791
9792
if (!fe)
9793
fe = TR_J9VMBase::get(jitConfig, vmThread);
9794
9795
TR_J9VMBase *trvm = (TR_J9VMBase *)fe;
9796
9797
if (details.isMethodHandleThunk())
9798
{
9799
#if defined(J9VM_OPT_JITSERVER)
9800
if (isJITServerMode)
9801
{
9802
if (startPC) // compilation succeeded
9803
{
9804
outOfProcessCompilationEnd(entry, comp);
9805
}
9806
else if (entry) // failure
9807
{
9808
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
9809
{
9810
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
9811
"compThreadID=%d has failed to compile a methodHandleThunk method", entry->_compInfoPT->getCompThreadId());
9812
}
9813
Trc_JITServerFailedToCompileMethodHandleThunk(vmThread, entry->_compInfoPT->getCompThreadId());
9814
int8_t compErrCode = entry->_compErrCode;
9815
if (compErrCode != compilationStreamInterrupted && compErrCode != compilationStreamFailure)
9816
entry->_stream->writeError(compErrCode);
9817
}
9818
}
9819
else // local compilation
9820
#endif /* defined(J9VM_OPT_JITSERVER) */
9821
{
9822
if (startPC)
9823
{
9824
J9::MethodHandleThunkDetails &mhDetails = static_cast<J9::MethodHandleThunkDetails &>(details);
9825
uintptr_t thunks = trvm->getReferenceField(*mhDetails.getHandleRef(), "thunks", "Ljava/lang/invoke/ThunkTuple;");
9826
int64_t jitEntryPoint = (int64_t)(intptr_t)startPC + J9::PrivateLinkage::LinkageInfo::get(startPC)->getJitEntryOffset();
9827
9828
#if defined(JIT_METHODHANDLE_TRANSLATED)
9829
jitMethodHandleTranslated(vmThread, *mhDetails.getHandleRef(), mhDetails.getArgRef() ? *mhDetails.getArgRef() : NULL, jitEntryPoint, startPC);
9830
#else
9831
// This doesn't need to be volatile. On 32-bit, we don't care about
9832
// word-tearing because it's a 32-bit address; on 64-bit, we don't get
9833
// word-tearing of aligned 64-bit stores on any platform we care about.
9834
//
9835
trvm->setInt64Field(thunks, "invokeExactThunk", jitEntryPoint);
9836
trvm->setInt64Field(thunks, "i2jInvokeExactThunk", (intptr_t)startPC);
9837
#endif
9838
deleteMethodHandleRef(mhDetails, vmThread, trvm);
9839
}
9840
else // TODO:JSR292: Handle compile failures gracefully
9841
{
9842
}
9843
}
9844
9845
if (((jitConfig->runtimeFlags & J9JIT_TOSS_CODE) || isJITServerMode) && comp)
9846
{
9847
if (jitConfig->runtimeFlags & J9JIT_TOSS_CODE)
9848
jitConfig->codeCache->heapAlloc = jitConfig->codeCache->heapBase;
9849
9850
dataCache = (TR_DataCache*)comp->getReservedDataCache();
9851
if (dataCache)
9852
{
9853
dataCache->resetAllocationToMark();
9854
// TODO: make sure we didn't allocate a new dataCache (the mark was set in the old cache)
9855
TR_DataCacheManager::getManager()->makeDataCacheAvailable(dataCache);
9856
comp->setReservedDataCache(NULL);
9857
}
9858
}
9859
9860
return startPC;
9861
}
9862
9863
J9Method *method = details.getMethod();
9864
9865
if (startPC) // if successful compilation
9866
{
9867
TR_ASSERT_FATAL(comp && entry, "comp object and entry must always exist when calling compilationEnd for a successful compilation");
9868
TR_ASSERT(vmThread, "We must always have a vmThread in compilationEnd()\n");
9869
#if defined(J9VM_OPT_JITSERVER)
9870
if (isJITServerMode)
9871
{
9872
outOfProcessCompilationEnd(entry, comp);
9873
}
9874
else
9875
#endif /* defined(J9VM_OPT_JITSERVER) */
9876
if (!(jitConfig->runtimeFlags & J9JIT_TOSS_CODE))
9877
{
9878
if (trvm->isAOT_DEPRECATED_DO_NOT_USE() && !entry->isRemoteCompReq())
9879
{
9880
// Committing AOT compilation that succeeded
9881
// We want to store AOT code in the cache
9882
#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))
9883
if (TR::Options::sharedClassCache())
9884
{
9885
J9JITExceptionTable *relocatedMetaData = NULL;
9886
const U_8 *dataStart;
9887
const U_8 *codeStart;
9888
UDATA dataSize, codeSize;
9889
9890
TR_ASSERT(comp, "AOT compilation that succeeded must have a compilation object");
9891
TR_ASSERT(comp->getAotMethodDataStart(), "The header must have been set");
9892
TR_AOTMethodHeader *aotMethodHeaderEntry = comp->getAotMethodHeaderEntry();
9893
9894
dataStart = (U_8 *)aotMethodHeaderEntry->compileMethodDataStartPC;
9895
dataSize = aotMethodHeaderEntry->compileMethodDataSize;
9896
codeStart = (U_8 *)aotMethodHeaderEntry->compileMethodCodeStartPC;
9897
codeSize = aotMethodHeaderEntry->compileMethodCodeSize;
9898
9899
aotMethodHeaderEntry->unused = TR::Compiler->host.is64Bit() ? 0xDEADC0DEDEADC0DEULL : 0xDEADC0DE;
9900
9901
J9ROMMethod *romMethod = comp->fej9()->getROMMethodFromRAMMethod(method);
9902
9903
TR::CompilationInfo::storeAOTInSharedCache(
9904
vmThread,
9905
romMethod,
9906
dataStart,
9907
dataSize,
9908
codeStart,
9909
codeSize,
9910
comp,
9911
jitConfig,
9912
entry
9913
);
9914
9915
#if defined(J9VM_INTERP_AOT_RUNTIME_SUPPORT)
9916
9917
bool canRelocateMethod = TR::CompilationInfo::canRelocateMethod(comp);
9918
9919
if (canRelocateMethod)
9920
{
9921
J9JITDataCacheHeader *cacheEntry;
9922
9923
TR_ASSERT_FATAL(comp->cg(), "CodeGenerator must be allocated");
9924
9925
// Use same code cache as AOT compile
9926
//
9927
TR::CodeCache *aotMCCRuntimeCodeCache = comp->cg()->getCodeCache();
9928
TR_ASSERT(aotMCCRuntimeCodeCache, "Must have a reserved codeCache");
9929
cacheEntry = (J9JITDataCacheHeader *)dataStart;
9930
9931
// If compilation and/or slot monitors are held, they must now be released in order to call the
9932
// AOT relocation.
9933
//
9934
if (entry->getMonitor())
9935
{
9936
compInfo->debugPrint(vmThread, "\treleasing queue-slot monitor\n");
9937
compInfo->debugPrint(vmThread, "-AM\n");
9938
entry->releaseSlotMonitor(vmThread);
9939
}
9940
9941
compInfo->debugPrint(vmThread, "\treleasing compilation monitor\n");
9942
compInfo->debugPrint(vmThread, "-CM\n");
9943
compInfo->releaseCompMonitor(vmThread);
9944
int32_t returnCode = 0;
9945
9946
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
9947
{
9948
TR_VerboseLog::writeLineLocked(
9949
TR_Vlog_DISPATCH,
9950
"Applying relocations to newly AOT compiled body for %s @ %s",
9951
comp->signature(),
9952
comp->getHotnessName()
9953
);
9954
}
9955
try
9956
{
9957
TR::CompilationInfoPerThreadBase::InterruptibleOperation(*entry->_compInfoPT);
9958
// need to get a non-shared cache VM to relocate
9959
TR_J9VMBase *fe = TR_J9VMBase::get(jitConfig, vmThread);
9960
TR_ResolvedMethod *compilee = fe->createResolvedMethod(comp->trMemory(), (TR_OpaqueMethodBlock *)method);
9961
relocatedMetaData = entry->_compInfoPT->reloRuntime()->prepareRelocateAOTCodeAndData(
9962
vmThread,
9963
fe,
9964
aotMCCRuntimeCodeCache,
9965
cacheEntry,
9966
method,
9967
true,
9968
comp->getOptions(),
9969
comp,
9970
compilee
9971
);
9972
returnCode = entry->_compInfoPT->reloRuntime()->returnCode();
9973
}
9974
catch (std::exception &e)
9975
{
9976
// Relocation Failure
9977
returnCode = compilationAotRelocationInterrupted;
9978
}
9979
9980
// Reacquire the compilation and/or slot monitors
9981
//
9982
compInfo->debugPrint(vmThread, "\tacquiring compilation monitor\n");
9983
compInfo->acquireCompMonitor(vmThread);
9984
compInfo->debugPrint(vmThread, "+CM\n");
9985
9986
if (entry->getMonitor())
9987
{
9988
// Acquire the queue slot monitor now
9989
//
9990
compInfo->debugPrint(vmThread, "\tre-acquiring queue-slot monitor\n");
9991
entry->acquireSlotMonitor(vmThread);
9992
compInfo->debugPrint(vmThread, "+AM-", entry);
9993
}
9994
9995
if (relocatedMetaData)
9996
{
9997
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
9998
{
9999
TR_VerboseLog::writeLineLocked(TR_Vlog_DISPATCH, "Successfully relocated metadata for %s", comp->signature());
10000
}
10001
10002
startPC = reinterpret_cast<void *>(relocatedMetaData->startPC);
10003
10004
if (J9_EVENT_IS_HOOKED(jitConfig->javaVM->hookInterface, J9HOOK_VM_DYNAMIC_CODE_LOAD))
10005
{
10006
TR::CompilationInfo::addJ9HookVMDynamicCodeLoadForAOT(vmThread, method, jitConfig, relocatedMetaData);
10007
}
10008
jitMethodTranslated(vmThread, method, startPC);
10009
}
10010
else
10011
{
10012
entry->_doNotUseAotCodeFromSharedCache = true;
10013
entry->_compErrCode = returnCode;
10014
startPC = NULL;
10015
10016
if (entry->_compilationAttemptsLeft > 0)
10017
{
10018
entry->_tryCompilingAgain = true;
10019
}
10020
10021
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerbosePerformance, TR_VerboseCompFailure))
10022
{
10023
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE,
10024
"Failure while relocating for %s, return code = %d [%s]\n",
10025
comp->signature(),
10026
returnCode,
10027
(returnCode >= 0) && (returnCode < compilationMaxError) ? compilationErrorNames[returnCode] : "unknown error");
10028
}
10029
}
10030
}
10031
10032
/*
10033
* Method cannot be relocated or relocation has failed.
10034
*/
10035
if (!canRelocateMethod || !relocatedMetaData)
10036
{
10037
// Must reclaim code cache, metadata, jittedBodyInfo, persistentMethodInfo,
10038
// assumptions and RI records that could have been allocated.
10039
//
10040
TR_AOTMethodHeader *aotMethodHeaderEntry = comp->getAotMethodHeaderEntry();
10041
J9JITDataCacheHeader *cacheEntry = (J9JITDataCacheHeader *)aotMethodHeaderEntry->compileMethodDataStartPC;
10042
J9JITDataCacheHeader *exceptionTableCacheEntry = (J9JITDataCacheHeader *)((U_8 *)cacheEntry + aotMethodHeaderEntry->offsetToExceptionTable);
10043
J9JITExceptionTable *metaData = (J9JITExceptionTable *) (exceptionTableCacheEntry + 1);
10044
10045
// The exception table is inserted in the AVL trees during the relocation
10046
// Since we didn't performed the relocation, we don't have to artifactManager->removeArtifact(metaData);
10047
10048
// Delete any assumptions that might still exist in persistent memory
10049
// The metadata parameter is NULL meaning that we want to delete ALL assumptions, including those for JBI
10050
compInfo->getPersistentInfo()->getRuntimeAssumptionTable()->reclaimAssumptions(comp->getMetadataAssumptionList(), NULL);
10051
10052
// reclaim code memory so we can use it for something else
10053
TR::CodeCacheManager::instance()->addFreeBlock(static_cast<void *>(metaData), reinterpret_cast<uint8_t *>(metaData->startPC));
10054
10055
metaData->constantPool = 0; // mark metadata as unloaded
10056
10057
TR_DataCache *dataCache = (TR_DataCache*)comp->getReservedDataCache();
10058
TR_ASSERT(dataCache, "A dataCache must be reserved for AOT compilations\n");
10059
// Make sure we didn't allocate a new dataCache (the mark was set in the old cache)
10060
TR_ASSERT(dataCache->getAllocationMark() == (uint8_t*)comp->getAotMethodDataStart(),
10061
"AllocationMark=%p does not match aotMethodDataStart=%p",
10062
dataCache->getAllocationMark(), comp->getAotMethodDataStart());
10063
dataCache->resetAllocationToMark();
10064
// Reservation will be cancelled at end of compilation
10065
10066
// Inform that metadata is now NULL
10067
if (entry->_compInfoPT)
10068
entry->_compInfoPT->setMetadata(NULL);
10069
10070
// mark that compilation failed
10071
startPC = oldStartPC;
10072
}
10073
#else
10074
/* If in the unlikely circumstance that AOT runtime support is off but AOT compilation occurred,
10075
* we should fail the compilation */
10076
jitMethodFailedTranslation(vmThread, method);
10077
#endif /* J9VM_INTERP_AOT_RUNTIME_SUPPORT */
10078
}
10079
else
10080
#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))
10081
{
10082
#ifdef AOT_DEBUG
10083
fprintf(stderr, "ERROR: AOT compiling but shared class is not available. Method will run interpreted\n");
10084
#endif
10085
TR_ASSERT(0, "shared classes flag not enabled yet we got an AOT compilation"); // This is a branch that is never expected to enter
10086
entry->_doNotUseAotCodeFromSharedCache = true;
10087
startPC = NULL;
10088
10089
if (entry->_compilationAttemptsLeft > 0)
10090
{
10091
entry->_tryCompilingAgain = true;
10092
}
10093
10094
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerbosePerformance, TR_VerboseCompFailure))
10095
{
10096
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"Shared Class not available for AOT compile for %s", comp->signature());
10097
}
10098
}
10099
}
10100
else // Non-AOT compilation or remote JIT/AOT compilations (at the JITClient)
10101
{
10102
if ((trvm->isAOT_DEPRECATED_DO_NOT_USE()
10103
#if defined(J9VM_OPT_JITSERVER)
10104
|| comp->isDeserializedAOTMethod()
10105
#endif /* defined(J9VM_OPT_JITSERVER) */
10106
) && !TR::CompilationInfo::canRelocateMethod(comp))
10107
{
10108
// Handle the case when relocations are delayed.
10109
// Delete any assumptions that might still exist in persistent memory
10110
// The metadata parameter is NULL meaning that we want to delete ALL assumptions, including those for JBI
10111
J9JITExceptionTable *metaData = (J9JITExceptionTable *) comp->getAotMethodDataStart();
10112
if (metaData)
10113
{
10114
compInfo->getPersistentInfo()->getRuntimeAssumptionTable()->reclaimAssumptions(comp->getMetadataAssumptionList(), NULL);
10115
10116
metaData->constantPool = 0; // mark metadata as unloaded
10117
}
10118
10119
if (entry->_compInfoPT)
10120
entry->_compInfoPT->setMetadata(NULL);
10121
startPC = oldStartPC;
10122
}
10123
else
10124
{
10125
jitMethodTranslated(vmThread, method, startPC);
10126
}
10127
}
10128
}
10129
10130
// If this is a retranslation, fix up the old method to forward to the new one
10131
//
10132
if (oldStartPC)
10133
{
10134
if (TR::Options::getVerboseOption(TR_VerboseCodeCache))
10135
{
10136
OMR::CodeCacheMethodHeader *oldMethodHeader = getCodeCacheMethodHeader((char*)oldStartPC, 32, NULL);
10137
OMR::CodeCacheMethodHeader *recompiledMethodHeader = getCodeCacheMethodHeader((char*)startPC, 32, NULL);
10138
UDATA oldEndPC = oldMethodHeader ? oldMethodHeader->_metaData->endPC : -1;
10139
UDATA endPC = recompiledMethodHeader ? recompiledMethodHeader->_metaData->endPC : -1;
10140
int oldMethodSize = oldMethodHeader ? (oldEndPC - (UDATA)oldStartPC + 1) : -1;
10141
int methodSize = recompiledMethodHeader ? (endPC - (UDATA)startPC + 1) : -1;
10142
10143
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO,"Recompile %s @ " POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT "(%d bytes) -> " POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT "(%d bytes)", comp->signature(), oldStartPC, oldEndPC, oldMethodSize, startPC, endPC, methodSize);
10144
}
10145
10146
TR::Recompilation::methodHasBeenRecompiled(oldStartPC, startPC, trvm);
10147
}
10148
}
10149
else if (!oldStartPC)
10150
{
10151
// Tell the VM that a non-compiled method failed translation
10152
//
10153
if (vmThread && entry && !entry->isOutOfProcessCompReq())
10154
jitMethodFailedTranslation(vmThread, method);
10155
#if defined(J9VM_OPT_JITSERVER)
10156
if (entry && isJITServerMode) // failure at the JITServer
10157
{
10158
// If no error code is set but the compilation failed,
10159
// it means the diagnostic JitDump compilation crashed.
10160
// We still need to notify the client, so manually set the error to compilationFailure
10161
if (entry->_compErrCode == compilationOK)
10162
entry->_compErrCode = compilationFailure;
10163
10164
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
10165
{
10166
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
10167
"compThreadID=%d has failed to compile: compErrCode %u %s",
10168
entry->_compInfoPT->getCompThreadId(), entry->_compErrCode, comp ? comp->signature() : "");
10169
}
10170
if (vmThread)
10171
Trc_JITServerFailedToCompile(vmThread, entry->_compInfoPT->getCompThreadId(), entry->_compErrCode,
10172
comp ? comp->signature() : "", comp ? comp->getHotnessName() : "");
10173
10174
static bool breakAfterFailedCompile = feGetEnv("TR_breakAfterFailedCompile") != NULL;
10175
if (breakAfterFailedCompile)
10176
{
10177
fprintf(stderr, "\n=== Failed to compile %s ===\n", comp ? comp->signature() : "");
10178
TR::Compiler->debug.breakPoint();
10179
}
10180
int8_t compErrCode = entry->_compErrCode;
10181
if (compErrCode != compilationStreamInterrupted && compErrCode != compilationStreamFailure)
10182
entry->_stream->writeError(compErrCode);
10183
}
10184
#endif /* defined(J9VM_OPT_JITSERVER) */
10185
}
10186
else // recompilation failure
10187
{
10188
// If this is a retranslation, fix up the old method to not try to recompile
10189
// again and return the oldStartPC as the new startPC so the old (fixed up)
10190
// method body is run
10191
//
10192
if (!isJITServerMode)
10193
TR::Recompilation::methodCannotBeRecompiled(oldStartPC, trvm);
10194
startPC = oldStartPC;
10195
#if defined(J9VM_OPT_JITSERVER)
10196
if (entry && isJITServerMode)
10197
{
10198
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
10199
{
10200
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer,
10201
"compThreadID=%d has failed to recompile: compErrCode %u %s",
10202
entry->_compInfoPT->getCompThreadId(), entry->_compErrCode, comp ? comp->signature() : "");
10203
}
10204
if (vmThread)
10205
Trc_JITServerFailedToRecompile(vmThread, entry->_compInfoPT->getCompThreadId(), entry->_compErrCode,
10206
comp ? comp->signature() : "", comp ? comp->getHotnessName() : "");
10207
10208
int8_t compErrCode = entry->_compErrCode;
10209
if (compErrCode != compilationStreamInterrupted && compErrCode != compilationStreamFailure)
10210
entry->_stream->writeError(compilationNotNeeded);
10211
}
10212
#endif /* defined(J9VM_OPT_JITSERVER) */
10213
}
10214
10215
if (((jitConfig->runtimeFlags & J9JIT_TOSS_CODE) || isJITServerMode) && comp)
10216
{
10217
if (jitConfig->runtimeFlags & J9JIT_TOSS_CODE)
10218
jitConfig->codeCache->heapAlloc = jitConfig->codeCache->heapBase;
10219
10220
dataCache = (TR_DataCache *)comp->getReservedDataCache();
10221
if (dataCache)
10222
{
10223
dataCache->resetAllocationToMark();
10224
// TODO: make sure we didn't allocate a new dataCache (the mark was set in the old cache)
10225
TR_DataCacheManager::getManager()->makeDataCacheAvailable(dataCache);
10226
comp->setReservedDataCache(NULL);
10227
}
10228
}
10229
10230
return startPC;
10231
}
10232
10233
// Ensure that only methods whose name (prefix) matches names in
10234
// the translation filter list are compiled.
10235
//
10236
bool
10237
TR::CompilationInfoPerThreadBase::methodCanBeCompiled(TR_Memory *trMemory, TR_FrontEnd * vm, TR_ResolvedMethod* method, TR_FilterBST * & filter)
10238
{
10239
filter = NULL;
10240
10241
static char *dontCompileNatives = feGetEnv("TR_DontCompile");
10242
10243
if (dontCompileNatives && (method->isNewInstanceImplThunk() || method->isJNINative()))
10244
{
10245
printf("don't compile because JNI or thunk\n");
10246
return false;
10247
}
10248
10249
if (!method->isCompilable(trMemory))
10250
return false;
10251
10252
char * methodName = method->nameChars();
10253
UDATA methodNameLen = method->nameLength();
10254
char * methodSig = method->signatureChars();
10255
UDATA methodSigLen = method->signatureLength();
10256
10257
if (!(_jitConfig->runtimeFlags & J9JIT_COMPILE_CLINIT) &&
10258
methodNameLen == 8 && !J9OS_STRNCMP(methodName, "<clinit>", 8))
10259
return false;
10260
10261
if (_jitConfig->bcSizeLimit && (method->maxBytecodeIndex() > _jitConfig->bcSizeLimit))
10262
return false;
10263
10264
// if we've translated something that has transformed a newInstanceImpl call to virtual call
10265
// to a thunk. Then we have to compile the thunk.
10266
//
10267
if (method->isNewInstanceImplThunk())
10268
{
10269
TR_J9VMBase *fej9 = (TR_J9VMBase *)vm;
10270
// Do not compile thunks for arrays
10271
return !fej9->isClassArray(method->classOfMethod());
10272
}
10273
10274
if (!TR::Options::getDebug())
10275
return true;
10276
10277
return TR::Options::getDebug()->methodCanBeCompiled(trMemory, method, filter);
10278
}
10279
10280
void TR::CompilationInfoPerThreadBase::logCompilationSuccess(
10281
J9VMThread * vmThread,
10282
TR_J9VMBase &vm,
10283
J9Method * method,
10284
TR::SegmentAllocator const &scratchSegmentProvider,
10285
TR_ResolvedMethod * compilee,
10286
TR::Compilation * compiler,
10287
TR_MethodMetaData * metaData,
10288
TR_OptimizationPlan * optimizationPlan
10289
)
10290
{
10291
if (!_methodBeingCompiled->isAotLoad())
10292
{
10293
J9JavaVM * javaVM = _jitConfig->javaVM;
10294
// Dump mixed mode disassembly listing.
10295
//
10296
if (compiler->getOutFile() != NULL && compiler->getOption(TR_TraceAll))
10297
compiler->getDebug()->dumpMixedModeDisassembly();
10298
10299
if (!vm.isAOT_DEPRECATED_DO_NOT_USE())
10300
{
10301
if (J9_EVENT_IS_HOOKED(javaVM->hookInterface, J9HOOK_VM_DYNAMIC_CODE_LOAD))
10302
{
10303
OMR::CodeCacheMethodHeader *ccMethodHeader;
10304
ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(javaVM->hookInterface, vmThread, method, (U_8*)metaData->startPC, metaData->endWarmPC - metaData->startPC, "JIT warm body", metaData);
10305
10306
if (metaData->startColdPC)
10307
{
10308
// Register the cold code section too
10309
//
10310
ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(javaVM->hookInterface, vmThread, method, (U_8*)metaData->startColdPC, metaData->endPC - metaData->startColdPC, "JIT cold body", metaData);
10311
}
10312
ccMethodHeader = getCodeCacheMethodHeader((char *)metaData->startPC, 32, metaData);
10313
if (ccMethodHeader && (metaData->bodyInfo != NULL))
10314
{
10315
J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get((void *)metaData->startPC);
10316
if (linkageInfo->isRecompMethodBody())
10317
{
10318
ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(javaVM->hookInterface, vmThread, method, (void *)((char*)ccMethodHeader->_eyeCatcher+4), metaData->startPC - (UDATA)((char*)ccMethodHeader->_eyeCatcher+4), "JIT method header", metaData);
10319
}
10320
}
10321
}
10322
}
10323
10324
PORT_ACCESS_FROM_JITCONFIG(_jitConfig);
10325
UDATA translationTime = j9time_usec_clock() - getTimeWhenCompStarted();
10326
if (TR::Options::_largeTranslationTime > 0 && translationTime > (UDATA)(TR::Options::_largeTranslationTime))
10327
{
10328
if (compiler->getOutFile() != NULL)
10329
trfprintf(compiler->getOutFile(), "Compilation took %d usec\n", (int32_t)translationTime);
10330
compiler->dumpMethodTrees("Post optimization trees for large computing method");
10331
}
10332
if (_onSeparateThread)
10333
{
10334
TR::CompilationInfoPerThread *cipt = (TR::CompilationInfoPerThread*)this;
10335
cipt->setLastCompilationDuration(translationTime / 1000);
10336
}
10337
10338
UDATA gcDataBytes = _jitConfig->lastGCDataAllocSize;
10339
UDATA atlasBytes = _jitConfig->lastExceptionTableAllocSize;
10340
10341
// Statistics for number of aoted methods that were recompiled
10342
//
10343
if (_methodBeingCompiled->_oldStartPC != 0) // this is a recompilation
10344
{
10345
TR_PersistentJittedBodyInfo *oldBodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(_methodBeingCompiled->_oldStartPC);
10346
// because this is a recompilation, the persistentJittedBodyInfo must exist
10347
if (oldBodyInfo->getIsAotedBody())
10348
_compInfo._statNumAotedMethodsRecompiled++;
10349
10350
// Statistics about Recompilations for bodies with Jprofiling
10351
if (oldBodyInfo->getUsesJProfiling())
10352
{
10353
if (compiler->getRecompilationInfo() &&
10354
compiler->getRecompilationInfo()->getJittedBodyInfo()->getMethodInfo()->getReasonForRecompilation() == TR_PersistentMethodInfo::RecompDueToJProfiling)
10355
_compInfo._statNumRecompilationForBodiesWithJProfiling++;
10356
}
10357
}
10358
// Statistics for compilations from LPQ
10359
if (_methodBeingCompiled->_reqFromSecondaryQueue)
10360
_compInfo.getLowPriorityCompQueue().incStatsCompFromLPQ(_methodBeingCompiled->_reqFromSecondaryQueue);
10361
10362
// Statistics about SamplingJProfiling bodies
10363
if (compiler->getRecompilationInfo() &&
10364
compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesSamplingJProfiling())
10365
_compInfo._statNumSamplingJProfilingBodies++;
10366
10367
// Statistics about JProfiling bodies
10368
if (compiler->getRecompilationInfo() &&
10369
compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesJProfiling())
10370
_compInfo._statNumJProfilingBodies++;
10371
10372
// Statistics about number of methods taken from the queue with JProfiling requests
10373
if (_methodBeingCompiled->_reqFromJProfilingQueue)
10374
_compInfo._statNumMethodsFromJProfilingQueue++;
10375
10376
if (_jitConfig->runtimeFlags & J9JIT_TOSS_CODE)
10377
{
10378
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "JIT %s OK\n", compiler->signature());
10379
}
10380
else
10381
{
10382
char compilationTypeString[15] = { 0 };
10383
TR::snprintfNoTrunc(compilationTypeString, sizeof(compilationTypeString), "%s%s",
10384
vm.isAOT_DEPRECATED_DO_NOT_USE() ? "AOT " : "",
10385
compiler->isProfilingCompilation() ? "profiled " : "");
10386
10387
UDATA startPC = 0;
10388
UDATA endWarmPC = 0;
10389
UDATA startColdPC = 0;
10390
UDATA endPC = 0;
10391
if (metaData)
10392
{
10393
startPC = metaData->startPC;
10394
startColdPC = metaData->startColdPC;
10395
endWarmPC = metaData->endWarmPC;
10396
endPC = metaData->endPC;
10397
}
10398
10399
TR_Hotness h = compiler->getMethodHotness();
10400
if (h < numHotnessLevels)
10401
{
10402
_compInfo._statsOptLevels[(int32_t)h]++;
10403
#if defined(J9VM_OPT_JITSERVER)
10404
if(_methodBeingCompiled->isRemoteCompReq())
10405
_compInfo._statsRemoteOptLevels[(int32_t)h]++;
10406
#endif /* defined(J9VM_OPT_JITSERVER) */
10407
}
10408
if (compilee->isJNINative())
10409
_compInfo._statNumJNIMethodsCompiled++;
10410
const char * hotnessString = compiler->getHotnessName(h);
10411
TR_ASSERT(hotnessString, "expected to have a hotness string");
10412
10413
const char * prexString = compiler->usesPreexistence() ? " prex" : "";
10414
10415
int32_t profilingCount = 0, profilingFrequencey = 0, counter = 0;
10416
if (compiler->isProfilingCompilation())
10417
{
10418
TR::Recompilation *recompInfo = compiler->getRecompilationInfo();
10419
profilingCount = recompInfo->getProfilingCount();
10420
profilingFrequencey = recompInfo->getProfilingFrequency();
10421
counter = recompInfo->getJittedBodyInfo()->getCounter(); // profiling invocation count
10422
}
10423
10424
char recompReason = '-';
10425
// For recompiled methods try to find the reason for recompilation
10426
if (_methodBeingCompiled->_oldStartPC)
10427
{
10428
TR_PersistentJittedBodyInfo *bodyInfo = TR::Recompilation::getJittedBodyInfoFromPC(_methodBeingCompiled->_oldStartPC);
10429
if (bodyInfo->getIsInvalidated())
10430
{
10431
recompReason = 'I'; // method was invalidated
10432
}
10433
else
10434
{
10435
switch (bodyInfo->getMethodInfo()->getReasonForRecompilation())
10436
{
10437
case TR_PersistentMethodInfo::RecompDueToThreshold:
10438
recompReason = 'T'; break;
10439
case TR_PersistentMethodInfo::RecompDueToCounterZero:
10440
recompReason = 'Z'; break;
10441
case TR_PersistentMethodInfo::RecompDueToMegamorphicCallProfile:
10442
recompReason = 'M'; break;
10443
case TR_PersistentMethodInfo::RecompDueToOptLevelUpgrade:
10444
recompReason = 'C'; break;
10445
case TR_PersistentMethodInfo::RecompDueToSecondaryQueue:
10446
recompReason = 'S'; break;
10447
case TR_PersistentMethodInfo::RecompDueToForcedAOTUpgrade:
10448
recompReason = 'A'; break;
10449
case TR_PersistentMethodInfo::RecompDueToRI:
10450
recompReason = 'R'; break;
10451
case TR_PersistentMethodInfo::RecompDueToJProfiling:
10452
recompReason = 'J'; break;
10453
case TR_PersistentMethodInfo::RecompDueToInlinedMethodRedefinition:
10454
recompReason = 'H'; break;
10455
case TR_PersistentMethodInfo::RecompDueToGCR:
10456
if (compiler->getOption(TR_NoOptServer))
10457
recompReason = 'g';// Guarded counting recompilation
10458
else
10459
recompReason = 'G';// Guarded counting recompilation
10460
_compInfo._statNumGCRInducedCompilations++;
10461
break;
10462
// TODO: add here the EDO case if we ever modify the codegen to track that
10463
} // end switch
10464
bodyInfo->getMethodInfo()->setReasonForRecompilation(0); // reset the flags
10465
}
10466
}
10467
10468
// If set, print verbose compile results, gc/exception, and/or time.
10469
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerboseGc, TR_VerboseRecompile, TR_VerbosePerformance, TR_VerboseOptimizer)
10470
|| (compiler->getOption(TR_CountOptTransformations) && compiler->getVerboseOptTransformationCount() >= 1))
10471
{
10472
const uint32_t bytecodeSize = TR::CompilationInfo::getMethodBytecodeSize(method);
10473
const bool isJniNative = compilee->isJNINative();
10474
TR_VerboseLog::CriticalSection vlogLock;
10475
TR_VerboseLog::write(TR_Vlog_COMP,"(%s%s) %s @ " POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT,
10476
compilationTypeString,
10477
hotnessString,
10478
compiler->signature(),
10479
startPC,
10480
startColdPC ? endWarmPC : endPC);
10481
10482
if (startColdPC)
10483
{
10484
TR_VerboseLog::write("/" POINTER_PRINTF_FORMAT "-" POINTER_PRINTF_FORMAT, startColdPC, endPC);
10485
}
10486
10487
j9jit_printf(_jitConfig, " %s", _methodBeingCompiled->getMethodDetails().name());
10488
10489
// Print recompilation reason
10490
// For methods compiled through sample thresholds, print also the CPU utilization
10491
if (recompReason == 'T')
10492
TR_VerboseLog::write(" %.2f%%", optimizationPlan->getPerceivedCPUUtil() / 10.0);
10493
10494
TR_VerboseLog::write(" %c", recompReason);
10495
TR_VerboseLog::write(" Q_SZ=%d Q_SZI=%d QW=%d", _compInfo.getMethodQueueSize(),
10496
_compInfo.getNumQueuedFirstTimeCompilations(), _compInfo.getQueueWeight());
10497
10498
TR_VerboseLog::write(" j9m=%p bcsz=%u", method, bytecodeSize);
10499
10500
if (!_methodBeingCompiled->_async)
10501
TR_VerboseLog::write(" sync"); // flag the synchronous compilations
10502
10503
if (isJniNative)
10504
TR_VerboseLog::write(" JNI"); // flag JNI compilations
10505
10506
if (compiler->getOption(TR_EnableOSR))
10507
TR_VerboseLog::write(" OSR");
10508
10509
if (compiler->getRecompilationInfo() && compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesGCR())
10510
TR_VerboseLog::write(" GCR");
10511
10512
if (compiler->getRecompilationInfo() && (compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesSamplingJProfiling() || compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesJProfiling()))
10513
TR_VerboseLog::write(" JPROF");
10514
10515
if (compiler->isDLT())
10516
TR_VerboseLog::write(" DLT@%d", compiler->getDltBcIndex());
10517
10518
if (_methodBeingCompiled->_reqFromSecondaryQueue)
10519
TR_VerboseLog::write(" LPQ");
10520
10521
if (_methodBeingCompiled->_reqFromJProfilingQueue)
10522
TR_VerboseLog::write(" JPQ");
10523
10524
#if defined(J9VM_OPT_JITSERVER)
10525
if (_methodBeingCompiled->isRemoteCompReq())
10526
{
10527
TR_VerboseLog::write(" remote");
10528
if (compiler->isDeserializedAOTMethod())
10529
TR_VerboseLog::write(" deserialized");
10530
}
10531
#endif /* defined(J9VM_OPT_JITSERVER) */
10532
10533
if (TR::Options::getVerboseOption(TR_VerboseGc))
10534
{
10535
TR_VerboseLog::write(" gc=%d atlas=%d", gcDataBytes, atlasBytes);
10536
}
10537
10538
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
10539
TR_VerboseLog::write(" time=%dus", translationTime);
10540
10541
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
10542
{
10543
TR_VerboseLog::write(
10544
" mem=[region=%llu system=%llu]KB",
10545
static_cast<unsigned long long>(scratchSegmentProvider.regionBytesAllocated())/1024,
10546
static_cast<unsigned long long>(scratchSegmentProvider.systemBytesAllocated())/1024);
10547
}
10548
10549
#if defined(WINDOWS) && defined(TR_TARGET_32BIT)
10550
if (TR::Options::getVerboseOption(TR_VerboseVMemAvailable))
10551
{
10552
J9MemoryInfo memInfo;
10553
PORT_ACCESS_FROM_JITCONFIG(_jitConfig);
10554
if (j9sysinfo_get_memory_info(&memInfo) == 0 &&
10555
memInfo.availVirtual != J9PORT_MEMINFO_NOT_AVAILABLE)
10556
TR_VerboseLog::write(" VMemAv=%u MB", static_cast<uint32_t>(memInfo.availVirtual >> 20));
10557
}
10558
#endif
10559
if (TR::Options::getVerboseOption(TR_VerboseRecompile))
10560
{
10561
TR_VerboseLog::write("%s [profiling c(%d), f(%d), ivc(%d)]", prexString, profilingCount, profilingFrequencey, counter);
10562
}
10563
10564
if (compiler->getOption(TR_CountOptTransformations) && compiler->getOption(TR_VerboseOptTransformations))
10565
{
10566
TR_VerboseLog::write(" transformations=%d", compiler->getVerboseOptTransformationCount());
10567
}
10568
10569
if (TR::Options::getVerboseOption(TR_VerboseOptimizer))
10570
{
10571
TR_VerboseLog::write(" opts=%d.%d", compiler->getLastPerformedOptIndex(), compiler->getLastPerformedOptSubIndex());
10572
}
10573
10574
if (TR::Options::isAnyVerboseOptionSet(TR_VerboseCompileEnd, TR_VerbosePerformance))
10575
{
10576
TR_VerboseLog::write(" compThreadID=%d", compiler->getCompThreadID());
10577
}
10578
10579
// print cached cpu usage (sampled elsewhere [samplerThreadProc])
10580
10581
CpuUtilization *cpuUtil = _compInfo.getCpuUtil();
10582
if (cpuUtil->isFunctional())
10583
{
10584
TR_VerboseLog::write(" CpuLoad=%d%%(%d%%avg) JvmCpu=%d%%",
10585
cpuUtil->getCpuUsage(),
10586
cpuUtil->getAvgCpuUsage(),
10587
cpuUtil->getVmCpuUsage());
10588
}
10589
10590
if (TR::Options::getVerboseOption(TR_VerboseCompilationThreads) && _onSeparateThread)
10591
{
10592
// CPU spent in comp thread is quite coarse (updated every 0.5 sec)
10593
// We could use getCpuTimeNow() if we wanted to be more accurate
10594
TR::CompilationInfoPerThread *cipt = (TR::CompilationInfoPerThread*)this;
10595
int32_t cpuUtil = cipt->getCompThreadCPU().getThreadLastCpuUtil();
10596
if (cpuUtil >= 0)
10597
TR_VerboseLog::write(" compCPU=%d%%", cpuUtil);
10598
}
10599
10600
TR_VerboseLog::writeLine("");
10601
}
10602
10603
char compilationAttributes[40] = { 0 };
10604
TR::snprintfNoTrunc(compilationAttributes, sizeof(compilationAttributes), "%s %s %s %s %s %s %s",
10605
prexString,
10606
!_methodBeingCompiled->_async ? "sync" : "",
10607
compilee->isJNINative()? "JNI" : "",
10608
compiler->getOption(TR_EnableOSR) ? "OSR" : "",
10609
(compiler->getRecompilationInfo() && compiler->getRecompilationInfo()->getJittedBodyInfo()->getUsesGCR()) ? "GCR" : "",
10610
compiler->isDLT() ? "DLT" : "",
10611
TR::CompilationInfo::isJSR292(method) ? "JSR292" : ""
10612
);
10613
10614
Trc_JIT_compileEnd15(vmThread, compilationTypeString, hotnessString, compiler->signature(),
10615
startPC, endWarmPC, startColdPC, endPC,
10616
translationTime, method, metaData,
10617
recompReason, _compInfo.getMethodQueueSize(), TR::CompilationInfo::getMethodBytecodeSize(method),
10618
static_cast<uint32_t>(
10619
(scratchSegmentProvider.systemBytesAllocated() / 1024) & static_cast<uint32_t>(-1)
10620
),
10621
compilationAttributes);
10622
10623
#ifdef TR_HOST_S390
10624
if (TR::Options::getVerboseOption(TR_VerboseMMap))
10625
{
10626
outputVerboseMMapEntries(compilee, metaData, compilationTypeString, hotnessString);
10627
}
10628
10629
#endif // ifdef TR_HOST_S390
10630
}
10631
}
10632
}
10633
10634
static void
10635
printCompFailureInfo(TR::Compilation * comp, const char * reason)
10636
{
10637
if (comp && comp->getOptions()->getAnyOption(TR_TraceAll))
10638
traceMsg(comp, "\n=== EXCEPTION THROWN (%s) ===\n", reason);
10639
}
10640
10641
void
10642
TR::CompilationInfoPerThreadBase::processException(
10643
J9VMThread *vmThread,
10644
TR::SegmentAllocator const &scratchSegmentProvider,
10645
TR::Compilation * compiler,
10646
volatile bool & haveLockedClassUnloadMonitor,
10647
const char *exceptionName
10648
) throw()
10649
{
10650
if (TR::Options::getVerboseOption(TR_VerboseCompilationDispatch))
10651
{
10652
TR_VerboseLog::writeLineLocked(
10653
TR_Vlog_DISPATCH,
10654
"Failed to finalize compiled body for %s @ %s",
10655
compiler->signature(),
10656
compiler->getHotnessName()
10657
);
10658
}
10659
10660
OMR::RuntimeAssumption **metadataAssumptionList = compiler->getMetadataAssumptionList();
10661
if (metadataAssumptionList && (*metadataAssumptionList))
10662
{
10663
compiler->getPersistentInfo()->getRuntimeAssumptionTable()->reclaimAssumptions(metadataAssumptionList, NULL);
10664
}
10665
10666
// Defect 194113 - still holding schedule monitor at this point, release it!
10667
//
10668
while (((TR::Monitor *)getCompilationInfo()->_schedulingMonitor)->owned_by_self())
10669
getCompilationInfo()->_schedulingMonitor->exit(); //the if monitor is still held, release
10670
10671
if (!compiler->getOption(TR_DisableNoVMAccess))
10672
{
10673
if (haveLockedClassUnloadMonitor)
10674
{
10675
// On the exception path the monitor may not be held
10676
// Do a test first, otherwise an internal assume will be triggered
10677
//
10678
if (TR::MonitorTable::get()->getClassUnloadMonitorHoldCount(getCompThreadId()) > 0)
10679
TR::MonitorTable::get()->readReleaseClassUnloadMonitor(getCompThreadId());
10680
}
10681
10682
if (!(vmThread->publicFlags & J9_PUBLIC_FLAGS_VM_ACCESS))
10683
acquireVMAccessNoSuspend(vmThread);
10684
}
10685
10686
if (TR::Options::getVerboseOption(TR_VerboseCompYieldStats))
10687
{
10688
if (compiler->getMaxYieldInterval() > TR::Options::_compYieldStatsThreshold)
10689
{
10690
TR_VerboseLog::CriticalSection vlogLock;
10691
compiler->printCompYieldStats();
10692
}
10693
}
10694
10695
PORT_ACCESS_FROM_JITCONFIG(_jitConfig);
10696
10697
bool shouldProcessExceptionCommonTasks = true;
10698
10699
try
10700
{
10701
throw;
10702
}
10703
10704
// The catch blocks below are ordered such that in each group of
10705
// blocks, the least derived type is at the end of the group.
10706
10707
/* Allocation Exceptions Start */
10708
catch (const TR::RecoverableCodeCacheError &e)
10709
{
10710
if (compiler->compileRelocatableCode())
10711
_methodBeingCompiled->_compErrCode = compilationAotCacheFullReloFailure;
10712
else
10713
_methodBeingCompiled->_compErrCode = compilationRecoverableCodeCacheError;
10714
}
10715
catch (const TR::CodeCacheError &e)
10716
{
10717
_methodBeingCompiled->_compErrCode = compilationCodeCacheError;
10718
}
10719
catch (const J9::RecoverableDataCacheError &e)
10720
{
10721
TR_ASSERT(compiler->compileRelocatableCode(),
10722
"Only AOT compiles should throw a J9::RecoverableDataCacheError exception\n");
10723
if (compiler->compileRelocatableCode())
10724
_methodBeingCompiled->_compErrCode = compilationAotCacheFullReloFailure;
10725
else
10726
_methodBeingCompiled->_compErrCode = compilationDataCacheError;
10727
}
10728
catch (const J9::DataCacheError &e)
10729
{
10730
_methodBeingCompiled->_compErrCode = compilationDataCacheError;
10731
}
10732
catch (const TR::RecoverableTrampolineError &e)
10733
{
10734
_methodBeingCompiled->_compErrCode = compilationRecoverableTrampolineFailure;
10735
}
10736
catch (const TR::TrampolineError &e)
10737
{
10738
_methodBeingCompiled->_compErrCode = compilationTrampolineFailure;
10739
}
10740
catch (const J9::LowPhysicalMemory &e)
10741
{
10742
_methodBeingCompiled->_compErrCode = compilationLowPhysicalMemory;
10743
}
10744
catch (const std::bad_alloc &e)
10745
{
10746
_methodBeingCompiled->_compErrCode = compilationHeapLimitExceeded;
10747
}
10748
/* Allocation Exceptions End */
10749
10750
/* IL Gen Exceptions Start */
10751
catch (const J9::AOTHasInvokeHandle &e)
10752
{
10753
_methodBeingCompiled->_compErrCode = compilationAotHasInvokehandle;
10754
}
10755
catch (const J9::AOTHasInvokeVarHandle &e)
10756
{
10757
_methodBeingCompiled->_compErrCode = compilationAotHasInvokeVarHandle;
10758
}
10759
catch (const J9::AOTHasInvokeSpecialInInterface &e)
10760
{
10761
_methodBeingCompiled->_compErrCode = compilationAotHasInvokeSpecialInterface;
10762
}
10763
catch (const J9::FSDHasInvokeHandle &e)
10764
{
10765
_methodBeingCompiled->_compErrCode = compilationRestrictedMethod;
10766
}
10767
catch (const J9::AOTHasPatchedCPConstant &e)
10768
{
10769
_methodBeingCompiled->_compErrCode = compilationAotPatchedCPConstant;
10770
}
10771
catch (const TR::NoRecompilationRecoverableILGenException &e)
10772
{
10773
_methodBeingCompiled->_compErrCode = compilationRestrictedMethod;
10774
}
10775
catch (const TR::ILGenFailure &e)
10776
{
10777
_methodBeingCompiled->_compErrCode = compilationILGenFailure;
10778
}
10779
catch (const TR::UnsupportedValueTypeOperation &e)
10780
{
10781
_methodBeingCompiled->_compErrCode = compilationILGenUnsupportedValueTypeOperationFailure;
10782
}
10783
/* IL Gen Exceptions End */
10784
10785
/* Runtime Failure Exceptions Start */
10786
catch (const J9::CHTableCommitFailure &e)
10787
{
10788
_methodBeingCompiled->_compErrCode = compilationCHTableCommitFailure;
10789
}
10790
catch (const J9::MetaDataCreationFailure &e)
10791
{
10792
_methodBeingCompiled->_compErrCode = compilationMetaDataFailure;
10793
}
10794
catch (const J9::AOTRelocationFailed &e)
10795
{
10796
// no need to set error code here because error code is set
10797
// in installAotCachedMethod when the relocation failed
10798
}
10799
/* Runtime Failure Exceptions End */
10800
10801
/* Insufficiently Aggressive Compilation Exceptions Start */
10802
catch (const J9::LambdaEnforceScorching &e)
10803
{
10804
_methodBeingCompiled->_compErrCode = compilationLambdaEnforceScorching;
10805
}
10806
catch (const J9::EnforceProfiling &e)
10807
{
10808
_methodBeingCompiled->_compErrCode = compilationEnforceProfiling;
10809
}
10810
catch (const TR::InsufficientlyAggressiveCompilation &e)
10811
{
10812
_methodBeingCompiled->_compErrCode = compilationNeededAtHigherLevel;
10813
}
10814
/* Insufficiently Aggressive Compilation Exceptions End */
10815
10816
/* Excessive Complexity Exceptions Start */
10817
catch (const TR::ExcessiveComplexity &e)
10818
{
10819
_methodBeingCompiled->_compErrCode = compilationExcessiveComplexity;
10820
}
10821
catch (const TR::MaxCallerIndexExceeded &e)
10822
{
10823
_methodBeingCompiled->_compErrCode = compilationMaxCallerIndexExceeded;
10824
}
10825
/* Excessive Complexity Exceptions End */
10826
10827
catch (const TR::CompilationInterrupted &e)
10828
{
10829
_methodBeingCompiled->_compErrCode = compilationInterrupted;
10830
}
10831
catch (const TR::UnimplementedOpCode &e)
10832
{
10833
_methodBeingCompiled->_compErrCode = compilationRestrictedMethod;
10834
}
10835
catch (const TR::GCRPatchFailure &e)
10836
{
10837
_methodBeingCompiled->_compErrCode = compilationGCRPatchFailure;
10838
}
10839
catch (const J9::AOTSymbolValidationManagerFailure &e)
10840
{
10841
_methodBeingCompiled->_compErrCode = compilationSymbolValidationManagerFailure;
10842
}
10843
catch (const J9::AOTNoSupportForAOTFailure &e)
10844
{
10845
_methodBeingCompiled->_compErrCode = compilationAOTNoSupportForAOTFailure;
10846
}
10847
catch (const J9::AOTRelocationRecordGenerationFailure &e)
10848
{
10849
_methodBeingCompiled->_compErrCode = compilationAOTRelocationRecordGenerationFailure;
10850
}
10851
catch (const J9::ClassChainPersistenceFailure &e)
10852
{
10853
shouldProcessExceptionCommonTasks = false;
10854
_methodBeingCompiled->_compErrCode = compilationCHTableCommitFailure;
10855
if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileEnd, TR_VerboseCompFailure))
10856
{
10857
uintptr_t translationTime = j9time_usec_clock() - getTimeWhenCompStarted(); //get the time it took to fail the compilation
10858
char compilationTypeString[15] = { 0 };
10859
TR::snprintfNoTrunc(compilationTypeString, sizeof(compilationTypeString), "%s%s",
10860
compiler->fej9()->isAOT_DEPRECATED_DO_NOT_USE() ? "AOT " : "",
10861
compiler->isProfilingCompilation() ? "profiled " : "");
10862
TR_VerboseLog::writeLineLocked(
10863
TR_Vlog_COMPFAIL,
10864
"(%s%s) %s Q_SZ=%d Q_SZI=%d QW=%d j9m=%p time=%dus %s compThreadID=%d",
10865
compilationTypeString,
10866
compiler->getHotnessName(compiler->getMethodHotness()),
10867
compiler->signature(),
10868
_compInfo.getMethodQueueSize(),
10869
_compInfo.getNumQueuedFirstTimeCompilations(),
10870
_compInfo.getQueueWeight(),
10871
_methodBeingCompiled->getMethodDetails().getMethod(),
10872
translationTime,
10873
"Class chain persistence failure",
10874
getCompThreadId()
10875
);
10876
}
10877
Trc_JIT_compilationFailed(vmThread, compiler->signature(), -1);
10878
}
10879
catch (const TR::AssertionFailure &e)
10880
{
10881
shouldProcessExceptionCommonTasks = false;
10882
if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileEnd, TR_VerboseCompFailure))
10883
{
10884
uintptr_t translationTime = j9time_usec_clock() - getTimeWhenCompStarted(); //get the time it took to fail the compilation
10885
char compilationTypeString[15] = { 0 };
10886
TR::snprintfNoTrunc(compilationTypeString, sizeof(compilationTypeString), "%s%s",
10887
compiler->fej9()->isAOT_DEPRECATED_DO_NOT_USE() ? "AOT " : "",
10888
compiler->isProfilingCompilation() ? "profiled " : "");
10889
// This assertion will only be generated in production, when softFailOnAssumes is set.
10890
TR_VerboseLog::writeLineLocked(
10891
TR_Vlog_COMPFAIL,
10892
"(%s%s) %s Q_SZ=%d Q_SZI=%d QW=%d j9m=%p time=%dus Assertion Failure compThreadID=%d",
10893
compilationTypeString,
10894
compiler->getHotnessName(compiler->getMethodHotness()),
10895
compiler->signature(),
10896
_compInfo.getMethodQueueSize(),
10897
_compInfo.getNumQueuedFirstTimeCompilations(),
10898
_compInfo.getQueueWeight(),
10899
_methodBeingCompiled->getMethodDetails().getMethod(),
10900
translationTime,
10901
getCompThreadId()
10902
);
10903
}
10904
Trc_JIT_compilationFailed(vmThread, compiler->signature(), -1);
10905
}
10906
#if defined(J9VM_OPT_JITSERVER)
10907
catch (const JITServer::StreamFailure &e)
10908
{
10909
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
10910
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d JITServer StreamFailure: %s", getCompThreadId(), e.what());
10911
Trc_JITServerStreamFailure(vmThread, getCompThreadId(), __FUNCTION__, compiler->signature(), compiler->getHotnessName(), e.what());
10912
_methodBeingCompiled->_compErrCode = compilationStreamFailure;
10913
}
10914
catch (const JITServer::StreamInterrupted &e)
10915
{
10916
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
10917
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d JITServer StreamInterrupted: %s", getCompThreadId(), e.what());
10918
Trc_JITServerStreamInterrupted(vmThread, getCompThreadId(), __FUNCTION__, compiler->signature(), compiler->getHotnessName(), e.what());
10919
_methodBeingCompiled->_compErrCode = compilationStreamInterrupted;
10920
}
10921
catch (const JITServer::StreamVersionIncompatible &e)
10922
{
10923
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
10924
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d JITServer StreamVersionIncompatible: %s", getCompThreadId(), e.what());
10925
Trc_JITServerStreamVersionIncompatible(vmThread, getCompThreadId(), __FUNCTION__, compiler->signature(), compiler->getHotnessName(), e.what());
10926
_methodBeingCompiled->_compErrCode = compilationStreamVersionIncompatible;
10927
}
10928
catch (const JITServer::StreamMessageTypeMismatch &e)
10929
{
10930
if (TR::Options::getVerboseOption(TR_VerboseJITServer))
10931
TR_VerboseLog::writeLineLocked(TR_Vlog_JITServer, "compThreadID=%d JITServer StreamMessageTypeMismatch: %s", getCompThreadId(), e.what());
10932
Trc_JITServerStreamMessageTypeMismatch(vmThread, getCompThreadId(), __FUNCTION__, compiler->signature(), compiler->getHotnessName(), e.what());
10933
_methodBeingCompiled->_compErrCode = compilationStreamMessageTypeMismatch;
10934
}
10935
catch (const JITServer::ServerCompilationFailure &e)
10936
{
10937
// no need to set error code here because error code is set
10938
// in remoteCompile at JITClient when the compilation failed.
10939
}
10940
catch (const J9::AOTCacheDeserializationFailure &e)
10941
{
10942
// error code was already set in remoteCompile()
10943
}
10944
#endif /* defined(J9VM_OPT_JITSERVER) */
10945
catch (...)
10946
{
10947
_methodBeingCompiled->_compErrCode = compilationFailure;
10948
}
10949
10950
if (shouldProcessExceptionCommonTasks)
10951
processExceptionCommonTasks(vmThread, scratchSegmentProvider, compiler, exceptionName);
10952
10953
TR::IlGeneratorMethodDetails & details = _methodBeingCompiled->getMethodDetails();
10954
J9Method *method = details.getMethod();
10955
TRIGGER_J9HOOK_JIT_COMPILING_END(_jitConfig->hookInterface, vmThread, method);
10956
}
10957
10958
void
10959
TR::CompilationInfoPerThreadBase::processExceptionCommonTasks(
10960
J9VMThread *vmThread,
10961
TR::SegmentAllocator const &scratchSegmentProvider,
10962
TR::Compilation * compiler,
10963
const char *exceptionName
10964
)
10965
{
10966
PORT_ACCESS_FROM_JITCONFIG(_jitConfig);
10967
10968
if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileEnd, TR_VerboseCompFailure))
10969
{
10970
uintptr_t translationTime = j9time_usec_clock() - getTimeWhenCompStarted(); //get the time it took to fail the compilation
10971
10972
char compilationTypeString[15] = { 0 };
10973
TR::snprintfNoTrunc(compilationTypeString, sizeof(compilationTypeString), "%s%s",
10974
compiler->fej9()->isAOT_DEPRECATED_DO_NOT_USE() ? "AOT " : "",
10975
compiler->isProfilingCompilation() ? "profiled " : "");
10976
10977
const char *hotnessString = compiler->getHotnessName(compiler->getMethodHotness());
10978
10979
TR_VerboseLog::CriticalSection vlogLock;
10980
if (_methodBeingCompiled->_compErrCode != compilationFailure)
10981
{
10982
if ((_jitConfig->runtimeFlags & J9JIT_TOSS_CODE) && _methodBeingCompiled->_compErrCode == compilationInterrupted)
10983
{
10984
TR_VerboseLog::write(TR_Vlog_FAILURE, "Translating %s j9m=%p time=%dus-- Interrupted because of %s",
10985
compiler->signature(), _methodBeingCompiled->getMethodDetails().getMethod(), translationTime, exceptionName);
10986
}
10987
else
10988
{
10989
TR_VerboseLog::write(TR_Vlog_COMPFAIL, "(%s%s) %s Q_SZ=%d Q_SZI=%d QW=%d j9m=%p time=%dus %s memLimit=%zu KB",
10990
compilationTypeString,
10991
hotnessString,
10992
compiler->signature(),
10993
_compInfo.getMethodQueueSize(),
10994
_compInfo.getNumQueuedFirstTimeCompilations(),
10995
_compInfo.getQueueWeight(),
10996
_methodBeingCompiled->getMethodDetails().getMethod(),
10997
translationTime,
10998
compilationErrorNames[_methodBeingCompiled->_compErrCode],
10999
scratchSegmentProvider.allocationLimit() >> 10);
11000
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
11001
{
11002
bool incomplete;
11003
uint64_t freePhysicalMemorySizeB = _compInfo.computeAndCacheFreePhysicalMemory(incomplete);
11004
if (freePhysicalMemorySizeB != OMRPORT_MEMINFO_NOT_AVAILABLE)
11005
TR_VerboseLog::write(" freePhysicalMemory=%llu MB", freePhysicalMemorySizeB >> 20);
11006
}
11007
}
11008
}
11009
else
11010
{
11011
TR_VerboseLog::write(TR_Vlog_COMPFAIL, "(%s%s) %s Q_SZ=%d Q_SZI=%d QW=%d j9m=%p time=%dus <TRANSLATION FAILURE: %s>",
11012
compilationTypeString,
11013
hotnessString,
11014
compiler->signature(),
11015
_compInfo.getMethodQueueSize(),
11016
_compInfo.getNumQueuedFirstTimeCompilations(),
11017
_compInfo.getQueueWeight(),
11018
_methodBeingCompiled->getMethodDetails().getMethod(),
11019
translationTime,
11020
exceptionName);
11021
}
11022
11023
if (TR::Options::getVerboseOption(TR_VerbosePerformance))
11024
{
11025
TR_VerboseLog::write(
11026
" mem=[region=%llu system=%llu]KB",
11027
static_cast<unsigned long long>(scratchSegmentProvider.regionBytesAllocated())/1024,
11028
static_cast<unsigned long long>(scratchSegmentProvider.systemBytesAllocated())/1024);
11029
}
11030
TR_VerboseLog::writeLine(" compThreadID=%d", compiler->getCompThreadID());
11031
}
11032
11033
if(_methodBeingCompiled->_compErrCode == compilationFailure)
11034
{
11035
Trc_JIT_outOfMemory(vmThread);
11036
}
11037
else
11038
{
11039
Trc_JIT_compilationFailed(vmThread, compiler->signature(), -1);
11040
}
11041
}
11042
11043
void TR::CompilationInfo::printCompQueue()
11044
{
11045
fprintf(stderr, "\nQueue:");
11046
for (TR_MethodToBeCompiled *cur = _methodQueue; cur; cur = cur->_next)
11047
{
11048
fprintf(stderr, " %p", cur);
11049
}
11050
fprintf(stderr, "\n");
11051
}
11052
11053
#if DEBUG
11054
void
11055
TR::CompilationInfo::debugPrint(char * debugString)
11056
{
11057
if (!_traceCompiling)
11058
return;
11059
fprintf(stderr, "%s", debugString);
11060
}
11061
11062
void
11063
TR::CompilationInfo::debugPrint(J9VMThread * vmThread, char * debugString)
11064
{
11065
if (!_traceCompiling)
11066
return;
11067
fprintf(stderr, "%8" OMR_PRIxPTR ":", (uintptr_t)vmThread);
11068
fprintf(stderr, "%s", debugString);
11069
}
11070
11071
void
11072
TR::CompilationInfo::debugPrint(char * debugString, intptr_t val)
11073
{
11074
if (!_traceCompiling)
11075
return;
11076
fprintf(stderr, debugString, val);
11077
}
11078
11079
void
11080
TR::CompilationInfo::debugPrint(J9VMThread * vmThread, char * debugString, IDATA val)
11081
{
11082
if (!_traceCompiling)
11083
return;
11084
fprintf(stderr, "%8" OMR_PRIxPTR ":", (uintptr_t)vmThread);
11085
fprintf(stderr, debugString, val);
11086
}
11087
11088
void
11089
TR::CompilationInfo::debugPrint(J9Method * method)
11090
{
11091
if (!_traceCompiling)
11092
return;
11093
if (!method)
11094
{
11095
fprintf(stderr, "none");
11096
return;
11097
}
11098
J9UTF8 *className;
11099
J9UTF8 *name;
11100
J9UTF8 *signature;
11101
getClassNameSignatureFromMethod(method, className, name, signature);
11102
fprintf(stderr, "%.*s.%.*s%.*s", J9UTF8_LENGTH(className), (char *) J9UTF8_DATA(className),
11103
J9UTF8_LENGTH(name), (char *) J9UTF8_DATA(name),
11104
J9UTF8_LENGTH(signature), (char *) J9UTF8_DATA(signature));
11105
}
11106
11107
void
11108
TR::CompilationInfo::debugPrint(char * debugString, J9Method * method)
11109
{
11110
if (!_traceCompiling)
11111
return;
11112
fprintf(stderr, "%s for method ", debugString);
11113
debugPrint(method);
11114
fprintf(stderr, "\n");
11115
}
11116
11117
void
11118
TR::CompilationInfo::debugPrint(char * debugString, TR::IlGeneratorMethodDetails & details, J9VMThread * vmThread)
11119
{
11120
if (!_traceCompiling)
11121
return;
11122
fprintf(stderr, "%8" OMR_PRIxPTR ":", (uintptr_t)vmThread);
11123
if (details.isNewInstanceThunk())
11124
{
11125
J9Class *classForNewInstance = static_cast<J9::NewInstanceThunkDetails &>(details).classNeedingThunk();
11126
fprintf(stderr, "%s for newInstanceThunk ", debugString);
11127
int32_t len;
11128
TR_J9VMBase * fej9 = TR_J9VMBase::get(_jitConfig, vmThread);
11129
char * className = fej9->getClassNameChars(fej9->convertClassPtrToClassOffset(classForNewInstance), len);
11130
fprintf(stderr, "%.*s.newInstancePrototype(Ljava/lang/Class;)Ljava/lang/Object;\n", len, className);
11131
}
11132
else
11133
{
11134
fprintf(stderr, "%s for method ",debugString);
11135
debugPrint(details.getMethod());
11136
fprintf(stderr, "\n");
11137
}
11138
}
11139
11140
void
11141
TR::CompilationInfo::debugPrint(J9VMThread * vmThread, char * msg, TR_MethodToBeCompiled *entry)
11142
{
11143
if (!_traceCompiling)
11144
return;
11145
fprintf(stderr, "%8" OMR_PRIxPTR ":%s%d\n", (uintptr_t)vmThread, msg, entry->_index);
11146
}
11147
11148
// This method must be called with the Compilation Monitor in hand
11149
//
11150
void
11151
TR::CompilationInfo::printQueue()
11152
{
11153
if (!_traceCompiling)
11154
return;
11155
11156
fprintf(stderr, "\t\t\tActive: ");
11157
bool activeMethods = false;
11158
11159
for (int32_t i = 0; i < getNumTotalCompilationThreads(); i++)
11160
{
11161
TR::CompilationInfoPerThread *curCompThreadInfoPT = _arrayOfCompilationInfoPerThread[i];
11162
TR_ASSERT(curCompThreadInfoPT, "a thread's compinfo is missing\n");
11163
11164
TR_MethodToBeCompiled * methodBeingCompiled = curCompThreadInfoPT->getMethodBeingCompiled();
11165
11166
if (methodBeingCompiled)
11167
{
11168
activeMethods = true;
11169
fprintf(stderr, "(%4d) %d:", methodBeingCompiled->_numThreadsWaiting, methodBeingCompiled->_index);
11170
debugPrint(methodBeingCompiled->getMethodDetails().getMethod());
11171
}
11172
}
11173
if (!activeMethods)
11174
fprintf(stderr, "none");
11175
11176
for (TR_MethodToBeCompiled *p = _methodQueue; p; p = p->_next)
11177
{
11178
fprintf(stderr, "\n\t\t\tQueued: (%4d) %d:", p->_numThreadsWaiting, p->_index);
11179
debugPrint(p->getMethodDetails().getMethod());
11180
}
11181
fprintf(stderr, "\n");
11182
}
11183
#endif
11184
11185
11186
TR_HWProfiler *
11187
TR::CompilationInfo::getHWProfiler() const
11188
{
11189
return ((TR_JitPrivateConfig*)_jitConfig->privateConfig)->hwProfiler;
11190
}
11191
11192
TR_JProfilerThread *
11193
TR::CompilationInfo::getJProfilerThread() const
11194
{
11195
return ((TR_JitPrivateConfig*)_jitConfig->privateConfig)->jProfiler;
11196
}
11197
11198
int32_t
11199
TR::CompilationInfo::calculateCodeSize(TR_MethodMetaData *metaData)
11200
{
11201
int32_t codeSize = 0;
11202
11203
if (metaData)
11204
{
11205
codeSize = ((uint8_t*)metaData->endWarmPC) - (uint8_t*)metaData->startPC;
11206
if (metaData->startColdPC)
11207
codeSize += ((uint8_t*)metaData->endPC) - (uint8_t*)metaData->startColdPC;
11208
}
11209
11210
return codeSize;
11211
}
11212
11213
void
11214
TR::CompilationInfo::increaseUnstoredBytes(U_32 aotBytes, U_32 jitBytes)
11215
{
11216
#if 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))
11217
J9SharedClassConfig *scConfig = _jitConfig->javaVM->sharedClassConfig;
11218
if (scConfig && scConfig->increaseUnstoredBytes)
11219
scConfig->increaseUnstoredBytes(_jitConfig->javaVM, aotBytes, jitBytes);
11220
#endif
11221
}
11222
11223
11224
uint64_t
11225
TR::CompilationInfo::computeFreePhysicalMemory(bool &incompleteInfo)
11226
{
11227
bool incomplete = false;
11228
PORT_ACCESS_FROM_JITCONFIG(_jitConfig);
11229
11230
uint64_t freePhysicalMemory = OMRPORT_MEMINFO_NOT_AVAILABLE;
11231
J9MemoryInfo memInfo;
11232
if (0 == j9sysinfo_get_memory_info(&memInfo)
11233
&& memInfo.availPhysical != OMRPORT_MEMINFO_NOT_AVAILABLE
11234
&& memInfo.hostAvailPhysical != OMRPORT_MEMINFO_NOT_AVAILABLE)
11235
{
11236
freePhysicalMemory = memInfo.availPhysical;
11237
uint64_t freeHostPhysicalMemorySizeB = memInfo.hostAvailPhysical;
11238
11239
if (memInfo.cached != OMRPORT_MEMINFO_NOT_AVAILABLE)
11240
freePhysicalMemory += memInfo.cached;
11241
else
11242
incomplete = !_cgroupMemorySubsystemEnabled;
11243
11244
if (memInfo.hostCached != OMRPORT_MEMINFO_NOT_AVAILABLE)
11245
freeHostPhysicalMemorySizeB += memInfo.hostCached;
11246
else
11247
incomplete = true;
11248
#if defined(LINUX)
11249
if (memInfo.buffered != OMRPORT_MEMINFO_NOT_AVAILABLE)
11250
freePhysicalMemory += memInfo.buffered;
11251
else
11252
incomplete = incomplete || !_cgroupMemorySubsystemEnabled;
11253
11254
if (memInfo.hostBuffered != OMRPORT_MEMINFO_NOT_AVAILABLE)
11255
freeHostPhysicalMemorySizeB += memInfo.hostBuffered;
11256
else
11257
incomplete = true;
11258
#endif
11259
// If we run in a container, freePhysicalMemory is the difference between
11260
// the container memory limit and how much physical memory the container used
11261
// It's possible that on the entire machine there is less physical memory
11262
// available because other processes have consumed it. Thus, we need to take
11263
// into account the available physical memory on the host
11264
if (freeHostPhysicalMemorySizeB < freePhysicalMemory)
11265
freePhysicalMemory = freeHostPhysicalMemorySizeB;
11266
}
11267
else
11268
{
11269
incomplete= true;
11270
freePhysicalMemory = OMRPORT_MEMINFO_NOT_AVAILABLE;
11271
}
11272
11273
incompleteInfo = incomplete;
11274
return freePhysicalMemory;
11275
}
11276
11277
11278
uint64_t
11279
TR::CompilationInfo::computeAndCacheFreePhysicalMemory(bool &incompleteInfo, int64_t updatePeriodMs)
11280
{
11281
if (updatePeriodMs < 0)
11282
updatePeriodMs = (int64_t)TR::Options::getUpdateFreeMemoryMinPeriod();
11283
// If the OS ever gave us bad information, avoid future calls
11284
if (_cachedFreePhysicalMemoryB != OMRPORT_MEMINFO_NOT_AVAILABLE)
11285
{
11286
static int64_t lastUpdateTime = 0;
11287
int64_t crtElapsedTime = getPersistentInfo()->getElapsedTime();
11288
11289
if (lastUpdateTime == 0
11290
|| (crtElapsedTime - lastUpdateTime) >= updatePeriodMs)
11291
{
11292
// time to recompute freePhysicalMemory
11293
bool incomplete;
11294
uint64_t freeMem = computeFreePhysicalMemory(incomplete);
11295
11296
// Cache the computed value for future reference
11297
// Synchronization issues can be ignored here
11298
_cachedIncompleteFreePhysicalMemory = incomplete;
11299
_cachedFreePhysicalMemoryB = freeMem;
11300
lastUpdateTime = crtElapsedTime;
11301
}
11302
}
11303
incompleteInfo = _cachedIncompleteFreePhysicalMemory;
11304
return _cachedFreePhysicalMemoryB;
11305
}
11306
11307
11308
uint64_t
11309
TR::CompilationInfo::computeFreePhysicalLimitAndAbortCompilationIfLow(TR::Compilation *comp,
11310
bool &incompleteInfo,
11311
size_t sizeToAllocate)
11312
{
11313
uint64_t freePhysicalMemorySizeB = computeAndCacheFreePhysicalMemory(incompleteInfo);
11314
if (OMRPORT_MEMINFO_NOT_AVAILABLE != freePhysicalMemorySizeB)
11315
{
11316
bool fail = false;
11317
// Avoid consuming the last drop of physical memory for JIT (leave 50 MB for emergency)
11318
// TODO: the emergency could be generated from SWAP
11319
if (freePhysicalMemorySizeB >= (uint64_t)TR::Options::getSafeReservePhysicalMemoryValue())
11320
{
11321
freePhysicalMemorySizeB -= (uint64_t)TR::Options::getSafeReservePhysicalMemoryValue();
11322
// Fail the compilation now if the remaining physical memory is not enough
11323
// to perform a warm compilation that may use up to 'sizeToAllocate' memory
11324
// However, do not fail if information about physical memory is incomplete
11325
if (!incompleteInfo && freePhysicalMemorySizeB < sizeToAllocate)
11326
fail = true;
11327
}
11328
else
11329
{
11330
fail = !incompleteInfo;
11331
}
11332
if (fail)
11333
{
11334
if (TR::Options::isAnyVerboseOptionSet(TR_VerbosePerformance, TR_VerboseCompileEnd, TR_VerboseCompFailure))
11335
{
11336
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE, "Aborting Compilation: Low On Physical Memory %lld B", freePhysicalMemorySizeB);
11337
}
11338
11339
comp->failCompilation<J9::LowPhysicalMemory>("Low Physical Memory");
11340
}
11341
}
11342
return freePhysicalMemorySizeB;
11343
}
11344
11345
void
11346
TR::CompilationInfo::replenishInvocationCount(J9Method *method, TR::Compilation *comp)
11347
{
11348
// Replenish the counts of the method
11349
// We are holding the compilation monitor at this point
11350
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
11351
if (romMethod->modifiers & J9AccNative)// Never change the extra field of a native method
11352
return;
11353
11354
int32_t methodVMExtra = TR::CompilationInfo::getJ9MethodVMExtra(method);
11355
if ((methodVMExtra == 1) || (methodVMExtra == J9_JIT_QUEUED_FOR_COMPILATION))
11356
{
11357
int32_t count;
11358
#if defined(J9VM_OPT_JITSERVER)
11359
// Even if the option to disable AOT relocation delay was specified, we need to delay relocation of deserialized
11360
// AOT methods using SVM received from the JITServer AOT cache until the next interpreted invocation. Such methods
11361
// cannot be immediately relocated in the current implementation; see CompilationInfo::canRelocateMethod().
11362
if (comp->isDeserializedAOTMethodUsingSVM() && comp->getOption(TR_DisableDelayRelocationForAOTCompilations))
11363
count = 0;
11364
else
11365
#endif /* defined(J9VM_OPT_JITSERVER) */
11366
// We want to use high counts unless the user specified counts on the command line
11367
// or used useLowerMethodCounts (or -Xquickstart)
11368
if (TR::Options::getCountsAreProvidedByUser() || (TR::Options::startupTimeMatters() == TR_yes))
11369
count = getCount(romMethod, comp->getOptions(), comp->getOptions());
11370
else
11371
count = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod) ? TR_DEFAULT_INITIAL_BCOUNT : TR_DEFAULT_INITIAL_COUNT;
11372
11373
TR::CompilationInfo::setInvocationCount(method, count);
11374
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
11375
{
11376
// compiler must exist because startPC != NULL
11377
TR_VerboseLog::writeLineLocked(TR_Vlog_PERF, "Reencoding count=%d for %s j9m=%p ", count, comp->signature(), method);
11378
}
11379
}
11380
else
11381
{
11382
TR_ASSERT(false, "Unexpected value for method->extra = %p (method=%p)\n", TR::CompilationInfo::getJ9MethodExtra(method), method);
11383
}
11384
}
11385
11386
void
11387
TR::CompilationInfo::addJ9HookVMDynamicCodeLoadForAOT(J9VMThread* vmThread, J9Method* method, J9JITConfig* jitConfig, TR_MethodMetaData* relocatedMetaData)
11388
{
11389
OMR::CodeCacheMethodHeader *ccMethodHeader;
11390
ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(
11391
jitConfig->javaVM->hookInterface,
11392
vmThread,
11393
method,
11394
reinterpret_cast<void *>(relocatedMetaData->startPC),
11395
relocatedMetaData->endWarmPC - relocatedMetaData->startPC,
11396
"JIT warm body",
11397
relocatedMetaData
11398
);
11399
if (relocatedMetaData->startColdPC)
11400
{
11401
// Register the cold code section too
11402
//
11403
ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(
11404
jitConfig->javaVM->hookInterface,
11405
vmThread,
11406
method,
11407
reinterpret_cast<void *>(relocatedMetaData->startColdPC),
11408
relocatedMetaData->endPC - relocatedMetaData->startColdPC,
11409
"JIT cold body",
11410
relocatedMetaData
11411
);
11412
}
11413
ccMethodHeader = getCodeCacheMethodHeader(
11414
reinterpret_cast<char *>(relocatedMetaData->startPC),
11415
32,
11416
relocatedMetaData
11417
);
11418
if (ccMethodHeader && (relocatedMetaData->bodyInfo != NULL))
11419
{
11420
J9::PrivateLinkage::LinkageInfo *linkageInfo = J9::PrivateLinkage::LinkageInfo::get(reinterpret_cast<void *>(relocatedMetaData->startPC));
11421
if (linkageInfo->isRecompMethodBody())
11422
{
11423
ALWAYS_TRIGGER_J9HOOK_VM_DYNAMIC_CODE_LOAD(
11424
jitConfig->javaVM->hookInterface,
11425
vmThread,
11426
method,
11427
ccMethodHeader->_eyeCatcher + 4,
11428
relocatedMetaData->startPC - reinterpret_cast<uintptr_t>(ccMethodHeader->_eyeCatcher + 4),
11429
"JIT method header",
11430
relocatedMetaData
11431
);
11432
}
11433
}
11434
}
11435
11436
#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))
11437
void
11438
TR::CompilationInfo::storeAOTInSharedCache(
11439
J9VMThread *vmThread,
11440
J9ROMMethod *romMethod,
11441
const U_8 *dataStart,
11442
UDATA dataSize,
11443
const U_8 *codeStart,
11444
UDATA codeSize,
11445
TR::Compilation *comp,
11446
J9JITConfig *jitConfig,
11447
TR_MethodToBeCompiled *entry
11448
)
11449
{
11450
bool safeToStore;
11451
const J9JITDataCacheHeader *storedCompiledMethod = NULL;
11452
PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);
11453
TR::CompilationInfo *compInfo = TR::CompilationInfo::get();
11454
11455
if (static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader == TR_yes)
11456
{
11457
safeToStore = true;
11458
}
11459
else if (static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader == TR_maybe)
11460
{
11461
TR_ASSERT_FATAL(static_cast<TR_JitPrivateConfig *>(jitConfig->privateConfig)->aotValidHeader != TR_maybe, "Should not be possible for aotValidHeader to be TR_maybe at this point\n");
11462
}
11463
else
11464
{
11465
safeToStore = false;
11466
}
11467
11468
if (safeToStore)
11469
{
11470
const U_8 *metadataToStore = dataStart;
11471
const U_8 *codedataToStore = codeStart;
11472
int metadataToStoreSize = dataSize;
11473
int codedataToStoreSize = codeSize;
11474
11475
#ifdef COMPRESS_AOT_DATA
11476
try
11477
{
11478
if (!comp->getOption(TR_DisableAOTBytesCompression))
11479
{
11480
/**
11481
* For each compiled method data we store in the shareclass cache looks like following.
11482
* -----------------------------------------------------------------------------------------------------
11483
* | CompiledMethodWrapper | J9JITDataCacheHeader | TR_AOTMethodHeader | Metadata | Compiled Code Data |
11484
* -----------------------------------------------------------------------------------------------------
11485
*
11486
* When we compile a method, we send data from J9JITDataCacheHeader to store in the cache.
11487
* For each method Shared Class Cache API adds CompiledMethodWrapper header which holds the size of data in cache,
11488
* as well as J9ROMMethod of compiled method.
11489
* Size of the original data is extracted from the TR_AOTMethodHeader while size of compressed data is extracted from
11490
* CompiledMethodWrapper.
11491
* That is why We do not compress header as we can extract the original data size
11492
* which is useful information while inflating the method data while loading compiled method.
11493
*
11494
* Compressed data stored in the cache looks like following
11495
* ------------------------------------------------------------------------------------------------------------------------------------------------
11496
* | CompiledMethodWrapper | J9JITDataCacheHeader (UnCompressed)| TR_AOTMethodHeader (UnCompressed)| (Metadata + Compiled Code Data) (Compressed) |
11497
* ------------------------------------------------------------------------------------------------------------------------------------------------
11498
*
11499
*/
11500
void * originalData = comp->trMemory()->allocateHeapMemory(codeSize+dataSize);
11501
void * compressedData = comp->trMemory()->allocateHeapMemory(codeSize+dataSize);
11502
11503
// Copy the metadata and codedata combined into single buffer so that we can compress it together
11504
memcpy(originalData, dataStart, dataSize);
11505
memcpy((U_8*)(originalData)+dataSize, codeStart, codeSize);
11506
int aotMethodHeaderSize = sizeof(J9JITDataCacheHeader)+sizeof(TR_AOTMethodHeader);
11507
int compressedDataSize = deflateBuffer((U_8*)(originalData)+aotMethodHeaderSize, dataSize+codeSize-aotMethodHeaderSize, (U_8*)(compressedData)+aotMethodHeaderSize, Z_DEFAULT_COMPRESSION);
11508
if (compressedDataSize != COMPRESSION_FAILED)
11509
{
11510
/**
11511
* We are going to store both metadata and code in contiguous memory in shared class cache.
11512
* In load run we get the whole buffer from the cache and use the information from header to
11513
* Get the relocation data and compiled code.
11514
* Because of this reason we copy both metadata and compiled code in one buffer and deflate it together.
11515
* TODO: We will always query the shared class cache to get full data for stored AOT compiled method
11516
* that is combined meta data and code data. Even if compression of AOT bytes is disabled, we do not need
11517
* to send two different buffers to store in cache and also as no one queries either code data / metadata for
11518
* method, clean up the share classs cache API.
11519
*/
11520
const J9JITDataCacheHeader *aotMethodHeader = reinterpret_cast<const J9JITDataCacheHeader *>(dataStart);
11521
TR_AOTMethodHeader *aotMethodHeaderEntry = const_cast<TR_AOTMethodHeader *>(reinterpret_cast<const TR_AOTMethodHeader *>(aotMethodHeader + 1));
11522
11523
aotMethodHeaderEntry->flags |= TR_AOTMethodHeader_CompressedMethodInCache;
11524
memcpy(compressedData, dataStart, aotMethodHeaderSize);
11525
metadataToStore = (const U_8*) compressedData;
11526
metadataToStoreSize = compressedDataSize+aotMethodHeaderSize;
11527
codedataToStore = NULL;
11528
codedataToStoreSize = 0;
11529
if (TR::Options::getVerboseOption(TR_VerboseAOTCompression))
11530
{
11531
TR_VerboseLog::writeLineLocked(TR_Vlog_AOTCOMPRESSION, "%s : Compression of method data Successful - Original method size = %d bytes, Compressed Method Size = %d bytes",
11532
comp->signature(),
11533
dataSize+codeSize, metadataToStoreSize);
11534
}
11535
}
11536
else
11537
{
11538
if (TR::Options::getVerboseOption(TR_VerboseAOTCompression))
11539
{
11540
TR_VerboseLog::writeLineLocked(TR_Vlog_AOTCOMPRESSION, "!%s : Compression of method data Failed - Original method size = %d bytes",
11541
comp->signature(),
11542
dataSize+codeSize);
11543
}
11544
}
11545
}
11546
}
11547
catch (const std::bad_alloc &allocationFailure)
11548
{
11549
// In case we can not allocate extra memory to hold temp data for compressing, we still the uncompressed data into the cache
11550
if (TR::Options::getVerboseOption(TR_VerboseAOTCompression))
11551
{
11552
TR_VerboseLog::writeLineLocked(TR_Vlog_AOTCOMPRESSION, "!%s : Method will not be compressed as necessary memory can not be allocated, Method Size = %d bytes",
11553
comp->signature(),
11554
dataSize+codeSize);
11555
}
11556
}
11557
#endif /* COMPRESS_AOT_DATA */
11558
11559
storedCompiledMethod =
11560
reinterpret_cast<const J9JITDataCacheHeader*>(
11561
jitConfig->javaVM->sharedClassConfig->storeCompiledMethod(
11562
vmThread,
11563
romMethod,
11564
(const U_8*)metadataToStore,
11565
metadataToStoreSize,
11566
(const U_8*)codedataToStore,
11567
codedataToStoreSize,
11568
0));
11569
switch(reinterpret_cast<uintptr_t>(storedCompiledMethod))
11570
{
11571
case J9SHR_RESOURCE_STORE_FULL:
11572
{
11573
if (jitConfig->javaVM->sharedClassConfig->verboseFlags & J9SHR_VERBOSEFLAG_ENABLE_VERBOSE)
11574
j9nls_printf( PORTLIB, J9NLS_WARNING, J9NLS_RELOCATABLE_CODE_STORE_FULL);
11575
TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::SHARED_CACHE_FULL);
11576
disableAOTCompilations();
11577
}
11578
break;
11579
case J9SHR_RESOURCE_STORE_ERROR:
11580
{
11581
if (jitConfig->javaVM->sharedClassConfig->verboseFlags & J9SHR_VERBOSEFLAG_ENABLE_VERBOSE)
11582
j9nls_printf( PORTLIB, J9NLS_WARNING, J9NLS_RELOCATABLE_CODE_STORE_ERROR);
11583
TR_J9SharedCache::setSharedCacheDisabledReason(TR_J9SharedCache::SHARED_CACHE_STORE_ERROR);
11584
TR::Options::getAOTCmdLineOptions()->setOption(TR_NoLoadAOT);
11585
disableAOTCompilations();
11586
}
11587
}
11588
}
11589
else
11590
{
11591
if (TR::Options::getAOTCmdLineOptions()->getVerboseOption(TR_VerboseCompileEnd))
11592
{
11593
PORT_ACCESS_FROM_JAVAVM(jitConfig->javaVM);
11594
TR_VerboseLog::writeLineLocked(TR_Vlog_FAILURE, " Failed AOT cache validation");
11595
}
11596
11597
disableAOTCompilations();
11598
}
11599
}
11600
#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)) */
11601
11602
//===========================================================
11603
TR_LowPriorityCompQueue::TR_LowPriorityCompQueue()
11604
: _firstLPQentry(NULL), _lastLPQentry(NULL), _sizeLPQ(0), _LPQWeight(0),
11605
_trackingEnabled(false), _spine(NULL), _STAT_compReqQueuedByIProfiler(0), _STAT_conflict(0),
11606
_STAT_staleScrubbed(0), _STAT_bypass(0), _STAT_compReqQueuedByJIT(0), _STAT_LPQcompFromIprofiler(0),
11607
_STAT_LPQcompFromInterpreter(0), _STAT_LPQcompUpgrade(0), _STAT_compReqQueuedByInterpreter(0),
11608
_STAT_numFailedToEnqueueInLPQ(0)
11609
{
11610
}
11611
11612
TR_LowPriorityCompQueue::~TR_LowPriorityCompQueue()
11613
{
11614
if (_spine)
11615
jitPersistentFree(_spine);
11616
}
11617
11618
void TR_LowPriorityCompQueue::startTrackingIProfiledCalls(int32_t threshold)
11619
{
11620
if (threshold > 0 && _compInfo->getCpuUtil() && _compInfo->getCpuUtil()->isFunctional()) // Need to have support for CPU utilization
11621
{
11622
// Must allocate the cache
11623
_spine = (Entry*)jitPersistentAlloc(HT_SIZE * sizeof(Entry));
11624
if (_spine)
11625
{
11626
memset(_spine, 0, HT_SIZE * sizeof(Entry));
11627
_threshold = threshold;
11628
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
11629
{
11630
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Allocated the LPQ tracking hashtable", (uint32_t)_compInfo->getPersistentInfo()->getElapsedTime());
11631
}
11632
FLUSH_MEMORY(TR::Compiler->target.isSMP());
11633
_trackingEnabled = true;
11634
}
11635
}
11636
}
11637
11638
inline
11639
bool TR_LowPriorityCompQueue::isTrackableMethod(J9Method *j9method) const
11640
{
11641
return !TR::CompilationInfo::isCompiled(j9method) && TR::CompilationInfo::getJ9MethodVMExtra(j9method) > 0;
11642
}
11643
11644
// Search given j9method in the hashtable;
11645
// If method found, increment counter
11646
// if counter equals threshold, add compilation request to the "Idle queue"
11647
void TR_LowPriorityCompQueue::tryToScheduleCompilation(J9VMThread *vmThread, J9Method *j9method)
11648
{
11649
// avoid mocking with startup heuristics
11650
if ((jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP && !TR::Options::getCmdLineOptions()->getOption(TR_EarlyLPQ)) ||
11651
// generating more compilations when there is plenty of work is counterproductive
11652
_compInfo->getNumQueuedFirstTimeCompilations() >= TR::Options::_qsziMaxToTrackLowPriComp ||
11653
// conserve idle time in the long run
11654
_compInfo->getPersistentInfo()->getElapsedTime() > 3600000 ||
11655
// Methods that are already compiled or queued for compilation should not be tracked
11656
!isTrackableMethod(j9method))
11657
return;
11658
11659
// Find the j9method in the hashtable
11660
Entry *entry = _spine + TR_LowPriorityCompQueue::hash(j9method);
11661
if (entry->_j9method == (uintptr_t)j9method) // found match
11662
{
11663
if (++entry->_count > _threshold) // hot entry; possibly queue compilation
11664
{
11665
if (!entry->_queuedForCompilation)
11666
{
11667
// AOT compilations could be delayed in order to accumulate more
11668
// IProfiler information. For such methods we don't want to accelerate
11669
// the compilation. Because it is expensive to identify such methods
11670
// we only do it when we reached the threshold for compilation
11671
// TODO: can we actually detect first run?
11672
if (TR::Options::sharedClassCache() && // must have AOT enabled
11673
!TR::Options::getCmdLineOptions()->getOption(TR_DisableDelayRelocationForAOTCompilations) &&
11674
!TR::Options::getAOTCmdLineOptions()->getOption(TR_NoLoadAOT))
11675
{
11676
TR_J9VMBase *fe = TR_J9VMBase::get(jitConfig, vmThread);
11677
// Invalidate the entry so that another j9method can use it
11678
if (vmThread->javaVM->sharedClassConfig->existsCachedCodeForROMMethod(vmThread, fe->getROMMethodFromRAMMethod(j9method)))
11679
entry->setInvalid();
11680
}
11681
else
11682
{
11683
// Check that the invocation count has been decremented enough to accumulate
11684
// some IP info and then queue a low priority compilation request
11685
// We only look at loopy methods because there is a greater chance
11686
// they will have the invocation count decremented very little.
11687
bool enoughIPInfo;
11688
J9ROMMethod * romMethod = (J9ROMMethod*)J9_ROM_METHOD_FROM_RAM_METHOD(j9method);
11689
bool isLoopy = J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod);
11690
// Trying to guess the initial invocation count is error prone and adds overhead
11691
// We must use some quick and dirty solution. Always assume TR_DEFAULT_INITIAL_BCOUNT
11692
if (isLoopy)
11693
{
11694
// For AOT bodies we use scount
11695
// For bootstrap romMethods present in SCC (but no AOT body) and loaded during startup, use low counts
11696
// For everybody else use high counts
11697
int32_t guessedInitialCount = TR::Options::getCountsAreProvidedByUser() ?
11698
TR::Options::getCmdLineOptions()->getInitialBCount() :
11699
TR_DEFAULT_INITIAL_BCOUNT;
11700
int32_t crtInvocationCount = (int32_t)TR::CompilationInfo::getInvocationCount(j9method);
11701
enoughIPInfo = (crtInvocationCount + TR::Options::_invocationThresholdToTriggerLowPriComp < guessedInitialCount);
11702
}
11703
else
11704
{
11705
enoughIPInfo = true;
11706
}
11707
if (enoughIPInfo)
11708
{
11709
entry->_queuedForCompilation = true;
11710
11711
_compInfo->getCompilationMonitor()->enter();
11712
bool enqueued = addFirstTimeCompReqToLPQ(j9method, TR_MethodToBeCompiled::REASON_IPROFILER_CALLS);
11713
// If conditions allow for processing of an LPQ request
11714
// we may have to notify a sleeping thread or activate a new one
11715
if (enqueued && _compInfo->canProcessLowPriorityRequest())
11716
{
11717
if (_compInfo->getNumCompThreadsJobless() > 0)
11718
{
11719
_compInfo->getCompilationMonitor()->notifyAll();
11720
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
11721
{
11722
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u LPQ logic waking up a sleeping comp thread. Jobless=%d",
11723
(uint32_t)_compInfo->getPersistentInfo()->getElapsedTime(),
11724
_compInfo->getNumCompThreadsJobless());
11725
}
11726
}
11727
else // At least one thread is active.
11728
{
11729
// Do we need to activate another compilation thread?
11730
int32_t numCompThreadsSuspended = _compInfo->getNumUsableCompilationThreads() - _compInfo->getNumCompThreadsActive();
11731
// Do not activate the last suspended thread
11732
if (numCompThreadsSuspended > 1)
11733
{
11734
TR_YesNoMaybe activate = _compInfo->shouldActivateNewCompThread();
11735
// If the answer is TR_maybe we may have to look at how many
11736
// threads are allowed to work on LPQ requests
11737
if (activate == TR_yes ||
11738
(activate == TR_maybe &&
11739
TR::Options::getCmdLineOptions()->getOption(TR_ConcurrentLPQ) &&
11740
jitConfig->javaVM->phase == J9VM_PHASE_NOT_STARTUP && // ConcurrentLPQ is too damaging to startup
11741
_compInfo->getNumCompThreadsActive() + 2 < _compInfo->getNumTargetCPUs()
11742
)
11743
)
11744
{
11745
TR::CompilationInfoPerThread *compInfoPT = _compInfo->getFirstSuspendedCompilationThread();
11746
compInfoPT->resumeCompilationThread();
11747
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
11748
{
11749
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Activate compThread %d to handle LPQ request. Qweight=%d active=%d",
11750
(uint32_t)_compInfo->getPersistentInfo()->getElapsedTime(),
11751
compInfoPT->getCompThreadId(),
11752
_compInfo->getQueueWeight(),
11753
_compInfo->getNumCompThreadsActive());
11754
}
11755
}
11756
}
11757
}
11758
}
11759
_compInfo->getCompilationMonitor()->exit();
11760
11761
if (enqueued)
11762
{
11763
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))
11764
{
11765
TR_VerboseLog::writeLineLocked(TR_Vlog_CR, "t=%u Compile request to LPQ for j9m=%p loopy=%d smpl=%u cnt=%d Q_SZ=%d Q_SZI=%d LPQ_SZ=%d CPU=%d%% JVM_CPU=%d%%",
11766
(uint32_t)_compInfo->getPersistentInfo()->getElapsedTime(),
11767
j9method,
11768
isLoopy,
11769
entry->_count,
11770
(int32_t)TR::CompilationInfo::getInvocationCount(j9method),
11771
_compInfo->getMethodQueueSize(),
11772
_compInfo->getNumQueuedFirstTimeCompilations(),
11773
getLowPriorityQueueSize(),
11774
_compInfo->getCpuUtil()->getCpuUsage(),
11775
_compInfo->getCpuUtil()->getVmCpuUsage());
11776
}
11777
}
11778
else // could not generate a comp req, maybe because of OOM
11779
{
11780
entry->setInvalid();
11781
}
11782
}
11783
}
11784
}
11785
}
11786
}
11787
else // no match
11788
{
11789
if (entry->isInvalid()) // entry is invalid, so we can reuse it
11790
{
11791
entry->initialize(j9method, 1);
11792
}
11793
else
11794
{
11795
// Scrub for stale entries that hold compiled methods
11796
// To make sure that entry->_j9method is actually valid we need to purge entries on class unload
11797
if (!isTrackableMethod((J9Method*)entry->_j9method))
11798
{
11799
entry->setInvalid();
11800
_STAT_staleScrubbed++;
11801
entry->initialize(j9method, 1);
11802
}
11803
else
11804
{
11805
_STAT_conflict++;
11806
// An idea is to push a compilation for the existing entry if it's close to
11807
// reaching its compilation threshold
11808
//fprintf(stderr, "Conflict j9method=%p locationID=%u\n", j9method, TR_LowPriorityCompQueue::hash(j9method));
11809
}
11810
}
11811
}
11812
}
11813
11814
11815
void TR_LowPriorityCompQueue::stopTrackingMethod(J9Method *j9method)
11816
{
11817
Entry *entry = _spine + TR_LowPriorityCompQueue::hash(j9method);
11818
if (entry->_j9method == (uintptr_t)j9method)
11819
{
11820
//TR_ASSERT(entry->_queuedForCompilation, "Entry %p, j9method %p j9m=%p, count=%u queued=%d (should be 1)\n", entry, entry->_j9method, j9method, entry->_count, entry->_queuedForCompilation);
11821
entry->setInvalid();
11822
}
11823
}
11824
// Bad scenario: put method in LPQ. Method gets compiled normally and entry becomes scrubabble.
11825
// Then the same method (running interpreted) finds the same entry usable and stores something in there.
11826
11827
11828
void TR_LowPriorityCompQueue::purgeEntriesOnClassLoaderUnloading(J9ClassLoader *j9classLoader)
11829
{
11830
if (isTrackingEnabled())
11831
{
11832
TR_ASSERT(_spine, "_spine must non-null once tracking is enabled");
11833
Entry *endOfHT = _spine + HT_SIZE;
11834
for (Entry *entry = _spine; entry < endOfHT; entry++)
11835
{
11836
if (entry->_j9method && J9_CLASS_FROM_METHOD((J9Method *)entry->_j9method)->classLoader == j9classLoader)
11837
entry->setInvalid();
11838
}
11839
}
11840
}
11841
11842
void TR_LowPriorityCompQueue::purgeEntriesOnClassRedefinition(J9Class *j9class)
11843
{
11844
if (isTrackingEnabled())
11845
{
11846
TR_ASSERT(_spine, "_spine must non-null once tracking is enabled");
11847
Entry *endOfHT = _spine + HT_SIZE;
11848
for (Entry *entry = _spine; entry < endOfHT; entry++)
11849
{
11850
if (entry->_j9method && J9_CLASS_FROM_METHOD((J9Method *)entry->_j9method) == j9class)
11851
entry->setInvalid();
11852
}
11853
}
11854
}
11855
11856
void TR_LowPriorityCompQueue::incStatsCompFromLPQ(uint8_t reason)
11857
{
11858
switch (reason) {
11859
case TR_MethodToBeCompiled::REASON_IPROFILER_CALLS:
11860
_STAT_LPQcompFromIprofiler++; break;
11861
case TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED:
11862
_STAT_LPQcompFromInterpreter++; break;
11863
case TR_MethodToBeCompiled::REASON_UPGRADE:
11864
_STAT_LPQcompUpgrade++; break;
11865
default:
11866
TR_ASSERT(false, "No other known reason for LPQ compilations\n");
11867
}
11868
}
11869
11870
void TR_LowPriorityCompQueue::incStatsReqQueuedToLPQ(uint8_t reason)
11871
{
11872
switch (reason) {
11873
case TR_MethodToBeCompiled::REASON_IPROFILER_CALLS:
11874
_STAT_compReqQueuedByIProfiler++; break;
11875
case TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED:
11876
_STAT_compReqQueuedByInterpreter++; break;
11877
case TR_MethodToBeCompiled::REASON_UPGRADE:
11878
_STAT_compReqQueuedByJIT++; break;
11879
default:
11880
TR_ASSERT(false, "No other known reason for LPQ compilations\n");
11881
}
11882
}
11883
11884
void TR_LowPriorityCompQueue::printStats() const
11885
{
11886
fprintf(stderr, "Stats for LPQ:\n");
11887
11888
fprintf(stderr, " Requests for LPQ = %4u (Sources: IProfiler=%3u Interpreter=%3u JIT=%3u)\n",
11889
_STAT_compReqQueuedByIProfiler + _STAT_compReqQueuedByInterpreter + _STAT_compReqQueuedByJIT,
11890
_STAT_compReqQueuedByIProfiler, _STAT_compReqQueuedByInterpreter, _STAT_compReqQueuedByJIT);
11891
fprintf(stderr, " Comps. from LPQ = %4u (Sources: IProfiler=%3u Interpreter=%3u JIT=%3u)\n",
11892
_STAT_LPQcompFromIprofiler + _STAT_LPQcompFromInterpreter + _STAT_LPQcompUpgrade,
11893
_STAT_LPQcompFromIprofiler, _STAT_LPQcompFromInterpreter, _STAT_LPQcompUpgrade);
11894
11895
fprintf(stderr, " Conflicts = %4u (tried to cache j9method that didn't have space)\n", _STAT_conflict);
11896
fprintf(stderr, " Stale entries = %4u\n", _STAT_staleScrubbed); // we want very few of these, hopefully 0
11897
fprintf(stderr, " Bypass ocurrences= %4u (normal comp req hapened before the fast LPQ comp req)\n", _STAT_bypass);
11898
}
11899
11900
void TR_LowPriorityCompQueue::invalidateRequestsForUnloadedMethods(J9Class * unloadedClass)
11901
{
11902
TR_MethodToBeCompiled *cur = _firstLPQentry;
11903
TR_MethodToBeCompiled *prev = NULL;
11904
bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks);
11905
while (cur)
11906
{
11907
TR_MethodToBeCompiled *next = cur->_next;
11908
TR::IlGeneratorMethodDetails & details = cur->getMethodDetails();
11909
J9Method *method = details.getMethod();
11910
if (method)
11911
{
11912
if (J9_CLASS_FROM_METHOD(method) == unloadedClass ||
11913
(details.isNewInstanceThunk() &&
11914
static_cast<J9::NewInstanceThunkDetails &>(details).isThunkFor(unloadedClass)))
11915
{
11916
TR_ASSERT(cur->_priority < CP_SYNC_MIN,
11917
"Unloading cannot happen for SYNC requests");
11918
if (verbose)
11919
TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "Invalidating compile request from LPQ for method=%p class=%p", method, unloadedClass);
11920
11921
// detach from queue
11922
if (prev)
11923
prev->_next = cur->_next;
11924
else
11925
_firstLPQentry = cur->_next;
11926
if (cur == _lastLPQentry)
11927
_lastLPQentry = prev;
11928
_sizeLPQ--;
11929
decreaseLPQWeightBy(cur->_weight);
11930
11931
// put back into the pool
11932
_compInfo->recycleCompilationEntry(cur);
11933
}
11934
else
11935
{
11936
prev = cur;
11937
}
11938
}
11939
cur = next;
11940
}
11941
}
11942
11943
void TR_LowPriorityCompQueue::purgeLPQ()
11944
{
11945
while (_firstLPQentry)
11946
{
11947
TR_MethodToBeCompiled *cur = _firstLPQentry;
11948
_firstLPQentry = _firstLPQentry->_next;
11949
_sizeLPQ--;
11950
decreaseLPQWeightBy(cur->_weight);
11951
_compInfo->recycleCompilationEntry(cur);
11952
}
11953
_lastLPQentry = NULL;
11954
}
11955
11956
TR_MethodToBeCompiled * TR_LowPriorityCompQueue::extractFirstLPQRequest()
11957
{
11958
// take the top method out of the queue
11959
TR_MethodToBeCompiled *m = _firstLPQentry;
11960
_firstLPQentry = _firstLPQentry->_next;
11961
_sizeLPQ--;
11962
decreaseLPQWeightBy(m->_weight);
11963
if (!_firstLPQentry)
11964
_lastLPQentry = 0;
11965
return m;
11966
}
11967
11968
// Searches the entire LPQ queue for an entry with the given method and given "reason"
11969
// If method is not found we return NULL.
11970
// If given method is found but the "reason" does not match, the entry is returned
11971
// and the "dequeued" flag is set to false to indicate that the entry is still part of the LPQ
11972
// If method is found and the "reason" matches, the entry is detached and returned to the caller
11973
// while the "dequeued" flag is set to true.
11974
// Needs compilation queue monitor in hand
11975
TR_MethodToBeCompiled *
11976
TR_LowPriorityCompQueue::findAndDequeueFromLPQ(TR::IlGeneratorMethodDetails &details,
11977
uint8_t reason, TR_J9VMBase *fe, bool & dequeued)
11978
{
11979
dequeued = false;
11980
TR_MethodToBeCompiled *cur = _firstLPQentry, *prev = NULL;
11981
while (cur)
11982
{
11983
if (cur->getMethodDetails().sameAs(details, fe))
11984
{
11985
if (cur->_reqFromSecondaryQueue == reason)
11986
{
11987
// detach from queue
11988
if (prev)
11989
prev->_next = cur->_next;
11990
else
11991
_firstLPQentry = cur->_next;
11992
if (cur == _lastLPQentry)
11993
_lastLPQentry = prev;
11994
_sizeLPQ--;
11995
decreaseLPQWeightBy(cur->_weight);
11996
dequeued = true;
11997
break;
11998
}
11999
else
12000
{
12001
break; // Will return un-detached entry
12002
}
12003
}
12004
12005
prev = cur;
12006
cur = cur->_next;
12007
}
12008
12009
return cur;
12010
}
12011
12012
TR_CompilationErrorCode
12013
TR::CompilationInfo::scheduleLPQAndBumpCount(TR::IlGeneratorMethodDetails &details, TR_J9VMBase *fe)
12014
{
12015
J9Method *method = details.getMethod();
12016
// Search the LPQ and if not found, add method to LPQ and bump invocation count
12017
// If method is found, move it to main queue
12018
// We prevent concurrency issues by making sure the invocation count is 0 when adding to LPQ
12019
// We must make sure that if the method is not found in LPQ there is absolutely no way
12020
// it can be present in main queue (invocation count being 0 should guarantee us that
12021
// because a method waiting in main queue should be marked QUEUED_FOR_COMPILATION)
12022
// We should put an assert that all ordinary async first time compilations in the main
12023
// queue are marked QUEUED_FOR_COMPILATION
12024
// To summarize: methods in LPQ can have any invocation count, but methods
12025
// in main queue must have an invocation count of QUEUED_FOR_COMPILATION
12026
intptr_t count = getInvocationCount(method);
12027
if (count == 0)
12028
{
12029
bool dequeued = false;
12030
TR_MethodToBeCompiled *entry = getLowPriorityCompQueue().findAndDequeueFromLPQ(details, TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED, fe, dequeued);
12031
if (!dequeued) // Early compilation request
12032
{
12033
// Place request in LPQ if it doesn't already exist
12034
bool queued = true;
12035
if (entry)
12036
{
12037
// Change the reason so that when the counter expires again we move the entry to the main queue
12038
entry->_reqFromSecondaryQueue = TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED;
12039
}
12040
else // try to queue
12041
{
12042
queued = getLowPriorityCompQueue().addFirstTimeCompReqToLPQ(method, TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED);
12043
}
12044
if (queued)
12045
{
12046
// We must replenish the invocation count
12047
J9ROMMethod *romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(method);
12048
TR_ASSERT((romMethod->modifiers & J9AccNative) == 0, "Should not change invocation count for natives");
12049
12050
// Decide what value to add
12051
// TODO: look at options sets
12052
12053
intptr_t newCount = getCount(romMethod, TR::Options::getCmdLineOptions(), TR::Options::getAOTCmdLineOptions());
12054
newCount = newCount * (100 - TR::Options::_countPercentageForEarlyCompilation) / 100; // TODO: verify we don't have negative numbers
12055
if (TR::CompilationInfo::setInvocationCount(method, count, newCount))
12056
{
12057
if (TR::Options::getJITCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))
12058
TR_VerboseLog::writeLineLocked(TR_Vlog_CR, "j9m=%p Enqueued in LPQ. LPQ_SZ=%d. Count-->%d",
12059
method, getLowPriorityCompQueue().getLowPriorityQueueSize(), (int)newCount);
12060
return compilationNotNeeded;
12061
}
12062
else
12063
{
12064
// We couldn't set the count maybe because another thread set it to another value
12065
// Very unlikely to happen
12066
// Take the request out from LPQ and move it to main queue
12067
bool removed;
12068
TR_MethodToBeCompiled *req = getLowPriorityCompQueue().findAndDequeueFromLPQ(details, TR_MethodToBeCompiled::REASON_LOW_COUNT_EXPIRED, fe, removed);
12069
if (req && removed)
12070
{
12071
recycleCompilationEntry(req); // Put the request back into the pool
12072
}
12073
else
12074
{
12075
TR_ASSERT(false, "We must have found the entry we just added");
12076
// TODO: add some stats for this case
12077
}
12078
}
12079
}
12080
else // Couldn't queue to LPQ
12081
{
12082
// We must attempt to put it in the main queue
12083
getLowPriorityCompQueue().incNumFailuresToEnqueue();
12084
}
12085
}
12086
else // Invocation counter expired for a second time
12087
{
12088
// Delete this entry and create another one for main queue
12089
recycleCompilationEntry(entry); // Put the request back into the pool
12090
}
12091
}
12092
else // count is not 0
12093
{
12094
// This case can happen if two threads call compileMethod() at about the same time
12095
// The first thread may put a request in LPQ and increase the count
12096
// The second thread should just ignore the request.
12097
// We have to make sure that there is no other part of the code
12098
// that increases the invocation count
12099
// Release the compilation lock before returning
12100
return compilationNotNeeded;
12101
}
12102
12103
return compilationOK;
12104
}
12105
12106
12107
void TR_JitSampleInfo::update(uint64_t crtTime, uint32_t crtGlobalSampleCounter)
12108
{
12109
if (crtTime > _timestampOfLastInterval) // avoid races
12110
{
12111
// Compute size of last observation interval
12112
_sizeOfLastInterval = crtTime - _timestampOfLastInterval;
12113
// Compute nr of samples seen in last observation interval
12114
uint32_t diffSamples = crtGlobalSampleCounter - _globalSampleCounterInLastInterval;
12115
// Compute density of samples
12116
_samplesPerSecondDuringLastInterval = diffSamples * 1000 / _sizeOfLastInterval;
12117
// Prepare for next interval
12118
_timestampOfLastInterval = crtTime;
12119
_globalSampleCounterInLastInterval = crtGlobalSampleCounter;
12120
12121
if (_samplesPerSecondDuringLastInterval > _maxSamplesPerSecond) // update maximum
12122
{
12123
_maxSamplesPerSecond = _samplesPerSecondDuringLastInterval;
12124
// May have to change thresholds
12125
// For 0-199 samples/sec we want a threshold of 30
12126
// Anything above that will increase the window by 30 for each extra 400 samples/sec
12127
uint32_t increaseFactor = 1;
12128
if (_maxSamplesPerSecond >= TR::Options::_sampleDensityBaseThreshold)
12129
{
12130
increaseFactor = 2 + ((_maxSamplesPerSecond - TR::Options::_sampleDensityBaseThreshold) / TR::Options::_sampleDensityIncrementThreshold);
12131
}
12132
if (increaseFactor != _increaseFactor)
12133
{
12134
// Change the _increasefactor, but watch for overflow on 8 bit (Observation window must fit on 8 bits)
12135
uint32_t maxIncreaseFactor = 0xff / TR::Options::_sampleInterval;
12136
if (increaseFactor > maxIncreaseFactor)
12137
increaseFactor = maxIncreaseFactor;
12138
_increaseFactor = increaseFactor;
12139
}
12140
}
12141
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseSampleDensity))
12142
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u globalSamplesDensity: %u/%u=%u samples/sec max=%u samples/sec increaseFactor=%u",
12143
crtTime, diffSamples, _sizeOfLastInterval, _samplesPerSecondDuringLastInterval, _maxSamplesPerSecond, _increaseFactor);
12144
}
12145
}
12146
12147
12148
void TR_InterpreterSamplingTracking::addOrUpdate(J9Method *method, int32_t cnt)
12149
{
12150
// get the compilation queue monitor
12151
OMR::CriticalSection mon(_compInfo->getCompilationMonitor());
12152
12153
// search my method in the container
12154
TR_MethodCnt *item = _container;
12155
for (; item; item = item->_next)
12156
{
12157
if (item->_method == method)
12158
{
12159
item->_skippedCount += cnt; // update the skipped count
12160
break;
12161
}
12162
}
12163
// If method not in the collection yet, add it now
12164
if (!item)
12165
{
12166
item = new (PERSISTENT_NEW) TR_MethodCnt(method, cnt);
12167
if (item)
12168
{
12169
item->_next = _container;
12170
_container = item;
12171
_size++;
12172
if (_size > _maxElements)
12173
{
12174
_maxElements = _size;
12175
//fprintf(stderr, "Max size=%u\n", _maxElements);
12176
// _maxElements is about 60 for Liberty startup with no SCC/AOT
12177
}
12178
}
12179
}
12180
// compilation queue monitor automatically released
12181
}
12182
12183
int32_t TR_InterpreterSamplingTracking::findAndDelete(J9Method *method)
12184
{
12185
int32_t retValue = 0;
12186
TR_MethodCnt *itemToBeDeleted = NULL;
12187
12188
{ // Open a new context
12189
// get the compilation queue monitor.
12190
OMR::CriticalSection mon(_compInfo->getCompilationMonitor());
12191
TR_MethodCnt *item = _container;
12192
// search my method in the container
12193
for (TR_MethodCnt *prev = NULL; item; prev = item, item = item->_next)
12194
{
12195
if (item->_method == method)
12196
{
12197
// detach
12198
if (prev)
12199
prev->_next = item->_next;
12200
else
12201
_container = item->_next;
12202
retValue = item->_skippedCount;
12203
itemToBeDeleted = item;
12204
_size--;
12205
break;
12206
}
12207
}
12208
}
12209
// If element was found, free the memory
12210
if (itemToBeDeleted)
12211
jitPersistentFree(itemToBeDeleted);
12212
return retValue;
12213
}
12214
12215
12216
J9Method_HT::HT_Entry::HT_Entry(J9Method *j9method, uint64_t timestamp)
12217
:_next(NULL), _j9method(j9method), _count(TR::CompilationInfo::getInvocationCount(j9method)), _seqID(0), _timestamp(timestamp) {}
12218
12219
J9Method_HT::J9Method_HT(TR::PersistentInfo *persistentInfo)
12220
{
12221
memset(_spine, 0, HT_SIZE * sizeof(HT_Entry*));
12222
_persistentInfo = persistentInfo;
12223
_numEntries = 0;
12224
}
12225
12226
J9Method_HT::HT_Entry * J9Method_HT::find(J9Method *j9method) const
12227
{
12228
// Search DLT_HT for this method
12229
size_t bucketID = hash(j9method) & MASK;
12230
HT_Entry *entry = _spine[bucketID];
12231
for (; entry; entry = entry->_next)
12232
if (entry->_j9method == j9method)
12233
break;
12234
return entry;
12235
}
12236
12237
// onClassUnloading is executed when all threads are stopped
12238
// so there are no synchronization issues
12239
void J9Method_HT::onClassUnloading()
12240
{
12241
// Scan the entire DLT_HT and delete entries matching the given classloader
12242
// Also free invalid entries that have j9method==NULL
12243
for (size_t bucketID = 0; bucketID < HT_SIZE; bucketID++)
12244
{
12245
HT_Entry *entry = _spine[bucketID];
12246
HT_Entry *prev = NULL;
12247
while (entry)
12248
{
12249
J9Class *clazz = J9_CLASS_FROM_METHOD(entry->_j9method);
12250
12251
// Non-Anon classes will be unloaded with their classloaders, hence the class's classloader will be marked as dead.
12252
// Anon Classes can be independently unloaded without their classloaders, however their classes are marked as dying.
12253
if ( J9_ARE_ALL_BITS_SET(clazz->classLoader->gcFlags, J9_GC_CLASS_LOADER_DEAD)
12254
|| (J9CLASS_FLAGS(clazz) & J9AccClassDying) )
12255
{
12256
HT_Entry *removed = NULL;
12257
if (prev)
12258
prev->_next = entry->_next;
12259
else
12260
_spine[bucketID] = entry->_next;
12261
removed = entry;
12262
entry = entry->_next;
12263
removed->_next = NULL; // for safety
12264
jitPersistentFree(removed);
12265
_numEntries--;
12266
continue;
12267
}
12268
prev = entry;
12269
entry = entry->_next;
12270
}
12271
}
12272
}
12273
12274
bool J9Method_HT::addNewEntry(J9Method *j9method, uint64_t timestamp)
12275
{
12276
bool added = false;
12277
bool alreadyCompiled = TR::CompilationInfo::isCompiled(j9method);
12278
12279
if (_numEntries < 1000 // prevent pathological cases
12280
&& !alreadyCompiled)
12281
{
12282
size_t bucketID = hash(j9method) & MASK;
12283
HT_Entry * newEntry = new (PERSISTENT_NEW) HT_Entry(j9method, timestamp);
12284
if (newEntry) // test for OOM
12285
{
12286
newEntry->_next = _spine[bucketID];
12287
if (newEntry->_count < 0)
12288
newEntry->_count = 0;
12289
FLUSH_MEMORY(TR::Compiler->target.isSMP());
12290
_spine[bucketID] = newEntry;
12291
_numEntries++; // benign multithreading issue
12292
added = true;
12293
}
12294
}
12295
if (TR::Options::getVerboseOption(TR_VerboseSampling))
12296
TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING, "t=%6u J9MethodTracking: j9m=%p Adding new entry. compiled:%d success=%d totalEntries=%u",
12297
(unsigned)getPersistentInfo()->getElapsedTime(), j9method, alreadyCompiled, added, _numEntries);
12298
return added;
12299
}
12300
12301
bool DLTTracking::shouldIssueDLTCompilation(J9Method *j9method, int32_t numHitsInDLTBuffer)
12302
{
12303
bool shouldIssueDLT = false;
12304
int32_t methodCount = TR::CompilationInfo::getInvocationCount(j9method);
12305
if (methodCount <= 0 || numHitsInDLTBuffer >= TR::Options::_numDLTBufferMatchesToEagerlyIssueCompReq)
12306
{
12307
if (TR::Options::getVerboseOption(TR_VerboseSampling))
12308
TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING, "t=%6u DLTTracking: j9m=%p Issue DLT because methodCount=%d numHitsInDLTBuffer=%d",
12309
(unsigned)getPersistentInfo()->getElapsedTime(), j9method, methodCount, numHitsInDLTBuffer);
12310
return true;
12311
}
12312
// Search DLT_HT for this method
12313
HT_Entry *entry = find(j9method);
12314
12315
if (entry) // if method already exists in DLT_HT
12316
{
12317
// If the method's invocation count is the same as the one in the
12318
// entry, the thread could be stuck in this body. If we encounter
12319
// this situation several times in succession, we must issue a DLT request
12320
int32_t entryCount = entry->_count;
12321
12322
if (entryCount == methodCount)
12323
{
12324
entry->_seqID += 1;
12325
if (entry->_seqID >= TR::Options::_dltPostponeThreshold)
12326
{
12327
shouldIssueDLT = true;
12328
// TODO: should we invalidate this entry?
12329
}
12330
}
12331
else
12332
{
12333
// If the invocation count has shrunk since the last inspection
12334
// we must avoid issuing a DLT request because it's possible that
12335
// some threads have actually left the method (they are not stuck)
12336
if (methodCount < entryCount)
12337
{
12338
// Update the entry count with the invocation count seen when we last checked for DLT
12339
// Use a CAS construct get around synchronization issues
12340
int32_t oldValue;
12341
int32_t newValue;
12342
do {
12343
oldValue = entry->_count;
12344
newValue = TR::CompilationInfo::getInvocationCount(j9method);
12345
if (newValue < 0)
12346
newValue = 0;
12347
} while (oldValue != VM_AtomicSupport::lockCompareExchangeU32((uint32_t*)&entry->_count, oldValue, newValue));
12348
12349
entry->_seqID = 0; // should we reset this?
12350
}
12351
}
12352
if (TR::Options::getVerboseOption(TR_VerboseSampling))
12353
TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING, "t=%6u DLTTracking: j9m=%p issueDLT=%d entry=%p entryCount=%d methodCount=%d seqID=%d",
12354
(unsigned)getPersistentInfo()->getElapsedTime(), j9method, shouldIssueDLT, entry, entryCount, methodCount, entry->_seqID);
12355
}
12356
else // method does not exist in DLT_HT
12357
{
12358
// Add method to DLT_HT
12359
// If adding is successful, do not issue DLT request
12360
shouldIssueDLT = !addNewEntry(j9method, getPersistentInfo()->getElapsedTime());
12361
if (TR::Options::getVerboseOption(TR_VerboseSampling))
12362
TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING, "t=%6u DLTTracking: j9m=%p issueDLT=%d entry=%p",
12363
(unsigned)getPersistentInfo()->getElapsedTime(), j9method, shouldIssueDLT, entry);
12364
}
12365
12366
return shouldIssueDLT;
12367
}
12368
12369
12370
12371
void DLTTracking::adjustStoredCounterForMethod(J9Method *j9method, int32_t countDiff)
12372
{
12373
// Search DLT_HT for this method
12374
HT_Entry *entry = find(j9method);
12375
if (entry)
12376
{
12377
// Subtract from the stored count the value given by the second parameter
12378
// Use a CAS construct to get around synchronization issues
12379
int32_t oldValue;
12380
int32_t newValue;
12381
do {
12382
oldValue = entry->_count;
12383
newValue = oldValue - countDiff;
12384
if (newValue < 0)
12385
newValue = 0;
12386
} while (oldValue != VM_AtomicSupport::lockCompareExchangeU32((uint32_t*)&entry->_count, oldValue, newValue));
12387
if (TR::Options::getVerboseOption(TR_VerboseSampling))
12388
TR_VerboseLog::writeLineLocked(TR_Vlog_SAMPLING, "t=%6u DLTTracking: j9m=%p entry=%p adjusting entry count to %d",
12389
(unsigned)getPersistentInfo()->getElapsedTime(), j9method, entry, newValue);
12390
}
12391
}
12392
12393
12394
12395
// Must have compMonitor in hand
12396
void TR_JProfilingQueue::enqueueCompReq(TR_MethodToBeCompiled *compReq)
12397
{
12398
// add at the end of queue
12399
if (_lastQentry)
12400
_lastQentry->_next = compReq;
12401
else
12402
_firstQentry = compReq;
12403
12404
_lastQentry = compReq;
12405
_size++;
12406
increaseQWeightBy(compReq->_weight);
12407
}
12408
12409
// Must have compMonitor in hand
12410
TR_MethodToBeCompiled *TR_JProfilingQueue::extractFirstCompRequest()
12411
{
12412
// take the top method out of the queue
12413
TR_MethodToBeCompiled *m = _firstQentry;
12414
_firstQentry = _firstQentry->_next;
12415
if (!_firstQentry)
12416
_lastQentry = NULL;
12417
_size--;
12418
decreaseQWeightBy(m->_weight);
12419
return m;
12420
}
12421
12422
// Must have compMonitor in hand
12423
bool TR_JProfilingQueue::createCompReqAndQueueIt(TR::IlGeneratorMethodDetails &details, void *startPC)
12424
{
12425
TR_OptimizationPlan *plan = TR_OptimizationPlan::alloc(warm); // TODO: pick first opt level
12426
if (!plan)
12427
return false; // OOM
12428
12429
TR_MethodToBeCompiled * compReq = _compInfo->getCompilationQueueEntry();
12430
if (!compReq)
12431
{
12432
TR_OptimizationPlan::freeOptimizationPlan(plan);
12433
return false; // OOM
12434
}
12435
compReq->initialize(details, 0, CP_ASYNC_ABOVE_MIN, plan);
12436
compReq->_reqFromJProfilingQueue = true;
12437
compReq->_jitStateWhenQueued = _compInfo->getPersistentInfo()->getJitState();
12438
compReq->_oldStartPC = startPC;
12439
compReq->_async = true; // app threads are not waiting for it
12440
12441
// Determine entry weight
12442
J9Method *j9method = details.getMethod();
12443
J9ROMMethod * romMethod = J9_ROM_METHOD_FROM_RAM_METHOD(j9method);
12444
compReq->_weight = (J9ROMMETHOD_HAS_BACKWARDS_BRANCHES(romMethod)) ? TR::CompilationInfo::WARM_LOOPY_WEIGHT : TR::CompilationInfo::WARM_LOOPLESS_WEIGHT;
12445
// add at the end of queue
12446
enqueueCompReq(compReq);
12447
if (TR::Options::getJITCmdLineOptions()->getVerboseOption(TR_VerboseCompileRequest))
12448
TR_VerboseLog::writeLineLocked(TR_Vlog_CR, "t=%u j9m=%p enqueued in JPQ. JPQ_SZ=%d",
12449
(uint32_t)_compInfo->getPersistentInfo()->getElapsedTime(), j9method, getQSize());
12450
12451
//incStatsReqQueuedToLPQ(reason);
12452
return true;
12453
}
12454
12455
bool TR_JProfilingQueue::isJProfilingCandidate(TR_MethodToBeCompiled *entry, TR::Options *options, TR_J9VMBase* fej9)
12456
{
12457
if (!options->getOption(TR_EnableJProfiling) ||
12458
entry->isJNINative() ||
12459
entry->_oldStartPC != 0 || // reject non first time compilations
12460
!entry->getMethodDetails().isOrdinaryMethod() ||
12461
entry->_optimizationPlan->insertInstrumentation() ||
12462
!options->canJITCompile() ||
12463
options->getOption(TR_NoRecompile) ||
12464
!options->allowRecompilation())
12465
return false;
12466
12467
static char *disableFilterOnJProfiling = feGetEnv("TR_DisableFilterOnJProfiling");
12468
if (!disableFilterOnJProfiling &&
12469
!fej9->isClassLibraryMethod((TR_OpaqueMethodBlock *)entry->getMethodDetails().getMethod(), true))
12470
return false;
12471
12472
return true;
12473
}
12474
12475
// Must have compMonitor in hand
12476
void TR_JProfilingQueue::invalidateRequestsForUnloadedMethods(J9Class * unloadedClass)
12477
{
12478
TR_MethodToBeCompiled *cur = _firstQentry;
12479
TR_MethodToBeCompiled *prev = NULL;
12480
bool verbose = TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseHooks);
12481
while (cur)
12482
{
12483
TR_MethodToBeCompiled *next = cur->_next;
12484
TR::IlGeneratorMethodDetails & details = cur->getMethodDetails();
12485
J9Method *method = details.getMethod();
12486
if (method)
12487
{
12488
if (J9_CLASS_FROM_METHOD(method) == unloadedClass ||
12489
(details.isNewInstanceThunk() &&
12490
static_cast<J9::NewInstanceThunkDetails &>(details).isThunkFor(unloadedClass)))
12491
{
12492
TR_ASSERT(cur->_priority < CP_SYNC_MIN,
12493
"Unloading cannot happen for SYNC requests");
12494
if (verbose)
12495
TR_VerboseLog::writeLineLocked(TR_Vlog_HK, "Invalidating compile request from JPQ for method=%p class=%p", method, unloadedClass);
12496
12497
// detach from queue
12498
if (prev)
12499
prev->_next = cur->_next;
12500
else
12501
_firstQentry = cur->_next;
12502
if (cur == _lastQentry)
12503
_lastQentry = prev;
12504
_size--;
12505
decreaseQWeightBy(cur->_weight);
12506
12507
// put back into the pool
12508
_compInfo->recycleCompilationEntry(cur);
12509
}
12510
else
12511
{
12512
prev = cur;
12513
}
12514
}
12515
cur = next;
12516
}
12517
}
12518
12519
// Must have compMonitor in hand
12520
void TR_JProfilingQueue::purge()
12521
{
12522
while (_firstQentry)
12523
{
12524
TR_MethodToBeCompiled *cur = _firstQentry;
12525
_firstQentry = _firstQentry->_next;
12526
_size--;
12527
decreaseQWeightBy(cur->_weight);
12528
_compInfo->recycleCompilationEntry(cur);
12529
}
12530
_lastQentry = NULL;
12531
}
12532
12533
12534
// This method returns true when the JIT thinks it's a good
12535
// time to allow the generation of JProfiling bodies
12536
bool TR::CompilationInfo::canProcessJProfilingRequest()
12537
{
12538
// Once we allow the generation of JProfiling bodies
12539
// we will not go back
12540
if (getJProfilingCompQueue().getAllowProcessing())
12541
{
12542
return true;
12543
}
12544
else
12545
{
12546
// Prevent processing during JVM startup or JIT startp/rampup state
12547
if (_jitConfig->javaVM->phase != J9VM_PHASE_NOT_STARTUP ||
12548
getPersistentInfo()->getJitState() == STARTUP_STATE ||
12549
getPersistentInfo()->getJitState() == RAMPUP_STATE)
12550
return false;
12551
// A sufficiently large number of samples in jitted code must have been seen.
12552
// This means that the jitted code has run for a while
12553
if (TR::Recompilation::globalSampleCount < TR::Options::_jProfilingEnablementSampleThreshold)
12554
{
12555
return false;
12556
}
12557
getJProfilingCompQueue().setAllowProcessing();
12558
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerbosePerformance))
12559
{
12560
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Allowing generation of JProfiling bodies",
12561
(uint32_t)getPersistentInfo()->getElapsedTime());
12562
}
12563
return true;
12564
}
12565
}
12566
12567
bool
12568
TR::CompilationInfo::canRelocateMethod(TR::Compilation *comp)
12569
{
12570
// Delay relocation by default, unless this option is enabled
12571
if (!comp->getOption(TR_DisableDelayRelocationForAOTCompilations))
12572
return false;
12573
12574
#if defined(J9VM_OPT_JITSERVER)
12575
// Delay relocation if this is a deserialized AOT method using SVM received from the JITServer AOT cache.
12576
// Such methods cannot be immediately relocated in the current implementation. An immediate AOT+SVM load
12577
// uses the ID-symbol mapping created during compilation. This mapping is missing when the client receives
12578
// a serialized AOT method from the server, and trying to load the deserialized method immediately
12579
// triggers fatal assertions in SVM validation in certain cases. As a workaround, we delay the AOT load
12580
// until the next interpreted invocation of the method; see CompilationInfo::replenishInvocationCounter().
12581
//
12582
//TODO: Avoid the overhead of rescheduling this compilation request by handling the deserialized AOT load as if
12583
// the method came from the local SCC, rather than as if it was freshly AOT-compiled at the JITServer.
12584
if (comp->isDeserializedAOTMethodUsingSVM())
12585
return false;
12586
#endif /* defined(J9VM_OPT_JITSERVER) */
12587
12588
TR_Debug *debug = TR::Options::getDebug();
12589
TR_FilterBST *filter = NULL;
12590
return debug ? debug->methodSigCanBeRelocated(comp->signature(), filter) : true;
12591
}
12592
12593
#if defined(J9VM_OPT_JITSERVER)
12594
// This method is executed by the JITServer to queue a placeholder for
12595
// a compilation request received from the client. At the time the new
12596
// entry is queued we do not know any details about the compilation request.
12597
// The method needs to be executed with compilation monitor in hand.
12598
TR_MethodToBeCompiled *
12599
TR::CompilationInfo::addOutOfProcessMethodToBeCompiled(JITServer::ServerStream *stream)
12600
{
12601
TR_MethodToBeCompiled *entry = getCompilationQueueEntry(); // Allocate a new entry
12602
if (entry)
12603
{
12604
// Initialize the entry with defaults (some, like methodDetails, are bogus)
12605
TR::IlGeneratorMethodDetails details;
12606
entry->initialize(details, NULL, CP_SYNC_NORMAL, NULL);
12607
entry->_entryTime = getPersistentInfo()->getElapsedTime(); // Cheaper version
12608
entry->_stream = stream; // Add the stream to the entry
12609
incrementMethodQueueSize(); // One more method added to the queue
12610
_numQueuedFirstTimeCompilations++; // Otherwise an assert triggers when we dequeue
12611
queueEntry(entry);
12612
12613
// Determine whether we need to activate another compilation thread from the pool
12614
TR_YesNoMaybe activate = TR_maybe;
12615
if (getNumCompThreadsActive() <= 0)
12616
{
12617
activate = TR_yes;
12618
}
12619
else if (getNumCompThreadsJobless() > 0)
12620
{
12621
activate = TR_no; // Just wake the jobless one
12622
}
12623
else
12624
{
12625
int32_t numCompThreadsSuspended = getNumUsableCompilationThreads() - getNumCompThreadsActive();
12626
TR_ASSERT(numCompThreadsSuspended >= 0, "Accounting error for suspendedCompThreads usable=%d active=%d\n",
12627
getNumUsableCompilationThreads(), getNumCompThreadsActive());
12628
// Cannot activate if there is nothing to activate
12629
activate = (numCompThreadsSuspended <= 0) ? TR_no : TR_yes;
12630
}
12631
12632
if (activate == TR_yes)
12633
{
12634
// Must find one that is SUSPENDED/SUSPENDING
12635
TR::CompilationInfoPerThread *compInfoPT = getFirstSuspendedCompilationThread();
12636
if (compInfoPT)
12637
{
12638
compInfoPT->resumeCompilationThread();
12639
if (TR::Options::getCmdLineOptions()->getVerboseOption(TR_VerboseCompilationThreads))
12640
{
12641
TR_VerboseLog::writeLineLocked(TR_Vlog_INFO, "t=%6u Activate compThread %d Qweight=%d active=%d",
12642
(uint32_t)getPersistentInfo()->getElapsedTime(), compInfoPT->getCompThreadId(), getQueueWeight(), getNumCompThreadsActive());
12643
}
12644
}
12645
}
12646
}
12647
return entry;
12648
}
12649
12650
void
12651
TR::CompilationInfo::requeueOutOfProcessEntry(TR_MethodToBeCompiled *entry)
12652
{
12653
TR_ASSERT(getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER, "Should be called in JITServer server mode only");
12654
12655
recycleCompilationEntry(entry);
12656
12657
if (entry->_stream && addOutOfProcessMethodToBeCompiled(entry->_stream))
12658
{
12659
// successfully queued the new entry, so notify a thread
12660
getCompilationMonitor()->notifyAll();
12661
}
12662
}
12663
#endif /* defined(J9VM_OPT_JITSERVER) */
12664
12665