Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/openj9
Path: blob/master/runtime/compiler/control/J9Recompilation.cpp
6000 views
1
/*******************************************************************************
2
* Copyright (c) 2000, 2022 IBM Corp. and others
3
*
4
* This program and the accompanying materials are made available under
5
* the terms of the Eclipse Public License 2.0 which accompanies this
6
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
7
* or the Apache License, Version 2.0 which accompanies this distribution and
8
* is available at https://www.apache.org/licenses/LICENSE-2.0.
9
*
10
* This Source Code may also be made available under the following
11
* Secondary Licenses when the conditions for such availability set
12
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
13
* General Public License, version 2 with the GNU Classpath
14
* Exception [1] and GNU General Public License, version 2 with the
15
* OpenJDK Assembly Exception [2].
16
*
17
* [1] https://www.gnu.org/software/classpath/license.html
18
* [2] http://openjdk.java.net/legal/assembly-exception.html
19
*
20
* SPDX-License-Identifier: EPL-2.0 OR Apache-2.0 OR GPL-2.0 WITH Classpath-exception-2.0 OR LicenseRef-GPL-2.0 WITH Assembly-exception
21
*******************************************************************************/
22
23
#include "AtomicSupport.hpp"
24
#include "codegen/CodeGenerator.hpp"
25
#include "control/CompilationRuntime.hpp"
26
#include "control/Recompilation.hpp"
27
#include "control/RecompilationInfo.hpp"
28
#include "compile/Compilation.hpp"
29
#include "control/Options.hpp"
30
#include "compile/SymbolReferenceTable.hpp"
31
#include "env/VMJ9.h"
32
#include "env/VerboseLog.hpp"
33
#include "runtime/J9Profiler.hpp"
34
#include "exceptions/RuntimeFailure.hpp"
35
#if defined(J9VM_OPT_JITSERVER)
36
#include "control/JITServerCompilationThread.hpp"
37
#endif /* defined(J9VM_OPT_JITSERVER) */
38
39
bool J9::Recompilation::_countingSupported = false;
40
41
42
43
J9::Recompilation::Recompilation(TR::Compilation *comp) :
44
OMR::RecompilationConnector(comp),
45
_firstCompile(comp->getCurrentMethod()->isInterpreted()),
46
_useSampling(TR::Options::getSamplingFrequency() != 0 && !comp->getOption(TR_MimicInterpreterFrameShape)),
47
_doNotCompileAgain(comp->getOption(TR_NoRecompile) || !comp->allowRecompilation()),
48
_methodInfo(0),
49
_bodyInfo(0),
50
_nextLevel(warm),
51
_nextCounter(0)
52
{
53
_timer.initialize(0, comp->trMemory());
54
}
55
56
57
void
58
J9::Recompilation::setupMethodInfo()
59
{
60
// FIXME: this code should move into the constructor
61
// the problem is - if someone gets the bodyinfo/method info before
62
// this method is done - there will be a bug.
63
64
// NOTE: by the end of this method we must have determined whether or
65
// not this method is going to be recompiled using sampling or counting.
66
//
67
TR_OptimizationPlan * optimizationPlan = _compilation->getOptimizationPlan();
68
69
#if defined(J9VM_OPT_JITSERVER)
70
// NOTE: cannot use _compilation->isOutOfProcessCompilation here, because this
71
// method is called from within OMR::Compilation() constructor, before
72
// _isOutOfProcessCompilation is set
73
if (comp()->getPersistentInfo()->getRemoteCompilationMode() == JITServer::SERVER)
74
{
75
auto compInfoPT = static_cast<TR::CompilationInfoPerThreadRemote *>(TR::compInfoPT);
76
_methodInfo = compInfoPT->getRecompilationMethodInfo();
77
if (!_methodInfo)
78
{
79
_compilation->failCompilation<std::bad_alloc>("Unable to allocate method info");
80
}
81
}
82
else if (_firstCompile)
83
#else
84
if (_firstCompile)
85
#endif /* defined(J9VM_OPT_JITSERVER) */
86
{
87
// Create the persistent method information
88
// If the previous compiled version of the method is AOTed, then we need to create a new persistent method information
89
//
90
_methodInfo = new (PERSISTENT_NEW) TR_PersistentMethodInfo(_compilation);
91
92
if (!_methodInfo)
93
{
94
_compilation->failCompilation<std::bad_alloc>("Unable to allocate method info");
95
}
96
97
// During compilation methodInfo->nextOptLevel is the current optlevel
98
// ie. we pretend that the previous (nonexistent) compile has set this up
99
// for us. Mark this as a non-profiling compile. Only sampleMethod
100
// even enables profiling.
101
//
102
// During bootstrapping of TR::Options, _compilation->getMethodHotness
103
// will be setup properly from the count strings
104
//
105
_methodInfo->setNextCompileLevel(optimizationPlan->getOptLevel(),
106
(optimizationPlan->insertInstrumentation() != 0));
107
_methodInfo->setWasNeverInterpreted(!comp()->fej9()->methodMayHaveBeenInterpreted(comp()));
108
}
109
else // this is a recompilation
110
{
111
// There already is a persistent method info for this method which already
112
// has a compilation level set in it (by virtue of a previous compilation)
113
//
114
_methodInfo = getExistingMethodInfo(_compilation->getCurrentMethod());
115
#if defined(J9VM_OPT_JITSERVER)
116
if (comp()->getPersistentInfo()->getRemoteCompilationMode() == JITServer::CLIENT)
117
{
118
TR_ASSERT_FATAL(_methodInfo->profilingDisabled(), "Profiling is not supported in JITServer");
119
}
120
#endif /* defined(J9VM_OPT_JITSERVER) */
121
122
if (!comp()->fej9()->canRecompileMethodWithMatchingPersistentMethodInfo(comp()) &&
123
!comp()->isGPUCompilation())
124
{
125
// TODO: Why does this assume sometimes fail in HCR mode?
126
TR_ASSERT(_compilation->getMethodHotness() == _methodInfo->getNextCompileLevel(),
127
"discrepancy in the method compile level %d %d while compiling %s",
128
_compilation->getMethodHotness(),
129
_methodInfo->getNextCompileLevel(),
130
_compilation->signature());
131
}
132
}
133
134
// TR_Controller is being used and has provided a compilation plan. Use it to setup the compilation
135
//
136
_bodyInfo = TR_PersistentJittedBodyInfo::allocate(
137
_methodInfo,
138
_compilation->getMethodHotness(),
139
(optimizationPlan->insertInstrumentation() != 0),
140
_compilation);
141
142
if (!_bodyInfo)
143
{
144
_compilation->failCompilation<std::bad_alloc>("Unable to allocate body info");
145
}
146
147
if (!optimizationPlan->getUseSampling())
148
{
149
_bodyInfo->setDisableSampling(true);
150
}
151
152
if (_compilation->getOption(TR_EnableFastHotRecompilation) ||
153
_compilation->getOption(TR_EnableFastScorchingRecompilation))
154
{
155
// The body must be able to receive samples and recompilation should be enabled
156
//
157
if (!_bodyInfo->getDisableSampling() && !_doNotCompileAgain)
158
{
159
if (_compilation->getOption(TR_EnableFastHotRecompilation) && _bodyInfo->getHotness() < hot)
160
{
161
_bodyInfo->setFastHotRecompilation(true);
162
}
163
164
if (_compilation->getOption(TR_EnableFastScorchingRecompilation) && _bodyInfo->getHotness() < scorching)
165
{
166
_bodyInfo->setFastScorchingRecompilation(true);
167
}
168
}
169
}
170
}
171
172
173
int32_t
174
J9::Recompilation::getProfilingFrequency()
175
{
176
return self()->findOrCreateProfileInfo()->getProfilingFrequency();
177
}
178
179
180
int32_t
181
J9::Recompilation::getProfilingCount()
182
{
183
return self()->findOrCreateProfileInfo()->getProfilingCount();
184
}
185
186
/**
187
* Find or create profiling information for the current jitted
188
* body. If creating information, this will update the recent
189
* profile information on the current method info.
190
*/
191
TR_PersistentProfileInfo *
192
J9::Recompilation::findOrCreateProfileInfo()
193
{
194
// Determine whether this bodyInfo already has profiling information
195
TR_PersistentProfileInfo *profileInfo = _bodyInfo->getProfileInfo();
196
if (!profileInfo)
197
{
198
// Create a new profiling info
199
profileInfo = new (PERSISTENT_NEW) TR_PersistentProfileInfo(DEFAULT_PROFILING_FREQUENCY, DEFAULT_PROFILING_COUNT);
200
_methodInfo->setRecentProfileInfo(profileInfo);
201
_bodyInfo->setProfileInfo(profileInfo);
202
203
// If running with the profiling thread, add to its list
204
if (!TR::Options::getCmdLineOptions()->getOption(TR_DisableJProfilerThread))
205
{
206
TR::CompilationInfo::get(NULL)->getJProfilerThread()->addProfileInfo(profileInfo);
207
}
208
}
209
return profileInfo;
210
}
211
212
TR_PersistentProfileInfo *
213
J9::Recompilation::getProfileInfo()
214
{
215
return _bodyInfo->getProfileInfo();
216
}
217
218
void
219
J9::Recompilation::startOfCompilation()
220
{
221
if (!_firstCompile && _compilation->getOption(TR_FailRecompile))
222
{
223
_compilation->failCompilation<TR::CompilationException>("failRecompile");
224
}
225
226
if (!_compilation->fej9()->isAOT_DEPRECATED_DO_NOT_USE())
227
{
228
_timer.startTiming(_compilation);
229
}
230
}
231
232
233
void
234
J9::Recompilation::beforeOptimization()
235
{
236
// If the method is to be compiled with profiling info, force it to use
237
// counting and not sampling. Also make sure there is a persistent
238
// profile info block.
239
//
240
if (self()->isProfilingCompilation()) // this asks the bodyInfo
241
{
242
// JProfiling should not use either sampling or counting mechanism to trip recompilation.
243
// Even though _useSampling is set to true here, at the end of compilation we disable sampling
244
// causing us to rely only on the in-body recompilation test that relies on block frequency counter
245
// to trip recompilation making sure we have enough profiling data to use in recompilation.
246
_useSampling = _compilation->getProfilingMode() != JitProfiling;
247
self()->findOrCreateProfileInfo()->setProfilingCount (DEFAULT_PROFILING_COUNT);
248
self()->findOrCreateProfileInfo()->setProfilingFrequency (DEFAULT_PROFILING_FREQUENCY);
249
}
250
251
// Create profilers
252
//
253
if (self()->couldBeCompiledAgain())
254
{
255
if (_compilation->getProfilingMode() == JProfiling)
256
self()->createProfilers();
257
else if (!self()->useSampling())
258
{
259
if (_compilation->getMethodHotness() == cold)
260
{
261
_profilers.add(new (_compilation->trHeapMemory()) TR_LocalRecompilationCounters(_compilation, self()));
262
}
263
else if (self()->isProfilingCompilation())
264
{
265
self()->createProfilers();
266
}
267
else if (!_compilation->getOption(TR_FullSpeedDebug))
268
{
269
_profilers.add(new (_compilation->trHeapMemory()) TR_GlobalRecompilationCounters(_compilation, self()));
270
}
271
}
272
else
273
{
274
if (!debug("disableCatchBlockProfiler"))
275
{
276
_profilers.add(new (_compilation->trHeapMemory()) TR_CatchBlockProfiler(_compilation, self(), true));
277
}
278
}
279
}
280
}
281
282
283
void
284
J9::Recompilation::beforeCodeGen()
285
{
286
// Set up the opt level and counter for the next compilation. This will
287
// also decide if there is going to be a next compilation.
288
TR::CompilationController::getCompilationStrategy()->beforeCodeGen(_compilation->getOptimizationPlan(), self());
289
}
290
291
292
void
293
J9::Recompilation::endOfCompilation()
294
{
295
// Perform any platform-dependant tasks if needed
296
//
297
self()->postCompilation();
298
299
// We will free the optimizationPlan at the end of compilation,
300
// do we need to clear the corresponding field in
301
//
302
TR::CompilationController::getCompilationStrategy()->postCompilation(_compilation->getOptimizationPlan(), self());
303
304
if (self()->couldBeCompiledAgain())
305
{
306
_bodyInfo->setCounter(_nextCounter);
307
308
// set the start counter to the current timestamp
309
//
310
_bodyInfo->setStartCount(globalSampleCount);
311
_bodyInfo->setOldStartCountDelta(TR::Options::_sampleThreshold);
312
_bodyInfo->setHotStartCountDelta(0);
313
_bodyInfo->setSampleIntervalCount(0);
314
315
// if the only possible next compilation of this method is
316
// unnatural, _nextLevel will not be set, recompile at the
317
// current level
318
//
319
if (!self()->shouldBeCompiledAgain())
320
{
321
_nextLevel = _compilation->getMethodHotness();
322
}
323
324
_methodInfo->setNextCompileLevel(_nextLevel, false); // profiling can only be triggered from sampleMethod
325
326
_bodyInfo->setHasLoops (_compilation->mayHaveLoops());
327
_bodyInfo->setUsesPreexistence(_compilation->usesPreexistence());
328
329
// if the only future compilation can be a forced one (preexistence)
330
// do not sample this method. If this is a counting based compilation
331
// disable sampling as well
332
//
333
if (!self()->shouldBeCompiledAgain() || !_useSampling || _compilation->getProfilingMode() == JProfiling)
334
{
335
_bodyInfo->setDisableSampling(true);
336
}
337
}
338
339
// If we disallow recompilation then disable sampling
340
if (!_compilation->allowRecompilation())
341
_bodyInfo->setDisableSampling(true);
342
}
343
344
345
/**
346
* @brief
347
* Switches the current compilation to a profiling mode in which profiling group optimizations will
348
* run and potentially insert profiling trees into the compiled body.
349
*
350
* @param f
351
* The profiling frequency for the persistent profiling info to use.
352
* @param c
353
* The profiling count for the persistent profiling info to use.
354
*
355
* @return
356
* True if the compilation was successfully switched to a profiling compilation; false otherwise.
357
*/
358
bool
359
J9::Recompilation::switchToProfiling(uint32_t f, uint32_t c)
360
{
361
if (_compilation->fej9()->isAOT_DEPRECATED_DO_NOT_USE())
362
{
363
return false;
364
}
365
366
if (!_methodInfo)
367
{
368
return false;
369
}
370
371
if (_methodInfo->profilingDisabled())
372
{
373
return false;
374
}
375
376
if (!self()->countingSupported())
377
{
378
return false;
379
}
380
381
if (self()->isProfilingCompilation())
382
{
383
return true;
384
}
385
386
if (!TR::CompilationController::getCompilationStrategy()->enableSwitchToProfiling())
387
{
388
return false;
389
}
390
391
if (comp()->getOptimizationPlan()->getDoNotSwitchToProfiling())
392
{
393
return false;
394
}
395
396
if (_compilation->isOptServer() && !_compilation->getOption(TR_AggressiveSwitchingToProfiling))
397
{
398
return false;
399
}
400
401
if (!_bodyInfo->getIsProfilingBody())
402
{
403
if (!performTransformation(comp(), "\nSwitching the compile to do profiling (isProfilingCompile=1)\n"))
404
return false;
405
}
406
407
_bodyInfo->setIsProfilingBody(true);
408
409
// If profiling will use JProfiling instrumentation and this is post JProfilingBlock opt pass, trigger restart
410
if (_compilation->getProfilingMode() == JProfiling && _compilation->getSkippedJProfilingBlock())
411
{
412
TR::DebugCounter::incStaticDebugCounter(_compilation, TR::DebugCounter::debugCounterName(_compilation,
413
"jprofiling.restartCompile/(%s)", _compilation->signature()));
414
if (TR::Options::getVerboseOption(TR_VerboseProfiling))
415
TR_VerboseLog::writeLineLocked(TR_Vlog_PROFILING, "Restarting compilation due to late switch to profiling");
416
comp()->failCompilation<J9::EnforceProfiling>("Enforcing profiling compilation");
417
}
418
419
_useSampling = _compilation->getProfilingMode() != JitProfiling;
420
self()->findOrCreateProfileInfo()->setProfilingFrequency(f);
421
self()->findOrCreateProfileInfo()->setProfilingCount(c);
422
self()->createProfilers();
423
return true;
424
}
425
426
427
bool
428
J9::Recompilation::switchToProfiling()
429
{
430
return self()->switchToProfiling(DEFAULT_PROFILING_FREQUENCY, DEFAULT_PROFILING_COUNT);
431
}
432
433
434
void
435
J9::Recompilation::switchAwayFromProfiling()
436
{
437
_bodyInfo->setIsProfilingBody(false);
438
_useSampling = true;
439
}
440
441
442
void
443
J9::Recompilation::createProfilers()
444
{
445
if (!self()->getValueProfiler())
446
_profilers.add(new (_compilation->trHeapMemory()) TR_ValueProfiler(_compilation, self(),
447
_compilation->getProfilingMode() == JProfiling ? HashTableProfiler : LinkedListProfiler ));
448
449
if (!self()->getBlockFrequencyProfiler() && _compilation->getProfilingMode() != JProfiling)
450
_profilers.add(new (_compilation->trHeapMemory()) TR_BlockFrequencyProfiler(_compilation, self()));
451
}
452
453
454
bool
455
J9::Recompilation::couldBeCompiledAgain()
456
{
457
return
458
self()->shouldBeCompiledAgain() ||
459
_compilation->usesPreexistence() ||
460
_compilation->getOption(TR_EnableHCR);
461
}
462
463
464
bool
465
J9::Recompilation::shouldBeCompiledAgain()
466
{
467
return TR::Options::canJITCompile() && !_doNotCompileAgain;
468
}
469
470
471
void
472
J9::Recompilation::preventRecompilation()
473
{
474
_nextCounter = 0;
475
_doNotCompileAgain = true;
476
477
for (TR_RecompilationProfiler * rp = getFirstProfiler(); rp; rp = rp->getNext())
478
{
479
if (rp->getHasModifiedTrees())
480
{
481
rp->removeTrees();
482
rp->setHasModifiedTrees(false);
483
}
484
}
485
}
486
487
488
TR_PersistentMethodInfo *
489
J9::Recompilation::getExistingMethodInfo(TR_ResolvedMethod *method)
490
{
491
// Default (null) implementation
492
//
493
TR_ASSERT(0, "This method needs to be implemented");
494
return 0;
495
}
496
497
/**
498
* This method can extract a value profiler from the current list of
499
* recompilation profilers.
500
*
501
* \return The first TR_ValueProfiler in the current list of profilers, NULL if there are none.
502
*/
503
TR_ValueProfiler *
504
J9::Recompilation::getValueProfiler()
505
{
506
for (TR_RecompilationProfiler * rp = getFirstProfiler(); rp; rp = rp->getNext())
507
{
508
TR_ValueProfiler *vp = rp->asValueProfiler();
509
if (vp)
510
return vp;
511
}
512
513
return NULL;
514
}
515
516
/**
517
* This method can extract a block profiler from the current list of
518
* recompilation profilers.
519
*
520
* \return The first TR_BlockFrequencyProfiler in the current list of profilers, NULL if there are none.
521
*/
522
TR_BlockFrequencyProfiler *
523
J9::Recompilation::getBlockFrequencyProfiler()
524
{
525
for (TR_RecompilationProfiler * rp = getFirstProfiler(); rp; rp = rp->getNext())
526
{
527
TR_BlockFrequencyProfiler *vp = rp->asBlockFrequencyProfiler();
528
if (vp)
529
return vp;
530
}
531
532
return NULL;
533
}
534
535
/**
536
* This method can remove a specified recompilation profiler from the
537
* current list. Useful when modifying the profiling strategy.
538
*
539
* \param rp The recompilation profiler to remove.
540
*/
541
void
542
J9::Recompilation::removeProfiler(TR_RecompilationProfiler *rp)
543
{
544
_profilers.remove(rp);
545
}
546
547
TR_Hotness
548
J9::Recompilation::getNextCompileLevel(void *oldStartPC)
549
{
550
TR_PersistentMethodInfo *methodInfo = TR::Recompilation::getMethodInfoFromPC(oldStartPC);
551
return methodInfo->getNextCompileLevel();
552
}
553
554
555
TR::SymbolReference *
556
J9::Recompilation::getCounterSymRef()
557
{
558
return _compilation->getSymRefTab()->findOrCreateRecompilationCounterSymbolRef(_bodyInfo->getCounterAddress());
559
}
560
561
562
/////////////////////////
563
// DEBUG
564
//////////////////////////
565
566
void
567
J9::Recompilation::shutdown()
568
{
569
static bool TR_RecompilationStats = feGetEnv("TR_RecompilationStats")?1:0;
570
if (TR_RecompilationStats)
571
{
572
TR_VerboseLog::writeLine(TR_Vlog_INFO,"Methods recompiled via count = %d", limitMethodsCompiled);
573
TR_VerboseLog::writeLine(TR_Vlog_INFO,"Methods recompiled via hot threshold = %d", hotThresholdMethodsCompiled);
574
TR_VerboseLog::writeLine(TR_Vlog_INFO,"Methods recompiled via scorching threshold = %d", scorchingThresholdMethodsCompiled);
575
}
576
}
577
578
579
580
581
TR_PersistentMethodInfo::TR_PersistentMethodInfo(TR::Compilation *comp) :
582
_methodInfo((TR_OpaqueMethodBlock *)comp->getCurrentMethod()->resolvedMethodAddress()),
583
_flags(0),
584
_nextHotness(unknownHotness),
585
_recentProfileInfo(0),
586
_bestProfileInfo(0),
587
_optimizationPlan(0),
588
_numberOfInvalidations(0),
589
_numberOfInlinedMethodRedefinition(0),
590
_numPrexAssumptions(0)
591
{
592
if (comp->getOption(TR_EnableHCR) && !comp->fej9()->isAOT_DEPRECATED_DO_NOT_USE())
593
{
594
// If the method gets replaced, we'll want _methodInfo to get updated
595
//
596
comp->cg()->jitAddPicToPatchOnClassRedefinition((void*)_methodInfo, (void*)&_methodInfo, false);
597
}
598
599
if (comp->getOption(TR_DisableProfiling) || comp->fej9()->isAOT_DEPRECATED_DO_NOT_USE())
600
{
601
setDisableProfiling();
602
}
603
604
// Start cpoSampleCounter at 1. Because the method sample count
605
// is stored in the compiled method info, we can't start counting
606
// until already compiled once, thus we missed the first sample.
607
// (not particularly clean solution. Should really attach the
608
// counter to the method, not the compiled-method)
609
//
610
_cpoSampleCounter = 1;
611
612
uint64_t tempTimeStamp = comp->getPersistentInfo()->getElapsedTime();
613
if (tempTimeStamp < (uint64_t)0x0FFFF)
614
_timeStamp = (uint16_t)tempTimeStamp;
615
else
616
_timeStamp = (uint16_t)0xFFFF;
617
}
618
619
TR_PersistentMethodInfo::TR_PersistentMethodInfo(TR_OpaqueMethodBlock *methodInfo) :
620
_methodInfo(methodInfo),
621
_flags(0),
622
_nextHotness(unknownHotness),
623
_recentProfileInfo(0),
624
_bestProfileInfo(0),
625
_optimizationPlan(0),
626
_numberOfInvalidations(0),
627
_numberOfInlinedMethodRedefinition(0),
628
_numPrexAssumptions(0)
629
{
630
}
631
632
TR_PersistentMethodInfo *
633
TR_PersistentMethodInfo::get(TR::Compilation *comp)
634
{
635
TR::Recompilation * recomp = comp->getRecompilationInfo();
636
return recomp ? recomp->getMethodInfo() : 0;
637
}
638
639
TR_PersistentMethodInfo *
640
TR_PersistentMethodInfo::get(TR_ResolvedMethod * feMethod)
641
{
642
if (feMethod->isInterpreted() || feMethod->isJITInternalNative())
643
return 0;
644
645
TR_PersistentJittedBodyInfo *bodyInfo = ((TR_ResolvedJ9Method*) feMethod)->getExistingJittedBodyInfo();
646
return bodyInfo ? bodyInfo->getMethodInfo() : 0;
647
}
648
649
TR_PersistentJittedBodyInfo::TR_PersistentJittedBodyInfo(
650
TR_PersistentMethodInfo *methodInfo,
651
TR_Hotness hotness,
652
bool profile,
653
TR::Compilation *comp) :
654
_methodInfo(methodInfo),
655
_counter(INT_MAX),
656
_mapTable(comp == 0 || comp->getOption(TR_DoNotUseFastStackwalk) ? 0 : (void *)-1),
657
_hotness(hotness),
658
_flags(0),
659
_sampleIntervalCount(0),
660
_startCount(0),
661
_isInvalidated(false),
662
_aggressiveRecompilationChances((uint8_t)TR::Options::_aggressiveRecompilationChances),
663
_startPCAfterPreviousCompile(0),
664
_longRunningInterpreted(false),
665
_numScorchingIntervals(0),
666
_profileInfo(0)
667
,_hwpInstructionStartCount(0),
668
_hwpInstructionCount(0),
669
_hwpInducedRecompilation(false),
670
_hwpReducedWarmCompileRequested(false),
671
_hwpReducedWarmCompileInQueue(false)
672
{
673
setIsProfilingBody(profile);
674
}
675
676
TR_PersistentJittedBodyInfo *
677
TR_PersistentJittedBodyInfo::allocate(
678
TR_PersistentMethodInfo *methodInfo,
679
TR_Hotness hotness,
680
bool profile,
681
TR::Compilation *comp)
682
{
683
return new (PERSISTENT_NEW) TR_PersistentJittedBodyInfo(methodInfo, hotness, profile, comp);
684
}
685
686
/**
687
* Increment reference count for shared profile info.
688
*
689
* This function and setForSharedInfo use the pointer's low bit as a lock,
690
* preventing other accesses to the persistent information through this pointer.
691
* This is necessary as the process of incrementing the reference count isn't
692
* atomic with the pointer updates.
693
*
694
* When locked, its able to safely dereference the pointer and increment
695
* its reference count. Without the lock, the information could have been
696
* deallocated in the interim.
697
*
698
* \param ptr Pointer shared across several threads.
699
*/
700
TR_PersistentProfileInfo *
701
TR_PersistentMethodInfo::getForSharedInfo(TR_PersistentProfileInfo** ptr)
702
{
703
uintptr_t locked;
704
uintptr_t unlocked;
705
706
// Lock the ptr
707
do {
708
locked = ((uintptr_t) *ptr) | (1ULL);
709
unlocked = ((uintptr_t) *ptr) & ~(1ULL);
710
if (unlocked == 0)
711
return NULL;
712
}
713
while (unlocked != VM_AtomicSupport::lockCompareExchange((uintptr_t*)ptr, unlocked, locked));
714
715
// Inc ref count
716
TR_PersistentProfileInfo::incRefCount((TR_PersistentProfileInfo*)unlocked);
717
718
// Unlock the ptr
719
// Assumes no updates to the ptr whilst locked
720
VM_AtomicSupport::set((uintptr_t*)ptr, unlocked);
721
722
return *ptr;
723
}
724
725
/**
726
* Update a shared pointer to reference a new persistent profile info.
727
*
728
* This should be used with getForSharedInfo, to ensure a shared persistent profile info is
729
* updated correctly.
730
*
731
* \param ptr Pointer shared across several threads.
732
* \param newInfo New persistent profile info to use. Should have a non-zero reference count in caller.
733
*/
734
void
735
TR_PersistentMethodInfo::setForSharedInfo(TR_PersistentProfileInfo** ptr, TR_PersistentProfileInfo *newInfo)
736
{
737
uintptr_t oldPtr;
738
739
// Before it can be accessed, inc ref count on new info
740
if (newInfo)
741
TR_PersistentProfileInfo::incRefCount(newInfo);
742
743
// Update ptr as if it was unlocked
744
// Doesn't matter what the old info was, as long as it was unlocked
745
do {
746
oldPtr = ((uintptr_t) *ptr) & ~(1ULL);
747
}
748
while (oldPtr != VM_AtomicSupport::lockCompareExchange((uintptr_t*)ptr, oldPtr, (uintptr_t)newInfo));
749
750
// Now that it can no longer be accessed, dec ref count on old info
751
if (oldPtr)
752
TR_PersistentProfileInfo::decRefCount((TR_PersistentProfileInfo*)oldPtr);
753
}
754
755
#if defined(J9VM_OPT_JITSERVER)
756
TR_PersistentJittedBodyInfo *
757
J9::Recompilation::persistentJittedBodyInfoFromString(const std::string &bodyInfoStr, const std::string &methodInfoStr, TR_Memory *trMemory)
758
{
759
if (bodyInfoStr.empty())
760
return NULL;
761
TR_ASSERT_FATAL(!methodInfoStr.empty(), "If we have a persistentBodyInfo we must have a persistentMethodInfo too");
762
auto bodyInfo = (TR_PersistentJittedBodyInfo*) trMemory->allocateHeapMemory(sizeof(TR_PersistentJittedBodyInfo), TR_MemoryBase::Recompilation);
763
auto methodInfo = (TR_PersistentMethodInfo*) trMemory->allocateHeapMemory(sizeof(TR_PersistentMethodInfo), TR_MemoryBase::Recompilation);
764
765
memcpy(bodyInfo, &bodyInfoStr[0], sizeof(TR_PersistentJittedBodyInfo));
766
memcpy(methodInfo, &methodInfoStr[0], sizeof(TR_PersistentMethodInfo));
767
768
bodyInfo->setMethodInfo(methodInfo);
769
bodyInfo->setProfileInfo(NULL);
770
bodyInfo->setMapTable(NULL);
771
resetPersistentProfileInfo(methodInfo);
772
return bodyInfo;
773
}
774
775
void
776
J9::Recompilation::resetPersistentProfileInfo(TR_PersistentMethodInfo *methodInfo)
777
{
778
methodInfo->setOptimizationPlan(NULL);
779
// Cannot use setter because it calls the destructor on the old profile data,
780
// which is a client pointer
781
methodInfo->_recentProfileInfo = NULL;
782
methodInfo->_bestProfileInfo = NULL;
783
}
784
#endif /* defined(J9VM_OPT_JITSERVER) */
785
786