-
Notifications
You must be signed in to change notification settings - Fork 746
/
Copy pathCompilationRuntime.hpp
1478 lines (1331 loc) · 70.4 KB
/
CompilationRuntime.hpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
/*******************************************************************************
* Copyright (c) 2000, 2022 IBM Corp. and others
*
* This program and the accompanying materials are made available under
* the terms of the Eclipse Public License 2.0 which accompanies this
* distribution and is available at https://www.eclipse.org/legal/epl-2.0/
* or the Apache License, Version 2.0 which accompanies this distribution and
* is available at https://www.apache.org/licenses/LICENSE-2.0.
*
* This Source Code may also be made available under the following
* Secondary Licenses when the conditions for such availability set
* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU
* General Public License, version 2 with the GNU Classpath
* Exception [1] and GNU General Public License, version 2 with the
* OpenJDK Assembly Exception [2].
*
* [1] https://www.gnu.org/software/classpath/license.html
* [2] http://openjdk.java.net/legal/assembly-exception.html
*
* 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
*******************************************************************************/
#ifndef COMPILATION_RUNTIME_HPP
#define COMPILATION_RUNTIME_HPP
#pragma once
#include "AtomicSupport.hpp"
#include "compile/CompilationTypes.hpp"
#include "control/CompilationPriority.hpp"
#include "control/ClassHolder.hpp"
#include "control/MethodToBeCompiled.hpp"
#include "env/CpuUtilization.hpp"
#include "env/Processors.hpp"
#include "env/ProcessorInfo.hpp"
#include "env/TRMemory.hpp"
#include "env/jittypes.h"
#include "infra/Flags.hpp"
#include "infra/Statistics.hpp"
#include "control/rossa.h"
#include "runtime/RelocationRuntime.hpp"
#if defined(J9VM_OPT_JITSERVER)
#include "control/JITServerHelpers.hpp"
#include "env/PersistentCollections.hpp"
#include "net/ServerStream.hpp"
#endif /* defined(J9VM_OPT_JITSERVER) */
extern "C" {
struct J9Method;
struct J9JITConfig;
struct J9VMThread;
struct J9ROMMethod;
struct J9ClassLoader;
struct J9SharedClassJavacoreDataDescriptor;
}
class CpuUtilization;
namespace TR { class CompilationInfoPerThread; }
namespace TR { class CompilationInfoPerThreadBase; }
class TR_FilterBST;
class TR_FrontEnd;
class TR_HWProfiler;
class TR_J9VMBase;
class TR_LowPriorityCompQueue;
class TR_OptimizationPlan;
class TR_PersistentMethodInfo;
class TR_RelocationRuntime;
class TR_ResolvedMethod;
namespace TR { class MonitorTable; }
namespace TR { class IlGeneratorMethodDetails; }
namespace TR { class Options; }
namespace J9 { class RWMonitor; }
struct TR_JitPrivateConfig;
struct TR_MethodToBeCompiled;
template <typename T> class TR_PersistentArray;
typedef J9JITExceptionTable TR_MethodMetaData;
#if defined(J9VM_OPT_JITSERVER)
class ClientSessionHT;
class JITServerAOTCacheMap;
class JITServerAOTDeserializer;
class JITServerSharedROMClassCache;
#endif /* defined(J9VM_OPT_JITSERVER) */
struct TR_SignatureCountPair
{
TR_PERSISTENT_ALLOC(TR_Memory::OptimizationPlan)
TR_SignatureCountPair(char *string, int32_t c)
{
count = c;
for(int32_t i=0 ; i < 4000 ; i++)
{
signature[i] = string[i];
if(string[i] == '\0')
break;
}
};
char signature[4000];
int32_t count;
};
class TR_LowPriorityCompQueue
{
public:
TR_PERSISTENT_ALLOC(TR_Memory::PersistentInfo); // TODO: define its own category
static const uint32_t HT_SIZE = (1 << 13); // power of two for cheap modulo
TR_LowPriorityCompQueue();
~TR_LowPriorityCompQueue();
void setCompInfo(TR::CompilationInfo *compInfo) { _compInfo = compInfo; }
bool hasLowPriorityRequest() const { return (_firstLPQentry != NULL); }
TR_MethodToBeCompiled *getFirstLPQRequest() const { return _firstLPQentry; }
TR_MethodToBeCompiled *extractFirstLPQRequest();
TR_MethodToBeCompiled *findAndDequeueFromLPQ(TR::IlGeneratorMethodDetails &details,
uint8_t reason, TR_J9VMBase *fe, bool & dequeued);
void enqueueCompReqToLPQ(TR_MethodToBeCompiled *compReq);
bool createLowPriorityCompReqAndQueueIt(TR::IlGeneratorMethodDetails &details, void *startPC, uint8_t reason);
bool addFirstTimeCompReqToLPQ(J9Method *j9method, uint8_t reason);
bool addUpgradeReqToLPQ(TR_MethodToBeCompiled*, uint8_t reason = TR_MethodToBeCompiled::REASON_UPGRADE);
int32_t getLowPriorityQueueSize() const { return _sizeLPQ; }
int32_t getLPQWeight() const { return _LPQWeight; }
void increaseLPQWeightBy(uint8_t weight) { _LPQWeight += (int32_t)weight; }
void decreaseLPQWeightBy(uint8_t weight) { _LPQWeight -= (int32_t)weight; }
void invalidateRequestsForUnloadedMethods(J9Class * unloadedClass);
void purgeLPQ();
// The following refer to the mechanism that schedules low priority
// compilation requests based on the Iprofiler
static uint32_t hash(J9Method *j9method) { return ((uintptr_t)j9method >> 3) & (HT_SIZE - 1); }
bool isTrackingEnabled() const { return _trackingEnabled; }
void startTrackingIProfiledCalls(int32_t threshold);
bool isTrackableMethod(J9Method *j9method) const;
void stopTrackingMethod(J9Method *j9method); // Executed by the compilation thread when a low pri req is processed
void tryToScheduleCompilation(J9VMThread *vmThread, J9Method *j9method); // Executed by the IProfiler thread
void purgeEntriesOnClassLoaderUnloading(J9ClassLoader *j9classLoader);
void purgeEntriesOnClassRedefinition(J9Class *j9class);
void printStats() const;
void incStatsBypass() { _STAT_bypass++; } // Done by comp threads
void incStatsCompFromLPQ(uint8_t reason); // Done by JIT
void incStatsReqQueuedToLPQ(uint8_t reason);
void incNumFailuresToEnqueue() { _STAT_numFailedToEnqueueInLPQ++; }
struct Entry
{
uintptr_t _j9method; // this is the key; Initialized by IProfiler thread; reset by compilation thread
uint32_t _count; // updated by IProfiler thread
bool _queuedForCompilation; // used to avoid duplicates in the queue; set by IProfiler thread
bool isInvalid() const { return !_j9method; }
void setInvalid() { _j9method = 0; }
void initialize(J9Method *m, uint32_t c) { _j9method = (uintptr_t)m; _count = c; _queuedForCompilation = false; }
};
private:
TR::CompilationInfo* _compInfo;
TR_MethodToBeCompiled* _firstLPQentry; // first entry of low priority queue
TR_MethodToBeCompiled* _lastLPQentry; // last entry of low priority queue
int32_t _sizeLPQ; // size of low priority queue
int32_t _LPQWeight; // weight of low priority queue
uint32_t _threshold;
bool _trackingEnabled;
// Direct mapped hashtable that records j9methods and "counts"
Entry *_spine; // my hashtable
// stats written by IProfiler thread
uint32_t _STAT_compReqQueuedByIProfiler;
uint32_t _STAT_conflict;
uint32_t _STAT_staleScrubbed;
// stats written by comp thread
uint32_t _STAT_bypass; // an LPQ compilation was overtaken by a normal compilation
uint32_t _STAT_compReqQueuedByJIT;
uint32_t _STAT_LPQcompFromIprofiler; // first time compilations coming from LPQ
uint32_t _STAT_LPQcompFromInterpreter;
uint32_t _STAT_LPQcompUpgrade;
// stats written by application threads
uint32_t _STAT_compReqQueuedByInterpreter;
uint32_t _STAT_numFailedToEnqueueInLPQ;
}; // TR_LowPriorityCompQueue
// Definition of compilation queue to hold JProfiling candidates
class TR_JProfilingQueue
{
public:
TR_PERSISTENT_ALLOC(TR_Memory::PersistentInfo); // TODO: define its own category
TR_JProfilingQueue() : _firstQentry(NULL), _lastQentry(NULL), _size(0), _weight(0), _allowProcessing(false) {};
void setCompInfo(TR::CompilationInfo *compInfo) { _compInfo = compInfo; }
bool isEmpty() const { return (_firstQentry == NULL); }
TR_MethodToBeCompiled *getFirstCompRequest() const { return _firstQentry; }
TR_MethodToBeCompiled *extractFirstCompRequest();
bool createCompReqAndQueueIt(TR::IlGeneratorMethodDetails &details, void *startPC);
int32_t getQSize() const { return _size; }
int32_t getQWeight() const { return _weight; }
bool getAllowProcessing() const { return _allowProcessing; }
void setAllowProcessing() { _allowProcessing = true; }
static bool isJProfilingCandidate(TR_MethodToBeCompiled *entry, TR::Options *options, TR_J9VMBase* fej9);
void invalidateRequestsForUnloadedMethods(J9Class * unloadedClass);
void purge();
private:
void increaseQWeightBy(uint8_t weight) { _weight += (int32_t)weight; }
void decreaseQWeightBy(uint8_t weight) { _weight -= (int32_t)weight; }
void enqueueCompReq(TR_MethodToBeCompiled *compReq);
TR::CompilationInfo* _compInfo;
TR_MethodToBeCompiled* _firstQentry; // first entry of JProfiling queue
TR_MethodToBeCompiled* _lastQentry; // last entry of JProfiling queue
int32_t _size; // size of JProfiling queue
int32_t _weight; // weight of JProfiling queue
bool _allowProcessing;
};
// Supporting class for getting information on density of samples
class TR_JitSampleInfo
{
public:
void init()
{
_maxSamplesPerSecond = 0;
_samplesPerSecondDuringLastInterval = 0;
_sizeOfLastInterval = 1; // avoid check for divide by 0
_globalSampleCounterInLastInterval = 0;
_timestampOfLastInterval = 0;
_increaseFactor = 1;
}
TR_JitSampleInfo() { init(); }
uint32_t getMaxSamplesPerSecond() const { return _maxSamplesPerSecond; }
uint32_t getSamplesPerSecondDuringLastInterval() const { return _samplesPerSecondDuringLastInterval; }
uint32_t getCurrentSamplesPerSecond(uint64_t crtTime, uint32_t crtGlobalSampleCounter) const
{
uint64_t diffTime = crtTime - _timestampOfLastInterval;
return diffTime > 0 ? (crtGlobalSampleCounter - _globalSampleCounterInLastInterval) * 1000 / diffTime : 0;
}
void update(uint64_t crtTime, uint32_t crtGlobalSampleCounter);
uint32_t getIncreaseFactor() const { return _increaseFactor; }
private:
uint32_t _maxSamplesPerSecond;
uint32_t _samplesPerSecondDuringLastInterval;
uint32_t _sizeOfLastInterval; // ms
uint32_t _globalSampleCounterInLastInterval;
uint64_t _timestampOfLastInterval;
uint32_t _increaseFactor;
}; // class TR_JitSampleInfo
// The following class is used for tracking methods that have their invocation
// count decremented due to a sample in interpreted code. When that happens
// we add the method to a list. When a method needs to be compiled we check
// the list and if the method is in the list we delete it and schedule a
// SamplingJprofiling compilation for the count that has been skipped
class TR_InterpreterSamplingTracking
{
public:
TR_PERSISTENT_ALLOC(TR_MemoryBase::CompilationInfo);
class TR_MethodCnt
{
friend class TR_InterpreterSamplingTracking;
TR_MethodCnt(J9Method *m, int32_t c) : _next(NULL), _method(m), _skippedCount(c) {}
TR_MethodCnt *_next;
J9Method * _method;
int32_t _skippedCount;
};
TR_InterpreterSamplingTracking(TR::CompilationInfo *compInfo) :
_container(NULL), _compInfo(compInfo), _maxElements(0), _size(0) {}
// both these methods need the compilation monitor in hand
void addOrUpdate(J9Method *method, int32_t cnt);
int32_t findAndDelete(J9Method *method);
void onClassUnloading() {/* TODO: prune list when classes change or get unloaded */}
uint32_t getMaxElements() const { return _maxElements; }
private:
TR_MethodCnt *_container;
TR::CompilationInfo *_compInfo; // cache value of compInfo
uint32_t _maxElements;
uint32_t _size;
};
class J9Method_HT
{
public:
TR_PERSISTENT_ALLOC(TR_MemoryBase::CompilationInfo);
static const size_t LOG_HT_SIZE = 6;
static const size_t HT_SIZE = 1 << LOG_HT_SIZE;
static const size_t MASK = HT_SIZE - 1;
struct HT_Entry
{
HT_Entry *_next; // for linking entries together
J9Method *_j9method;
volatile int32_t _count; // invocation count when last visited
uint32_t _seqID;
uint64_t _timestamp;
HT_Entry(J9Method *j9method, uint64_t timestamp);
uint64_t getTimestamp() const { return _timestamp; }
};
J9Method_HT(TR::PersistentInfo *persistentInfo);
size_t getNumEntries() const { return _numEntries; }
// method used by various hooks that perform class unloading
void onClassUnloading();
protected:
TR::PersistentInfo *getPersistentInfo() const { return _persistentInfo; }
size_t hash(J9Method *j9method) const
{ return (size_t)(((uintptr_t)j9method >> 3) ^ ((uintptr_t)j9method >> (3 + LOG_HT_SIZE))); }
HT_Entry *find(J9Method *j9method) const;
bool addNewEntry(J9Method *j9method, uint64_t timestamp);
private:
// Backbone of the hashtable
struct HT_Entry *_spine[HT_SIZE];
TR::PersistentInfo *_persistentInfo;
int32_t _numEntries; // for stats; may be imprecise due to multithreading issues
};
class DLTTracking : public J9Method_HT
{
public:
DLTTracking(TR::PersistentInfo *persistentInfo) : J9Method_HT(persistentInfo) {}
// Method used by application threads when a DLT decision needs to be taken
// Need to have VMaccess in hand
bool shouldIssueDLTCompilation(J9Method *j9method, int32_t numHitsInDLTBuffer);
// Method used by application threads whenever invocation count
// for a method is changed abruptly (e.g. interpreter sampling)
// Need to have VMaccess in hand
void adjustStoredCounterForMethod(J9Method *j9method, int32_t countDiff);
};
//--------------------------------- TR::CompilationInfo -----------------------
namespace TR
{
class CompilationInfo
{
public:
friend class TR::CompilationInfoPerThreadBase;
friend class TR::CompilationInfoPerThread;
friend class ::TR_LowPriorityCompQueue;
friend class ::TR_JProfilingQueue;
TR_PERSISTENT_ALLOC(TR_MemoryBase::CompilationInfo);
enum hotnessWeights
{
AOT_LOAD_WEIGHT = 1, // actually AOT loads have their own parameter
THUNKS_WEIGHT = 1,
NOOPT_WEIGHT = 1,
COLD_WEIGHT = 2,
WARM_LOOPLESS_WEIGHT = 6,
WARM_LOOPY_WEIGHT = 12,
JSR292_WEIGHT = 20,
HOT_WEIGHT = 30,
VERY_HOT_WEIGHT = 100,
MAX_WEIGHT = 255
};
enum TR_SamplerStates
{
SAMPLER_NOT_INITIALIZED = 0,
SAMPLER_DEFAULT,
SAMPLER_IDLE,
SAMPLER_DEEPIDLE,
SAMPLER_SUSPENDED,
SAMPLER_STOPPED,
SAMPLER_LAST_STATE, // must be the last one
// If adding new state, one must add a new name as well in samplerThreadStateNames array
// and a frequency in samplerThreadStateFrequencies array
};
enum TR_SamplingThreadLifetimeStates
{
SAMPLE_THR_NOT_CREATED = 0,
SAMPLE_THR_FAILED_TO_ATTACH,
SAMPLE_THR_ATTACHED,
SAMPLE_THR_INITIALIZED,
SAMPLE_THR_STOPPING,
SAMPLE_THR_DESTROYED,
SAMPLE_THR_LAST_STATE // must be the last one
};
enum TR_CompThreadActions
{
PROCESS_ENTRY,
GO_TO_SLEEP_EMPTY_QUEUE,
GO_TO_SLEEP_CONCURRENT_EXPENSIVE_REQUESTS,
SUSPEND_COMP_THREAD_EXCEED_CPU_ENTITLEMENT,
THROTTLE_COMP_THREAD_EXCEED_CPU_ENTITLEMENT,
SUSPEND_COMP_THREAD_EMPTY_QUEUE,
UNDEFINED_ACTION
};
#if defined(J9VM_OPT_CRIU_SUPPORT)
enum TR_CheckpointStatus
{
NO_CHECKPOINT_IN_PROGRESS,
CHECKPOINT_IN_PROGRESS,
INTERRUPT_CHECKPOINT
};
#endif
struct DLT_record
{
DLT_record *_next;
J9Method *_method;
void *_dltEntry;
int32_t _bcIndex;
};
struct CompilationStatistics
{
// perhaps not the greatest way to do this, but TR_Stats classes weren't an exact match
uint32_t _heartbeatWindowCount;
uint32_t _windowStartTick;
uint32_t _sampleMessagesSent;
uint32_t _sampleMessagesReceived;
uint32_t _interpretedMethodSamples;
uint32_t _compiledMethodSamples;
uint32_t _compiledMethodSamplesIgnored;
uint32_t _ticksInIdleMode;
uint32_t _methodsCompiledOnCount;
uint32_t _methodsReachingSampleInterval;
uint32_t _methodsSelectedToRecompile;
uint32_t _methodsSampleWindowReset;
}; // CompilationStatistics
struct CompilationStatsPerInterval
{
uint32_t _interpretedMethodSamples;
uint32_t _compiledMethodSamples;
uint32_t _numFirstTimeCompilationsInInterval;
uint32_t _numRecompilationsInInterval;
uint32_t _numRecompPrevInterval;
uint32_t _samplesSentInInterval;
void reset()
{
_interpretedMethodSamples = _compiledMethodSamples = 0;
_numFirstTimeCompilationsInInterval = _numRecompilationsInInterval = 0;
_numRecompPrevInterval = 0; _samplesSentInInterval = 0;
}
void decay()
{
_interpretedMethodSamples >>= 1;
_compiledMethodSamples >>= 1;
_numFirstTimeCompilationsInInterval >>= 1;
_numRecompPrevInterval = _numRecompilationsInInterval; // remember the previous value
_numRecompilationsInInterval = (_numRecompilationsInInterval*2)/3;
_samplesSentInInterval = 0;
}
}; // CompilationStatsPerInterval
static bool createCompilationInfo(J9JITConfig * jitConfig);
static void freeCompilationInfo(J9JITConfig *jitConfig);
static TR::CompilationInfo *get(J9JITConfig * = 0) { return _compilationRuntime; }
static bool shouldRetryCompilation(TR_MethodToBeCompiled *entry, TR::Compilation *comp);
static bool shouldAbortCompilation(TR_MethodToBeCompiled *entry, TR::PersistentInfo *persistentInfo);
static bool canRelocateMethod(TR::Compilation * comp);
static int computeCompilationThreadPriority(J9JavaVM *vm);
static void *compilationEnd(J9VMThread *context, TR::IlGeneratorMethodDetails & details, J9JITConfig *jitConfig, void * startPC,
void *oldStartPC, TR_FrontEnd *vm=0, TR_MethodToBeCompiled *entry=NULL, TR::Compilation *comp=NULL);
#if defined(J9VM_OPT_JITSERVER)
static JITServer::ServerStream *getStream();
#endif /* defined(J9VM_OPT_JITSERVER) */
static bool isInterpreted(J9Method *method) { return !isCompiled(method); }
/**
* @brief Determines if a J9Method is compiled
*
* @param method pointer to the J9Method
*
* @return true if compiled, false otherwise
*/
static bool isCompiled(J9Method *method)
{
#if defined(J9VM_OPT_JITSERVER)
if (auto stream = getStream())
{
stream->write(JITServer::MessageType::CompInfo_isCompiled, method);
return std::get<0>(stream->read<bool>());
}
#endif /* defined(J9VM_OPT_JITSERVER) */
return (getPCIfCompiled(method) != NULL);
}
/**
* @brief Returns the PC of a method that is compiled
*
* @param method pointer to the J9Method
*
* @return The start PC if compiled, NULL otherwise
*/
static void* getPCIfCompiled(J9Method *method)
{
#if defined(J9VM_OPT_JITSERVER)
if (auto stream = getStream())
{
stream->write(JITServer::MessageType::CompInfo_getPCIfCompiled, method);
return std::get<0>(stream->read<void *>());
}
#endif /* defined(J9VM_OPT_JITSERVER) */
/* Read extra field only once */
void *extra = method->extra;
/* Return extra field if compiled, NULL otherwise */
return ((uintptr_t)extra & J9_STARTPC_NOT_TRANSLATED) == 0 ? extra : NULL;
}
static bool isJNINative(J9Method *method)
{
#if defined(J9VM_OPT_JITSERVER)
if (auto stream = getStream())
{
stream->write(JITServer::MessageType::CompInfo_isJNINative, method);
return std::get<0>(stream->read<bool>());
}
#endif /* defined(J9VM_OPT_JITSERVER) */
// Note: This query is only concerned with the method to be compiled
// and so we don't have to care if the VM has a FastJNI version
return (((uintptr_t)method->constantPool) & J9_STARTPC_JNI_NATIVE) != 0;
}
static const intptr_t J9_INVOCATION_COUNT_MASK = 0xffffffff;
static int32_t getInvocationCount(J9Method *method)
{
#if defined(J9VM_OPT_JITSERVER)
if (auto stream = getStream())
{
stream->write(JITServer::MessageType::CompInfo_getInvocationCount, method);
return std::get<0>(stream->read<int32_t>());
}
#endif /* defined(J9VM_OPT_JITSERVER) */
if (((intptr_t)method->extra & J9_STARTPC_NOT_TRANSLATED) == 0)
return -1;
int32_t count = getJ9MethodVMExtra(method);
if (count < 0)
return count;
return count >> 1;
}
static intptr_t getJ9MethodExtra(J9Method *method)
{
#if defined(J9VM_OPT_JITSERVER)
if (auto stream = getStream())
{
stream->write(JITServer::MessageType::CompInfo_getJ9MethodExtra, method);
return (intptr_t) std::get<0>(stream->read<uint64_t>());
}
#endif /* defined(J9VM_OPT_JITSERVER) */
return (intptr_t)method->extra;
}
static int32_t getJ9MethodVMExtra(J9Method *method)
{
#if defined(J9VM_OPT_JITSERVER)
TR_ASSERT_FATAL(!TR::CompilationInfo::getStream(), "not yet implemented for JITServer");
#endif /* defined(J9VM_OPT_JITSERVER) */
return (int32_t)((intptr_t)method->extra);
}
static void * getJ9MethodStartPC(J9Method *method)
{
#if defined(J9VM_OPT_JITSERVER)
if (auto stream = getStream())
{
stream->write(JITServer::MessageType::CompInfo_getJ9MethodStartPC, method);
return std::get<0>(stream->read<void*>());
}
else
#endif /* defined(J9VM_OPT_JITSERVER) */
{
/* Read extra field only once */
void *extra = method->extra;
TR_ASSERT(!((intptr_t)extra & J9_STARTPC_NOT_TRANSLATED), "Method NOT Jitted!");
return extra;
}
}
static void setJ9MethodExtra(J9Method *method, intptr_t newValue)
{
#if defined(J9VM_OPT_JITSERVER)
if (auto stream = getStream())
{
stream->write(JITServer::MessageType::CompInfo_setJ9MethodExtra, method, (uint64_t) newValue);
std::get<0>(stream->read<JITServer::Void>());
}
else
#endif /* defined(J9VM_OPT_JITSERVER) */
{
method->extra = (void *)newValue;
}
}
static bool setJ9MethodExtraAtomic(J9Method *method, intptr_t oldValue, intptr_t newValue)
{
#if defined(J9VM_OPT_JITSERVER)
TR_ASSERT_FATAL(!TR::CompilationInfo::getStream(), "not yet implemented for JITServer");
#endif /* defined(J9VM_OPT_JITSERVER) */
return oldValue == VM_AtomicSupport::lockCompareExchange((UDATA*)&method->extra, oldValue, newValue);
}
static bool setJ9MethodExtraAtomic(J9Method *method, intptr_t newValue)
{
#if defined(J9VM_OPT_JITSERVER)
TR_ASSERT_FATAL(!TR::CompilationInfo::getStream(), "not yet implemented for JITServer");
#endif /* defined(J9VM_OPT_JITSERVER) */
intptr_t oldValue = (intptr_t)method->extra;
return setJ9MethodExtraAtomic(method, oldValue, newValue);
}
static bool setJ9MethodVMExtra(J9Method *method, int32_t value)
{
#if defined(J9VM_OPT_JITSERVER)
TR_ASSERT_FATAL(!TR::CompilationInfo::getStream(), "not yet implemented for JITServer");
#endif /* defined(J9VM_OPT_JITSERVER) */
intptr_t oldValue = (intptr_t)method->extra;
intptr_t newValue = (intptr_t)value;
return setJ9MethodExtraAtomic(method, oldValue, newValue);
}
static bool setInvocationCount(J9Method *method, int32_t newCount)
{
#if defined(J9VM_OPT_JITSERVER)
if (auto stream = getStream())
{
stream->write(JITServer::MessageType::CompInfo_setInvocationCount, method, newCount);
return std::get<0>(stream->read<bool>());
}
#endif /* defined(J9VM_OPT_JITSERVER) */
newCount = (newCount << 1) | J9_STARTPC_NOT_TRANSLATED;
if (newCount < 1)
return false;
return setJ9MethodVMExtra(method, newCount);
}
static bool setInvocationCount(J9Method *method, int32_t oldCount, int32_t newCount)
{
#if defined(J9VM_OPT_JITSERVER)
if (auto stream = getStream())
{
stream->write(JITServer::MessageType::CompInfo_setInvocationCountAtomic, method, oldCount, newCount);
return std::get<0>(stream->read<bool>());
}
#endif /* defined(J9VM_OPT_JITSERVER) */
newCount = (newCount << 1) | J9_STARTPC_NOT_TRANSLATED;
oldCount = (oldCount << 1) | J9_STARTPC_NOT_TRANSLATED;
if (newCount < 0)
return false;
intptr_t oldMethodExtra = (intptr_t) method->extra & (intptr_t)(~J9_INVOCATION_COUNT_MASK);
intptr_t newMethodExtra = oldMethodExtra | newCount;
oldMethodExtra = oldMethodExtra | oldCount;
bool success = setJ9MethodExtraAtomic(method, oldMethodExtra, newMethodExtra);
if (success)
{
DLTTracking *dltHT = _compilationRuntime->getDLT_HT();
if (dltHT)
dltHT->adjustStoredCounterForMethod(method, oldCount - newCount);
}
return success;
}
// If the invocation count is 0, set it to the value indicated by newCount
static bool replenishInvocationCountIfExpired(J9Method *method, int32_t newCount)
{
intptr_t oldMethodExtra = (intptr_t) method->extra;
if ((oldMethodExtra & J9_STARTPC_NOT_TRANSLATED) == 0)
return false; // Do not touch compiled methods
int32_t oldCount = (int32_t)oldMethodExtra;
if (oldCount < 0)
return false; // Do not touch uncountable methods
oldCount >>= 1; // Eliminate the J9_STARTPC_NOT_TRANSLATED bit
if (oldCount != 0)
return false; // Only replenish invocation count if it expired
// Prepare the new method->extra
intptr_t oldMethodExtraUpperPart = oldMethodExtra & (~J9_INVOCATION_COUNT_MASK);
newCount = (newCount << 1) | J9_STARTPC_NOT_TRANSLATED;
intptr_t newMethodExtra = oldMethodExtraUpperPart | newCount;
return setJ9MethodExtraAtomic(method, oldMethodExtra, newMethodExtra);
}
static void setInitialInvocationCountUnsynchronized(J9Method *method, int32_t value)
{
#if defined(J9VM_OPT_JITSERVER)
TR_ASSERT_FATAL(!TR::CompilationInfo::getStream(), "not yet implemented for JITServer");
#endif /* defined(J9VM_OPT_JITSERVER) */
value = (value << 1) | J9_STARTPC_NOT_TRANSLATED;
if (value < 0)
value = INT_MAX;
method->extra = reinterpret_cast<void *>(static_cast<intptr_t>(value));
}
static uint32_t getMethodBytecodeSize(const J9ROMMethod * romMethod);
static uint32_t getMethodBytecodeSize(J9Method* method);
// Check to see if the J9AccMethodHasMethodHandleInvokes flag is set
static bool isJSR292(const J9ROMMethod *romMethod);
static bool isJSR292(J9Method *j9method);
#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))
static void disableAOTCompilations();
#endif
void * operator new(size_t s, void * p) throw() { return p; }
void operator delete (void *, void * p) {}
CompilationInfo (J9JITConfig *jitConfig);
TR::Monitor *getCompilationMonitor() {return _compilationMonitor;}
void acquireCompMonitor(J9VMThread *vmThread); // used when we know we have a compilation monitor
void releaseCompMonitor(J9VMThread *vmThread); // used when we know we have a compilation monitor
void waitOnCompMonitor(J9VMThread *vmThread);
intptr_t waitOnCompMonitorTimed(J9VMThread *vmThread, int64_t millis, int32_t nanos);
#if defined(J9VM_OPT_CRIU_SUPPORT)
/* The CR Monitor (Checkpoint/Restore Monitor) must always be acquired with the Comp Monitor
* in hand. If waiting on the CR Monitor, the Comp Monitor should be released. After being
* notified, the CR Monitor should be released before re-acquiring the Comp Monitor.
*/
TR::Monitor *getCRMonitor() { return _crMonitor; }
void acquireCRMonitor();
void releaseCRMonitor();
void waitOnCRMonitor();
/* The following APIs should only be invoked with the Comp Monitor in hand. */
bool isCheckpointInProgress() { return _checkpointStatus != TR_CheckpointStatus::NO_CHECKPOINT_IN_PROGRESS; }
void setCheckpointInProgress() { _checkpointStatus = TR_CheckpointStatus::CHECKPOINT_IN_PROGRESS; }
void resetCheckpointInProgress() { _checkpointStatus = TR_CheckpointStatus::NO_CHECKPOINT_IN_PROGRESS; }
bool shouldCheckpointBeInterrupted() { return _checkpointStatus == TR_CheckpointStatus::INTERRUPT_CHECKPOINT; }
void interruptCheckpoint() { _checkpointStatus = TR_CheckpointStatus::INTERRUPT_CHECKPOINT; }
#endif
TR_PersistentMemory * persistentMemory() { return _persistentMemory; }
TR::PersistentInfo * getPersistentInfo() { return persistentMemory()->getPersistentInfo(); }
TR_MethodToBeCompiled *requestExistsInCompilationQueue(TR::IlGeneratorMethodDetails & details, TR_FrontEnd *fe);
TR_MethodToBeCompiled *addMethodToBeCompiled(TR::IlGeneratorMethodDetails &details, void *pc, CompilationPriority priority,
bool async, TR_OptimizationPlan *optPlan, bool *queued, TR_YesNoMaybe methodIsInSharedCache);
#if defined(J9VM_OPT_JITSERVER)
TR_MethodToBeCompiled *addOutOfProcessMethodToBeCompiled(JITServer::ServerStream *stream);
#endif /* defined(J9VM_OPT_JITSERVER) */
void queueEntry(TR_MethodToBeCompiled *entry);
void recycleCompilationEntry(TR_MethodToBeCompiled *cur);
#if defined(J9VM_OPT_JITSERVER)
void requeueOutOfProcessEntry(TR_MethodToBeCompiled *entry);
#endif /* defined(J9VM_OPT_JITSERVER) */
TR_MethodToBeCompiled *adjustCompilationEntryAndRequeue(TR::IlGeneratorMethodDetails &details,
TR_PersistentMethodInfo *methodInfo,
TR_Hotness newOptLevel, bool useProfiling,
CompilationPriority priority, TR_J9VMBase *fe);
void changeCompReqFromAsyncToSync(J9Method * method);
int32_t promoteMethodInAsyncQueue(J9Method * method, void *pc);
TR_MethodToBeCompiled *getNextMethodToBeCompiled(TR::CompilationInfoPerThread *compInfoPT, bool compThreadCameOutOfSleep, TR_CompThreadActions*);
TR_MethodToBeCompiled *peekNextMethodToBeCompiled();
TR_MethodToBeCompiled *getMethodQueue() { return _methodQueue; }
int32_t getOverallCompCpuUtilization() const { return _overallCompCpuUtilization; } // -1 in case of error. 0 if feature is not enabled
void setOverallCompCpuUtilization(int32_t c) { _overallCompCpuUtilization = c; }
TR_YesNoMaybe exceedsCompCpuEntitlement() const { return _exceedsCompCpuEntitlement; }
void setExceedsCompCpuEntitlement(TR_YesNoMaybe value) { _exceedsCompCpuEntitlement = value; }
int32_t computeCompThreadSleepTime(int32_t compilationTimeMs);
bool isQueuedForCompilation(J9Method *, void *oldStartPC);
void * startPCIfAlreadyCompiled(J9VMThread *, TR::IlGeneratorMethodDetails & details, void *oldStartPC);
static int32_t getCompThreadSuspensionThreshold(int32_t threadID) { return _compThreadSuspensionThresholds[threadID]; }
// updateNumUsableCompThreads() is called before startCompilationThread() to update TR::Options::_numUsableCompilationThreads.
// It makes sure the number of usable compilation threads is within allowed bounds.
// If not, set it to the upper bound based on the mode: JITClient/non-JITServer or JITServer.
void updateNumUsableCompThreads(int32_t &numUsableCompThreads);
bool allocateCompilationThreads(int32_t numUsableCompThreads);
void freeAllCompilationThreads();
void freeAllResources();
uintptr_t startCompilationThread(int32_t priority, int32_t id, bool isDiagnosticThread);
bool asynchronousCompilation();
void stopCompilationThreads();
/**
* @brief
* Stops a compilation thread by issuing an interruption request at the threads next yield point and by changing
* its state to signal termination. Note that there can be a delay between making this request and the thread
* state changing to `COMPTHREAD_STOPPED`.
*
* @param compInfoPT
* The thread to be stopped.
*/
void stopCompilationThread(CompilationInfoPerThread* compInfoPT);
/**
* @brief Suspends all compilation threads. By default it also purges the comp queue.
*
* @param purgeCompQueue bool to determine whether or not to purge the comp queue.
*/
void suspendCompilationThread(bool purgeCompQueue = true);
/**
* @brief Resumes suspended compilation threads; the number of threads that are
* resumed depends on several factors, such as the queue size and available
* CPU resources.
*/
void resumeCompilationThread();
#if defined(J9VM_OPT_CRIU_SUPPORT)
/**
* @brief Work that is necessary prior to taking a snapshot. This includes:
* - Setting the _checkpointStatus state.
* - Suspending all compilation threads.
* - Waiting until all compilation threads are suspended.
*
* Normal Execution (steps 5&6 can be interchanged)
* ================================================
* 1. Hook Thread acquires Comp Monitor
* 2. Hook Thread signals Comp Threads to suspend
* 3. Hook Thread acquires CR Monitor, releases Comp Monitor, and waits on
* CR Monitor
* 4. Comp Threads acquire Comp Monitor and CompThread Monitor, and change
* state to COMPTHREAD_SUSPENDED
* 5. Comp Threads acquire CR Monitor, call notifyAll, and release CR
* Monitor
* 6. Hook Thread wakes up with CR Monitor in hand, releases CR Monitor, and
* blocks on Comp Monitor
* 7. Comp Threads release Comp Monitor and wait on CompThread Monitor
* 8. Hook Thread acquires Comp Monitor, ensures state has changed to
* COMPTHREAD_SUSPENDED for the current compInfoPT
* 9. Hook Thread checks the next compInfoPT, waiting on the CR Monitor if
* needed (it will release the Comp Monitor prior to waiting)
* 10. Hook Thread releases Comp Monitor, returns from the hook
*
*
* JIT Dump
* ========
* - Crash on application thread:
* - Hook Thread running prepareForCheckpoint will run as normal
* - Comp Threads will suspend themselves
* - Hook Thread will wait till all Comp Threads are suspended
* - Hook Thread will return from the jit hook
* - VM will need to ensure it doesn't invoke criu API
*
* - Crash on compilation thread:
* - Crashing Comp Thread will return to the VM and terminate process
* (https://github.com/eclipse-openj9/openj9/blob/500e0a26e2c5be6ead0f838495ae8d8cc34821e1/runtime/compiler/control/CompilationThread.cpp#L3442-L3447)
* - Possible scenarios for Hook Thread:
* 1. Hook Thread will try to acquire the Comp Monitor to signal Comp
* Threads to suspend but will end up blocking until the JVM
* terminates
* 2. Hook Thread will manage to signal Comp Threads to suspend, but
* will remain waiting on the CR Monitor for the crashed Comp
* Thread to suspend until the JVM terminates
* - VM will need to ensure it doesn't invoke criu API
*
*
* Normal Shutdown
* ===============
* - Scenario 1
* 1. Hook Thread waits on CR Monitor
* 2. Comp Thread goes to suspend, already has Comp Monitor in hand
* 3. Shutdown Thread blocks on the Comp Monitor
* 4. Comp Thread updates state to COMPTHREAD_SUSPENDED, acquires CR
* Monitor, and calls notifyAll
* 5. Comp Thread releases CR Monitor, releases Comp Monitor, and waits
* on CompThread Monitor
* 6. Hook Thread wakes up with CR Monitor in hand, releases CR Monitor,
* acquires Comp Monitor and continues on to next thread
* 7. Hook Thread checks state and moves onto the next threads possibly
* finding them all suspended.
* 8. Hook Thread release Comp Monitor and returns from hook
* 9. Shutdown Thread goes through the sequence of stopping all threads
*
* - Scenario 2
* Repeat steps 1-5 from Scenario 1
* 6. Shutdown Thread acquires Comp Monitor
* 7. Hook Thread wakes up with CR Monitor in hand, releases CR Monitor
* and blocks on the Comp Monitor
* 8. Shutdown Thread sets checkpoint to be interrupted flag.
* Additionally (though irrelevant in this scenario) it also
* acquires the CR Monitor, calls notify, and releases CR Monitor.
* 9. Shutdown Thread finishes stopping all threads, releases Comp
* Monitor
* 10. Hook Thread acquires Comp Monitor, sees that the checkpoint should
* be interrupted
* 11. Hook Thread breaks out of the loops, releases Comp Monitor, and
* returns from hook
*
* - Scenario 3
* 1. Hook Thread waits on CR Monitor
* 2. Shutdown Thread acquires Comp Monitor
* 3. Comp Thread blocks on the Comp Monitor in order to (eventually)
* suspend itself
* 4. Shutdown Thread sets checkpoint to be interrupted flag, acquires CR
* Monitor, calls notify, and releases CR Monitor
* 5. Shutdown Thread goes about the task of stopping Comp Threads
* 6. Hook Thread wakes up with CR Monitor in hand, releases CR Monitor
* and blocks on the Comp Monitor
* 7. Shutdown Thread finishes stopping all threads, releases Comp
* Monitor (steps 5 & 6 can be interchanged with the same following
* steps)
* 8. Hook Thread acquires Comp Monitor, sees that the checkpoint should
* be interrupted
* 9. Hook Thread breaks out of the loops, releases Comp Monitor, and
* returns from hook
*
* It should be noted that when the Hook Thread runs prepareForCheckpoint,
* either it will succeed in signalling the Comp Threads to suspend, or it
* will wait indefinitely on the Comp Monitor (in the case of a JIT Dump) or
* it will abort after acquring the Comp Monitor if the Shutdown Thread
* already finished its task. Once the Hook Thread reaches the point where
* it waits on the CR Monitor, the scenarioes above can occur.
*
*
* Shutdown during JIT Dump
* ========================
* - Crash on application thread
* - same as Normal Shutdown
*
* - Crash on compilation thread
* - In all of the above scenarios:
* - Hook Thread remains waiting on CR Monitor
* - Shutdown Thread blocks on the Comp Monitor
* - Comp Thread returns to VM and terminates the process
*/
void prepareForCheckpoint();
/**
* @brief Work that is necessary after the JVM has been restored. This includes:
* - Resetting the _checkpointStatus state.
* - Resuming all suspended compilation threads.
*/
void prepareForRestore();
#endif
void purgeMethodQueue(TR_CompilationErrorCode errorCode);
void *compileMethod(J9VMThread * context, TR::IlGeneratorMethodDetails &details, void *oldStartPC,
TR_YesNoMaybe async, TR_CompilationErrorCode *, bool *queued, TR_OptimizationPlan *optPlan);
void *compileOnSeparateThread(J9VMThread * context, TR::IlGeneratorMethodDetails &details, void *oldStartPC,
TR_YesNoMaybe async, TR_CompilationErrorCode*,
bool *queued, TR_OptimizationPlan *optPlan);
void invalidateRequestsForUnloadedMethods(TR_OpaqueClassBlock *unloadedClass, J9VMThread * vmThread, bool hotCodeReplacement);
void invalidateRequestsForNativeMethods(J9Class * clazz, J9VMThread * vmThread);
#if defined(J9VM_JIT_DYNAMIC_LOOP_TRANSFER)
void *searchForDLTRecord(J9Method *method, int32_t bcIndex);
void insertDLTRecord(J9Method *method, int32_t bcIndex, void *dltEntry);
void cleanDLTRecordOnUnload();
DLTTracking *getDLT_HT() const { return _dltHT; }
void setDLT_HT(DLTTracking *dltHT) { _dltHT = dltHT; }
#else
DLTTracking *getDLT_HT() const { return NULL; }
#endif // J9VM_JIT_DYNAMIC_LOOP_TRANSFER
J9::RWMonitor *getClassUnloadMonitor() { return _classUnloadMonitor; }
// Synchronize output to the vlog file (or stdout if there is no file)
//
void vlogAcquire();
void vlogRelease();
// Synchronize output to the rtlog file (or stdout if there is no file)
//
void rtlogAcquire();
void rtlogRelease();
// Synchronize updates to J9Method objects
//
void acquireCompilationLock();
void releaseCompilationLock();
TR::Monitor *createLogMonitor();
void acquireLogMonitor();
void releaseLogMonitor();
int32_t getQueueWeight() const { return _queueWeight; }
void increaseQueueWeightBy(uint8_t w) { _queueWeight += (int32_t)w; }
int32_t decreaseQueueWeightBy(uint8_t w) { TR_ASSERT((int32_t)w <= _queueWeight, "assertion failure"); return _queueWeight -= (int32_t)w; }
int32_t getOverallQueueWeight() const { return _queueWeight; /*+ (_LPQWeight >> 1);*/ } // make secondary queue count only half as much
int32_t getMethodQueueSize() const { return _numQueuedMethods; }
void incrementMethodQueueSize();
int32_t getPeakMethodQueueSize() const { return _maxQueueSize; }
int32_t getNumQueuedFirstTimeCompilations() const { return _numQueuedFirstTimeCompilations; }
void decNumGCRReqestsQueued(TR_MethodToBeCompiled *entry);
void incNumGCRRequestsQueued(TR_MethodToBeCompiled *entry);
int32_t getNumGCRRequestsQueued() const { return _numGCRQueued; }
void decNumInvReqestsQueued(TR_MethodToBeCompiled *entry);
void incNumInvRequestsQueued(TR_MethodToBeCompiled *entry);
void updateCompQueueAccountingOnDequeue(TR_MethodToBeCompiled *entry);
int32_t getNumCompThreadsActive() const { return _numCompThreadsActive; }
void incNumCompThreadsActive() { _numCompThreadsActive++; }
void decNumCompThreadsActive() { _numCompThreadsActive--; }
void setNumCompThreadsActive(int32_t n) { _numCompThreadsActive = n; }
int32_t getNumCompThreadsJobless() const { return _numCompThreadsJobless; }
void incNumCompThreadsJobless() { _numCompThreadsJobless++; }
void decNumCompThreadsJobless() { _numCompThreadsJobless--; }
void setNumCompThreadsJobless(int32_t n) { _numCompThreadsJobless = n; }
int32_t getNumCompThreadsCompilingHotterMethods() const { return _numCompThreadsCompilingHotterMethods; }
void incNumCompThreadsCompilingHotterMethods() { _numCompThreadsCompilingHotterMethods++; }
void decNumCompThreadsCompilingHotterMethods() { _numCompThreadsCompilingHotterMethods--; TR_ASSERT(_numCompThreadsCompilingHotterMethods>=0, "assertion failure");}
void setNumCompThreadsCompilingHotterMethods(int32_t n) { _numCompThreadsCompilingHotterMethods = n; }
int32_t getNumAppThreadsActive() const { return _numAppThreadsActive; }
uint64_t getElapsedTimeNumAppThreadsActiveWasSet() const { return _elapsedTimeNumAppThreadsActiveWasSet; }
void setNumAppThreadsActive(int32_t n, uint64_t t) { _numAppThreadsActive = n; _elapsedTimeNumAppThreadsActiveWasSet = t; }
bool useOptLevelAdjustment();
bool getHasResumableTrapHandler() {return _flags.testAny(HasResumableTrapHandler);}
void setHasResumableTrapHandler(bool t=true)
{
if (t)
_flags.set(HasResumableTrapHandler);
else
_flags.reset(HasResumableTrapHandler);
}