#ifndef jit_IonOptimizationLevels_h
#define jit_IonOptimizationLevels_h
#include "mozilla/EnumeratedArray.h"
#include "jstypes.h"
#include "jit/JitOptions.h"
#include "js/TypeDecls.h"
namespace js {
namespace jit {
enum class OptimizationLevel : uint8_t {
Normal,
Full,
Wasm,
Count,
DontCompile
};
#ifdef JS_JITSPEW
inline const char* OptimizationLevelString(OptimizationLevel level) {
switch (level) {
case OptimizationLevel::DontCompile:
return "Optimization_DontCompile";
case OptimizationLevel::Normal:
return "Optimization_Normal";
case OptimizationLevel::Full:
return "Optimization_Full";
case OptimizationLevel::Wasm:
return "Optimization_Wasm";
case OptimizationLevel::Count:;
}
MOZ_CRASH("Invalid OptimizationLevel");
}
#endif
class OptimizationInfo {
OptimizationLevel level_;
bool eaa_;
bool ama_;
bool edgeCaseAnalysis_;
bool eliminateRedundantChecks_;
bool inlineInterpreted_;
bool inlineNative_;
bool gvn_;
bool licm_;
bool rangeAnalysis_;
bool reordering_;
bool autoTruncate_;
bool sincos_;
bool sink_;
IonRegisterAllocator registerAllocator_;
uint32_t inlineMaxBytecodePerCallSiteHelperThread_;
uint32_t inlineMaxBytecodePerCallSiteMainThread_;
uint16_t inlineMaxCalleeInlinedBytecodeLength_;
uint32_t inlineMaxTotalBytecodeLength_;
uint32_t inliningMaxCallerBytecodeLength_;
uint32_t maxInlineDepth_;
bool scalarReplacement_;
uint32_t smallFunctionMaxInlineDepth_;
double inliningWarmUpThresholdFactor_;
uint32_t inliningRecompileThresholdFactor_;
uint32_t baseCompilerWarmUpThreshold() const {
switch (level_) {
case OptimizationLevel::Normal:
return JitOptions.normalIonWarmUpThreshold;
case OptimizationLevel::Full:
if (!JitOptions.disableOptimizationLevels) {
return JitOptions.fullIonWarmUpThreshold;
}
return JitOptions.normalIonWarmUpThreshold;
case OptimizationLevel::DontCompile:
case OptimizationLevel::Wasm:
case OptimizationLevel::Count:
break;
}
MOZ_CRASH("Unexpected optimization level");
}
public:
constexpr OptimizationInfo()
: level_(OptimizationLevel::Normal),
eaa_(false),
ama_(false),
edgeCaseAnalysis_(false),
eliminateRedundantChecks_(false),
inlineInterpreted_(false),
inlineNative_(false),
gvn_(false),
licm_(false),
rangeAnalysis_(false),
reordering_(false),
autoTruncate_(false),
sincos_(false),
sink_(false),
registerAllocator_(RegisterAllocator_Backtracking),
inlineMaxBytecodePerCallSiteHelperThread_(0),
inlineMaxBytecodePerCallSiteMainThread_(0),
inlineMaxCalleeInlinedBytecodeLength_(0),
inlineMaxTotalBytecodeLength_(0),
inliningMaxCallerBytecodeLength_(0),
maxInlineDepth_(0),
scalarReplacement_(false),
smallFunctionMaxInlineDepth_(0),
inliningWarmUpThresholdFactor_(0.0),
inliningRecompileThresholdFactor_(0) {}
void initNormalOptimizationInfo();
void initFullOptimizationInfo();
void initWasmOptimizationInfo();
OptimizationLevel level() const { return level_; }
bool inlineInterpreted() const {
return inlineInterpreted_ && !JitOptions.disableInlining;
}
bool inlineNative() const {
return inlineNative_ && !JitOptions.disableInlining;
}
uint32_t compilerWarmUpThreshold(JSScript* script,
jsbytecode* pc = nullptr) const;
uint32_t recompileWarmUpThreshold(JSScript* script, jsbytecode* pc) const;
bool gvnEnabled() const { return gvn_ && !JitOptions.disableGvn; }
bool licmEnabled() const { return licm_ && !JitOptions.disableLicm; }
bool rangeAnalysisEnabled() const {
return rangeAnalysis_ && !JitOptions.disableRangeAnalysis;
}
bool instructionReorderingEnabled() const {
return reordering_ && !JitOptions.disableInstructionReordering;
}
bool autoTruncateEnabled() const {
return autoTruncate_ && rangeAnalysisEnabled();
}
bool sincosEnabled() const { return sincos_ && !JitOptions.disableSincos; }
bool sinkEnabled() const { return sink_ && !JitOptions.disableSink; }
bool eaaEnabled() const { return eaa_ && !JitOptions.disableEaa; }
bool amaEnabled() const { return ama_ && !JitOptions.disableAma; }
bool edgeCaseAnalysisEnabled() const {
return edgeCaseAnalysis_ && !JitOptions.disableEdgeCaseAnalysis;
}
bool eliminateRedundantChecksEnabled() const {
return eliminateRedundantChecks_;
}
IonRegisterAllocator registerAllocator() const {
return JitOptions.forcedRegisterAllocator.valueOr(registerAllocator_);
}
bool scalarReplacementEnabled() const {
return scalarReplacement_ && !JitOptions.disableScalarReplacement;
}
uint32_t smallFunctionMaxInlineDepth() const {
return smallFunctionMaxInlineDepth_;
}
bool isSmallFunction(JSScript* script) const;
uint32_t maxInlineDepth() const { return maxInlineDepth_; }
uint32_t inlineMaxBytecodePerCallSite(bool offThread) const {
return (offThread || !JitOptions.limitScriptSize)
? inlineMaxBytecodePerCallSiteHelperThread_
: inlineMaxBytecodePerCallSiteMainThread_;
}
uint16_t inlineMaxCalleeInlinedBytecodeLength() const {
return inlineMaxCalleeInlinedBytecodeLength_;
}
uint32_t inlineMaxTotalBytecodeLength() const {
return inlineMaxTotalBytecodeLength_;
}
uint32_t inliningMaxCallerBytecodeLength() const {
return inliningMaxCallerBytecodeLength_;
}
uint32_t inliningWarmUpThreshold() const {
return baseCompilerWarmUpThreshold() * inliningWarmUpThresholdFactor_;
}
uint32_t inliningRecompileThreshold() const {
return inliningWarmUpThreshold() * inliningRecompileThresholdFactor_;
}
};
class OptimizationLevelInfo {
private:
mozilla::EnumeratedArray<OptimizationLevel, OptimizationLevel::Count,
OptimizationInfo>
infos_;
public:
OptimizationLevelInfo();
const OptimizationInfo* get(OptimizationLevel level) const {
return &infos_[level];
}
OptimizationLevel nextLevel(OptimizationLevel level) const;
OptimizationLevel firstLevel() const;
bool isLastLevel(OptimizationLevel level) const;
OptimizationLevel levelForScript(JSScript* script,
jsbytecode* pc = nullptr) const;
};
extern const OptimizationLevelInfo IonOptimizations;
} }
#endif