Path: blob/master/runtime/compiler/control/RecompilationInfo.hpp
6000 views
/*******************************************************************************1* Copyright (c) 2000, 2021 IBM Corp. and others2*3* This program and the accompanying materials are made available under4* the terms of the Eclipse Public License 2.0 which accompanies this5* distribution and is available at https://www.eclipse.org/legal/epl-2.0/6* or the Apache License, Version 2.0 which accompanies this distribution and7* is available at https://www.apache.org/licenses/LICENSE-2.0.8*9* This Source Code may also be made available under the following10* Secondary Licenses when the conditions for such availability set11* forth in the Eclipse Public License, v. 2.0 are satisfied: GNU12* General Public License, version 2 with the GNU Classpath13* Exception [1] and GNU General Public License, version 2 with the14* OpenJDK Assembly Exception [2].15*16* [1] https://www.gnu.org/software/classpath/license.html17* [2] http://openjdk.java.net/legal/assembly-exception.html18*19* 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-exception20*******************************************************************************/2122#ifndef TR_RECOMPILATION_INFO_INCL23#define TR_RECOMPILATION_INFO_INCL242526#include <stddef.h>27#include <stdint.h>28#include "compile/Compilation.hpp"29#include "compile/CompilationTypes.hpp"30#include "control/Options.hpp"31#include "control/Options_inlines.hpp"32#include "env/CHTable.hpp"33#include "env/TRMemory.hpp"34#include "env/defines.h"35#include "env/jittypes.h"36#include "infra/Assert.hpp"37#include "infra/Flags.hpp"38#include "infra/Link.hpp"39#include "infra/Timer.hpp"40#include "runtime/J9Profiler.hpp"4142class TR_FrontEnd;43class TR_OpaqueMethodBlock;44class TR_OptimizationPlan;45class TR_ResolvedMethod;46namespace TR { class Instruction; }47namespace TR { class SymbolReference; }4849// Bits to represent sampling mechanism in method return info field.50// Bits 3, 4, 5, 6, 7 are reserved for this purpose (could use fewer)51// This has to be in sync with LinkageInfo (in Runtime.hpp).52//53#define METHOD_SAMPLING_RECOMPILATION 0x0000001054#define METHOD_COUNTING_RECOMPILATION 0x0000002055#define METHOD_HAS_BEEN_RECOMPILED 0x000000405657// Adaptive Profiling Parameters: chose smaller counts for methods58// with fewer back-edges.59// 0 1 2 3 4 >= 5 <-- number of async checks60static int32_t profilingCountsTable[] = { 100, 625, 1250, 2500, 5000, 10000 }; // <-- profiling count61static int32_t profilingFreqTable [] = { 19, 29, 47, 47, 47, 53 }; // <-- profiling frequency62// (should be prime)63#define MAX_BACKEDGES (5) // max index in the above array6465#define DEFAULT_PROFILING_FREQUENCY (profilingFreqTable [MAX_BACKEDGES])66#define DEFAULT_PROFILING_COUNT (profilingCountsTable[MAX_BACKEDGES])6768namespace TR { class DefaultCompilationStrategy; }69namespace TR { class ThresholdCompilationStrategy; }70namespace OMR { class Recompilation; }71namespace J9 { class Recompilation; }7273// Persistent information associated with a method for recompilation74//75class TR_PersistentMethodInfo76{77friend class OMR::Recompilation;78friend class J9::Recompilation;79friend class TR::CompilationInfo;80friend class TR_S390Recompilation; // FIXME: ugly81friend class ::OMR::Options;82friend class TR::DefaultCompilationStrategy;83friend class TR::ThresholdCompilationStrategy;8485public:86TR_PERSISTENT_ALLOC(TR_Memory::PersistentMethodInfo);8788TR_PersistentMethodInfo() {}89TR_PersistentMethodInfo(TR::Compilation *);90TR_PersistentMethodInfo(TR_OpaqueMethodBlock *);9192static TR_PersistentMethodInfo * get(TR::Compilation *);93static TR_PersistentMethodInfo * get(TR_ResolvedMethod * method);94TR_OpaqueMethodBlock * getMethodInfo() {return _methodInfo;}95void * getAddressOfMethodInfo() { return &_methodInfo; }9697void setMethodInfo(void *mi) { _methodInfo = (TR_OpaqueMethodBlock *)mi; }9899100void setDisableProfiling() { _flags.set(ProfilingDisabled); }101bool profilingDisabled() { return _flags.testAny(ProfilingDisabled); }102103void setDisableMiscSamplingCounterDecrementation() { _flags.set(DisableMiscSamplingCounterDecrementation); }104bool disableMiscSamplingCounterDecrementation() { return _flags.testAny(DisableMiscSamplingCounterDecrementation); }105106void setOptLevelDowngraded(bool b) { _flags.set(OptLevelDowngraded, b); }107bool isOptLevelDowngraded() { return _flags.testAny(OptLevelDowngraded); }108109void setReasonForRecompilation(int32_t reason) { _flags.setValue(CompilationReasonMask, reason); }110int32_t getReasonForRecompilation() { return _flags.getValue(CompilationReasonMask); }111112bool hasBeenReplaced() { return _flags.testAny(HasBeenReplaced); }113void setHasBeenReplaced(bool b=true) { _flags.set(HasBeenReplaced, b); }114115bool wasNeverInterpreted() { return _flags.testAny(WasNeverInterpreted); }116void setWasNeverInterpreted(bool b) { _flags.set(WasNeverInterpreted, b); }117118bool wasScannedForInlining() { return _flags.testAny(WasScannedForInlining); }119void setWasScannedForInlining(bool b) { _flags.set(WasScannedForInlining, b); }120121bool isInDataCache() { return _flags.testAny(IsInDataCache); }122void setIsInDataCache(bool b) { _flags.set(IsInDataCache, b); }123124bool hasFailedDLTCompRetrials() { return _flags.testAny(HasFailedDLTCompRetrials); }125void setHasFailedDLTCompRetrials(bool b) { _flags.set(HasFailedDLTCompRetrials, b); }126127bool hasRefinedAliasSets() { return _flags.testAny(RefinedAliasesMask); }128129bool doesntKillAddressStatics() { return _flags.testAny(DoesntKillAddressStatics); }130void setDoesntKillAddressStatics(bool b) { _flags.set(DoesntKillAddressStatics, b); }131132bool doesntKillIntStatics() { return _flags.testAny(DoesntKillIntStatics); }133void setDoesntKillIntStatics(bool b) { _flags.set(DoesntKillIntStatics, b); }134135bool doesntKillNonIntPrimitiveStatics() { return _flags.testAny(DoesntKillNonIntPrimitiveStatics); }136void setDoesntKillNonIntPrimitiveStatics(bool b) { _flags.set(DoesntKillNonIntPrimitiveStatics, b); }137138bool doesntKillAddressFields() { return _flags.testAny(DoesntKillAddressFields); }139void setDoesntKillAddressFields(bool b) { _flags.set(DoesntKillAddressFields, b); }140141bool doesntKillIntFields() { return _flags.testAny(DoesntKillIntFields); }142void setDoesntKillIntFields(bool b) { _flags.set(DoesntKillIntFields, b); }143144bool doesntKillNonIntPrimitiveFields() { return _flags.testAny(DoesntKillNonIntPrimitiveFields); }145void setDoesntKillNonIntPrimitiveFields(bool b) { _flags.set(DoesntKillNonIntPrimitiveFields, b); }146147bool doesntKillAddressArrayShadows() { return _flags.testAny(DoesntKillAddressArrayShadows); }148void setDoesntKillAddressArrayShadows(bool b) { _flags.set(DoesntKillAddressArrayShadows, b); }149150bool doesntKillIntArrayShadows() { return _flags.testAny(DoesntKillIntArrayShadows); }151void setDoesntKillIntArrayShadows(bool b) { _flags.set(DoesntKillIntArrayShadows, b); }152153bool doesntKillNonIntPrimitiveArrayShadows() { return _flags.testAny(DoesntKillNonIntPrimitiveArrayShadows); }154void setDoesntKillNonIntPrimitiveArrayShadows(bool b) { _flags.set(DoesntKillNonIntPrimitiveArrayShadows, b); }155156bool doesntKillEverything() { return _flags.testAny(DoesntKillEverything); }157void setDoesntKillEverything(bool b) { _flags.set(DoesntKillEverything, b); }158159bool doesntKillAnything() { return _flags.testAll(RefinedAliasesMask); }160161// Accessor methods for the "cpoCounter". This does not really162// need to be its own counter, as it is conceptually the same as163// "_counter". However, the original _counter is still during instrumentation, so164// it was simplest to keep them separate165//166int32_t cpoGetCounter() {return _cpoSampleCounter;}167int32_t cpoIncCounter() {return ++_cpoSampleCounter;}168int32_t cpoSetCounter(int newCount) {return _cpoSampleCounter = newCount;}169170uint16_t getTimeStamp() { return _timeStamp; }171172TR_OptimizationPlan * getOptimizationPlan() {return _optimizationPlan;}173void setOptimizationPlan(TR_OptimizationPlan *optPlan) { _optimizationPlan = optPlan; }174uint8_t getNumberOfInvalidations() {return _numberOfInvalidations;}175void incrementNumberOfInvalidations() {_numberOfInvalidations++;}176uint8_t getNumberOfInlinedMethodRedefinition() {return _numberOfInlinedMethodRedefinition;}177void incrementNumberOfInlinedMethodRedefinition() {_numberOfInlinedMethodRedefinition++;}178int16_t getNumPrexAssumptions() {return _numPrexAssumptions;}179void incNumPrexAssumptions() {_numPrexAssumptions++;}180181enum InfoBits182{183// Normally set by the previous compilation to indicate that the next184// compilation should use profiling. Sometimes we can start out without185// profiling and then set it during if switched our minds.186// At the end of compilation we set it to the value we want for the187// next compilation.188// If the flag ProfilingDisabled (below) is set we should never set this flag.189UseProfiling = 0x00000001,190191CanBeCalledInSinglePrecisionMode = 0x00000002,192193// This flag disables any future profiling of this method.194// Normally we set this when we know that profiling is going to have195// a large overhead.196ProfilingDisabled = 0x00000004,197198// This flag is used to disable the decrementation of the sampling199// counter for reasons other than sampling or EDO. Normally it is set in200// sampleMethod when a recompilation is triggered by PIC misses decrementing201// the sampling counter or by profiling of PIC addresses at warm.202DisableMiscSamplingCounterDecrementation=0x00000008,203204// This flag is set when a method is silently downgraded from warm to cold205OptLevelDowngraded = 0x00000010,206207HasFailedDLTCompRetrials = 0x00000020,208209RefinedAliasesMask = 0x0000FFC0,210211DoesntKillAddressStatics = 0x00000040,212DoesntKillIntStatics = 0x00000080,213DoesntKillNonIntPrimitiveStatics = 0x00000100,214DoesntKillAddressFields = 0x00000200,215DoesntKillIntFields = 0x00000400,216DoesntKillNonIntPrimitiveFields = 0x00000800,217DoesntKillAddressArrayShadows = 0x00001000,218DoesntKillIntArrayShadows = 0x00002000,219DoesntKillNonIntPrimitiveArrayShadows= 0x00004000,220DoesntKillEverything = 0x00008000,221222// Define 4 bits to record the reason for recompilation (RAS feature; will be printed in VLOG)223CompilationReasonMask = 0x000F0000,224RecompDueToThreshold = 0x00010000,225RecompDueToCounterZero = 0x00020000,226RecompDueToMegamorphicCallProfile = 0x00030000, // also PIC miss (because we cannot distinguish between the two)227RecompDueToEdo = 0x00040000,228RecompDueToOptLevelUpgrade = 0x00050000,229RecompDueToSecondaryQueue = 0x00060000,230RecompDueToRecompilationPushing = 0x00070000,231RecompDueToGCR = 0x00080000,232RecompDueToForcedAOTUpgrade = 0x00090000,233RecompDueToRI = 0x000A0000,234RecompDueToJProfiling = 0x000B0000,235RecompDueToInlinedMethodRedefinition = 0x000C0000,236// NOTE: recompilations due to EDO decrementation cannot be tracked237// because they are triggered from a snippet (must change the code for snippet)238// Also, the recompilations after a profiling step cannot be marked as such.239// NOTE: recompilations can be triggered by invalidations too, but this240// information is already available in the linkage info for the body241242HasBeenReplaced = 0x00100000, // HCR: this struct is for the old version of a replaced method243// Note: _methodInfo points to the methodInfo for the new version244// Note: this flag is accessed from recomp asm code, so be careful about changing it245WasNeverInterpreted = 0x00200000, // for methods that were compiled at count=0246// Attention: this is not always accurate247WasScannedForInlining = 0x00400000, // New scanning for warm method inlining248IsInDataCache = 0x00800000, // This TR_PersistentMethodInfo is stored in the datacache for AOT249lastFlag = 0x80000000250};251252void setNextCompileLevel(TR_Hotness level, bool profile)253{254_nextHotness = level; if (profile) TR_ASSERT(!profilingDisabled(), "assertion failure");255_flags.set(UseProfiling, profile);256}257258TR_Hotness getNextCompileLevel() { return _nextHotness; }259bool getNextCompileProfiling() { return _flags.testAny(UseProfiling); }260261/**262* Methods to update and access profile information. These will modify reference counts.263* Most accesses to profiling data should go TR_AccessesProfileInfo on TR::Compilation,264* as it will manage reference counts for a compilation.265*266* Several threads may attempt to manipulate reference counts on these at once, potentially267* resulting in a deallocation before it was intended. The low bit of the relevant pointer268* is reused to avoid these situations. All accesses to _bestProfileInfo and _recentProfileInfo269* should consider this.270*/271TR_PersistentProfileInfo *getBestProfileInfo() { return getForSharedInfo(&_bestProfileInfo); }272TR_PersistentProfileInfo *getRecentProfileInfo() { return getForSharedInfo(&_recentProfileInfo); }273void setBestProfileInfo(TR_PersistentProfileInfo * ppi) { setForSharedInfo(&_bestProfileInfo, ppi); }274void setRecentProfileInfo(TR_PersistentProfileInfo * ppi) { setForSharedInfo(&_recentProfileInfo, ppi); }275276// ### IMPORTANT ###277// Method info must always be the first field in this structure278// Flags must always be second279private:280TR_OpaqueMethodBlock *_methodInfo;281flags32_t _flags;282// ### IMPORTANT ###283284// During compilation _nextHotness is really the present hotness285// at which compilation is taking place. This is setup at the end286// of compilation to correct hotness level the next compilation should287// be at. This may get tweaked by the sampling thread at runtime.288//289TR_Hotness _nextHotness;290291292TR_OptimizationPlan *_optimizationPlan;293294int32_t _cpoSampleCounter; // TODO remove this field295uint16_t _timeStamp;296uint8_t _numberOfInvalidations; // how many times this method has been invalidated297uint8_t _numberOfInlinedMethodRedefinition; // how many times this method triggers recompilation because of its inlined callees being redefined298int16_t _numPrexAssumptions;299300TR_PersistentProfileInfo *_bestProfileInfo;301TR_PersistentProfileInfo *_recentProfileInfo;302303TR_PersistentProfileInfo * getForSharedInfo(TR_PersistentProfileInfo** ptr);304void setForSharedInfo(TR_PersistentProfileInfo** ptr, TR_PersistentProfileInfo *newInfo);305};306307308// This information is kept for every jitted method that can be recompiled309// It may be garbage collected along with the jitted method310// The only way to get the following information is via a pointer that is kept311// in the prologue of the jitted method.312//313class TR_PersistentJittedBodyInfo314{315friend class OMR::Recompilation;316friend class J9::Recompilation;317friend class TR::CompilationInfo;318friend class TR_S390Recompilation; // FIXME: ugly319friend class TR::DefaultCompilationStrategy;320friend class TR_EmilyPersistentJittedBodyInfo;321friend class ::OMR::Options;322friend class J9::Options;323324#if defined(TR_HOST_X86) || defined(TR_HOST_POWER) || defined(TR_HOST_S390) || defined(TR_HOST_ARM) || defined(TR_HOST_ARM64)325friend void fixPersistentMethodInfo(void *table, bool isJITClientAOTLoad);326#endif327328public:329TR_PERSISTENT_ALLOC(TR_Memory::PersistentJittedBodyInfo);330331static TR_PersistentJittedBodyInfo *get(void *startPC);332333bool getHasLoops() { return _flags.testAny(HasLoops); }334bool getUsesPreexistence() { return _flags.testAny(UsesPreexistence); }335bool getDisableSampling() { return _flags.testAny(DisableSampling); }336void setDisableSampling(bool b) { _flags.set(DisableSampling, b); }337bool getIsProfilingBody() { return _flags.testAny(IsProfilingBody); }338bool getIsAotedBody() { return _flags.testAny(IsAotedBody); }339void setIsAotedBody(bool b) { _flags.set(IsAotedBody, b); }340bool getIsRemoteCompileBody() { return _flags.testAny(IsRemoteCompileBody); }341void setIsRemoteCompileBody(bool b){ _flags.set(IsRemoteCompileBody, b); }342bool getSamplingRecomp() { return _flags.testAny(SamplingRecomp); }343void setSamplingRecomp() { _flags.set(SamplingRecomp, true); }344bool getIsPushedForRecompilation(){ return _flags.testAny(IsPushedForRecompilation); }345void setIsPushedForRecompilation(){ _flags.set(IsPushedForRecompilation, true); }346bool getIsInvalidated() { return _isInvalidated; }347void setIsInvalidated() { _isInvalidated = true; }348349bool getFastHotRecompilation() { return _flags.testAny(FastHotRecompilation); }350void setFastHotRecompilation(bool b){ _flags.set(FastHotRecompilation, b); }351bool getFastScorchingRecompilation(){ return _flags.testAny(FastScorchingRecompilation); }352void setFastScorchingRecompilation(bool b){ _flags.set(FastScorchingRecompilation, b); }353bool getFastRecompilation() { return _flags.testAny(FastRecompilationMask); }354355bool getUsesGCR() { return _flags.testAny(UsesGCR); }356void setUsesGCR() { _flags.set(UsesGCR, true); }357358bool getReducedWarm() { return _flags.testAny(ReducedWarm); }359void setReducedWarm() { _flags.set(ReducedWarm, true); }360361bool getUsesSamplingJProfiling() { return _flags.testAny(UsesSamplingJProfiling); }362void setUsesSamplingJProfiling() { _flags.set(UsesSamplingJProfiling, true); }363364bool getUsesJProfiling() { return _flags.testAny(UsesJProfiling); }365void setUsesJProfiling() { _flags.set(UsesJProfiling, true); }366367// used in dump recompilations368void *getStartPCAfterPreviousCompile() { return _startPCAfterPreviousCompile; }369void setStartPCAfterPreviousCompile(void *oldStartPC) { _startPCAfterPreviousCompile = oldStartPC; }370371TR_PersistentMethodInfo *getMethodInfo() { return _methodInfo; }372int32_t getCounter() const { return _counter; }373int32_t getStartCount() const { return _startCount; }374TR_Hotness getHotness() const { return _hotness; }375void setHotness(TR_Hotness h) { _hotness = h; }376int32_t getOldStartCount() const { return _startCount - _oldStartCountDelta; } // FIXME: what if this is negative?377uint16_t getOldStartCountDelta() const { return _oldStartCountDelta; }378uint16_t getHotStartCountDelta() const { return _hotStartCountDelta; }379void setHotStartCountDelta(uint16_t v) { _hotStartCountDelta = v; }380381// TODO: can we eliminate this mechanism?382// FIXME: this should be unsigned383uint8_t getAggressiveRecompilationChances() const { return _aggressiveRecompilationChances; }384uint8_t decAggressiveRecompilationChances() { return _aggressiveRecompilationChances > 0 ? --_aggressiveRecompilationChances : 0; }385386uint8_t getNumScorchingIntervals() const { return _numScorchingIntervals; }387void incNumScorchingIntervals() { if (_numScorchingIntervals < 255) ++_numScorchingIntervals; }388void setMethodInfo(TR_PersistentMethodInfo *mi) { _methodInfo = mi; }389void setStartCount(int32_t count) { _startCount = count; }390void setCounter(int32_t counter) { _counter = counter; }391void setOldStartCountDelta(uint16_t count) { _oldStartCountDelta = count; }392393void *getMapTable() const { return _mapTable; }394void setMapTable(void* p) { _mapTable = p; }395396bool isLongRunningInterpreted() const { return _longRunningInterpreted; }397398/**399* Access and modify the persistent profile info for this body.400*401* Uses of these methods should only occur while the body info is guaranteed402* to not be cleaned up, such as during its compilation. This is because403* these calls do not manage reference counts or synchronization, in404* an attempt to reduce the overhead on accesses that are known to be safe.405*/406void setProfileInfo(TR_PersistentProfileInfo * ppi) { _profileInfo = ppi; }407TR_PersistentProfileInfo *getProfileInfo() { return _profileInfo; }408409enum410{411HasLoops = 0x0001,412//HasManyIterationsLoops = 0x0002, // Available413UsesPreexistence = 0x0004,414DisableSampling = 0x0008, // This flag disables sampling of this method even though its recompilable415IsProfilingBody = 0x0010,416IsAotedBody = 0x0020, // } Mutually417IsRemoteCompileBody = 0x0040, // } exclusive418SamplingRecomp = 0x0080, // Set when recomp decision is taken due to sampling; used to419// prevent further sampling once a decision is taken420IsPushedForRecompilation= 0x0100, // Set when the counter of this method is abruptly decremented to 1421// by the recompilation pushing mechanism422FastRecompilationMask = 0x0600, // RAS423FastHotRecompilation = 0x0200, // RAS flag424FastScorchingRecompilation=0x0400,// RAS flag425UsesGCR = 0x0800,426ReducedWarm = 0x1000, // Warm body was optimized to a lesser extent (NoServer) to reduce compilation time427UsesSamplingJProfiling = 0x2000, // Body has samplingJProfiling code428UsesJProfiling = 0x4000 // Body has jProfiling code429};430431// ### IMPORTANT ###432// These following four fields must always be the first four elements of this structure433private:434int32_t _counter; // must be at offset 0435TR_PersistentMethodInfo *_methodInfo; // must be at offset 4 (8 for 64bit)436void *_startPCAfterPreviousCompile;437void *_mapTable; // must be at offset 12 (24 for 64bit)438439// ### IMPORTANT ###440441static TR_PersistentJittedBodyInfo *allocate(TR_PersistentMethodInfo *methodInfo, TR_Hotness hotness, bool profiling, TR::Compilation * comp = 0);442TR_PersistentJittedBodyInfo(TR_PersistentMethodInfo *methodInfo, TR_Hotness hotness, bool profile, TR::Compilation * comp = 0);443444int32_t *getCounterAddress() {return &_counter; }445int32_t decCounter() { return --_counter; } //FIXME verify implementation446447uint8_t getSampleIntervalCount() { return _sampleIntervalCount; }448void setSampleIntervalCount(uint8_t val) { _sampleIntervalCount = val; }449uint8_t incSampleIntervalCount(uint8_t maxValue)450{451if (++_sampleIntervalCount >= maxValue)452{453_sampleIntervalCount = 0; // wrap around454incNumScorchingIntervals();455}456return _sampleIntervalCount;457}458459460void setHasLoops(bool b) { _flags.set(HasLoops, b); }461void setUsesPreexistence(bool b) { _flags.set(UsesPreexistence, b); }462void setIsProfilingBody(bool b) { _flags.set(IsProfilingBody, b); }463464int32_t _startCount; // number of global samples at the beginning of the sampling window465uint16_t _hotStartCountDelta; // delta from the startCount (for the begin of a hot sampling window)466uint16_t _oldStartCountDelta; // delta from the current start count (in the past);467flags16_t _flags;468uint8_t _sampleIntervalCount; // increases from 0 to 29. Defines a hot sampling window (30 samples)469uint8_t _aggressiveRecompilationChances;470TR_Hotness _hotness;471uint8_t _numScorchingIntervals; // How many times we reached scorching recompilation decision points472bool _isInvalidated;473bool _longRunningInterpreted; // This cannot be moved into _flags due to synchronization issues474TR_PersistentProfileInfo * _profileInfo;475public:476// Used for HWP-based recompilation477bool _hwpInducedRecompilation;478bool _hwpReducedWarmCompileRequested;479bool _hwpReducedWarmCompileInQueue;480uint64_t _hwpInstructionStartCount;481uint32_t _hwpInstructionCount;482};483484#endif485486487