/* This Source Code Form is subject to the terms of the Mozilla Public
* License, v. 2.0. If a copy of the MPL was not distributed with this
* file, You can obtain one at http://mozilla.org/MPL/2.0/. */
#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, 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::Wasm:
return "Optimization_Wasm";
case OptimizationLevel::Count:;
}
MOZ_CRASH(
"Invalid OptimizationLevel");
}
#endif
// Class representing the Ion optimization settings for an OptimizationLevel.
class OptimizationInfo {
OptimizationLevel level_;
// Toggles whether Effective Address Analysis is performed.
bool eaa_;
// Toggles whether Alignment Mask Analysis is performed.
bool ama_;
// Toggles whether Edge Case Analysis is used.
bool edgeCaseAnalysis_;
// Toggles whether redundant checks get removed.
bool eliminateRedundantChecks_;
// Toggles whether redundant shape guards get removed.
bool eliminateRedundantShapeGuards_;
// Toggles whether redundant GC barriers get removed.
bool eliminateRedundantGCBarriers_;
// Toggles whether interpreted scripts get inlined.
bool inlineInterpreted_;
// Toggles whether native scripts get inlined.
bool inlineNative_;
// Toggles whether global value numbering is used.
bool gvn_;
// Toggles whether loop invariant code motion is performed.
bool licm_;
// Toggles whether Range Analysis is used.
bool rangeAnalysis_;
// Toggles whether instruction reordering is performed.
bool reordering_;
// Toggles whether Truncation based on Range Analysis is used.
bool autoTruncate_;
// Toggles whether scalar replacement is used.
bool scalarReplacement_;
// Describes which register allocator to use.
IonRegisterAllocator registerAllocator_;
public:
constexpr OptimizationInfo()
: level_(OptimizationLevel::Normal),
eaa_(
false),
ama_(
false),
edgeCaseAnalysis_(
false),
eliminateRedundantChecks_(
false),
eliminateRedundantShapeGuards_(
false),
eliminateRedundantGCBarriers_(
false),
inlineInterpreted_(
false),
inlineNative_(
false),
gvn_(
false),
licm_(
false),
rangeAnalysis_(
false),
reordering_(
false),
autoTruncate_(
false),
scalarReplacement_(
false),
registerAllocator_(RegisterAllocator_Backtracking) {}
constexpr
void initNormalOptimizationInfo() {
level_ = OptimizationLevel::Normal;
autoTruncate_ = true;
eaa_ = true;
edgeCaseAnalysis_ = true;
eliminateRedundantChecks_ = true;
eliminateRedundantShapeGuards_ = true;
eliminateRedundantGCBarriers_ = true;
inlineInterpreted_ = true;
inlineNative_ = true;
licm_ = true;
gvn_ = true;
rangeAnalysis_ = true;
reordering_ = true;
scalarReplacement_ = true;
registerAllocator_ = RegisterAllocator_Backtracking;
}
constexpr
void initWasmOptimizationInfo() {
// The Wasm optimization level
// Disables some passes that don't work well with wasm.
// Take normal option values for not specified values.
initNormalOptimizationInfo();
level_ = OptimizationLevel::Wasm;
ama_ = true;
autoTruncate_ =
false;
edgeCaseAnalysis_ =
false;
eliminateRedundantChecks_ =
false;
eliminateRedundantShapeGuards_ =
false;
eliminateRedundantGCBarriers_ =
false;
scalarReplacement_ = true;
}
OptimizationLevel level()
const {
return level_; }
bool inlineInterpreted()
const {
return inlineInterpreted_ && !JitOptions.disableInlining;
}
bool inlineNative()
const {
return inlineNative_ && !JitOptions.disableInlining;
}
static uint32_t baseWarmUpThresholdForScript(JSContext* cx, JSScript* script);
static uint32_t warmUpThresholdForPC(JSScript* script, jsbytecode* pc,
uint32_t baseThreshold);
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 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_;
}
bool eliminateRedundantShapeGuardsEnabled()
const {
return eliminateRedundantShapeGuards_ &&
!JitOptions.disableRedundantShapeGuards;
}
bool eliminateRedundantGCBarriersEnabled()
const {
return eliminateRedundantGCBarriers_ &&
!JitOptions.disableRedundantGCBarriers;
}
IonRegisterAllocator registerAllocator()
const;
bool scalarReplacementEnabled()
const {
return scalarReplacement_ && !JitOptions.disableScalarReplacement;
}
};
class OptimizationLevelInfo {
private:
mozilla::EnumeratedArray<OptimizationLevel, OptimizationInfo,
size_t(OptimizationLevel::Count)>
infos_;
public:
constexpr OptimizationLevelInfo() {
infos_[OptimizationLevel::Normal].initNormalOptimizationInfo();
infos_[OptimizationLevel::Wasm].initWasmOptimizationInfo();
}
const OptimizationInfo* get(OptimizationLevel level)
const {
return &infos_[level];
}
OptimizationLevel levelForScript(JSContext* cx, JSScript* script,
jsbytecode* pc = nullptr)
const;
};
constexpr OptimizationLevelInfo IonOptimizations;
}
// namespace jit
}
// namespace js
#endif /* jit_IonOptimizationLevels_h */