blob: 0ca81822a91202e77b459a6dcb4a5d6ce4f07b37 [file] [log] [blame]
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
* vim: set ts=8 sts=4 et sw=4 tw=99:
* 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 */
#ifndef jit_IonOptimizationLevels_h
#define jit_IonOptimizationLevels_h
#include "jsbytecode.h"
#include "jstypes.h"
#include "jit/JitOptions.h"
#include "js/TypeDecls.h"
namespace js {
namespace jit {
enum OptimizationLevel
inline const char*
OptimizationLevelString(OptimizationLevel level)
switch (level) {
case Optimization_DontCompile:
return "Optimization_DontCompile";
case Optimization_Normal:
return "Optimization_Normal";
case Optimization_AsmJS:
return "Optimization_AsmJS";
MOZ_CRASH("Invalid 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 interpreted scripts get inlined.
bool inlineInterpreted_;
// Toggles whether native scripts get inlined.
bool inlineNative_;
// Toggles whether eager unboxing of SIMD is used.
bool eagerSimdUnbox_;
// 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 loop unrolling is performed.
bool loopUnrolling_;
// Toggles whether instruction reordering is performed.
bool reordering_;
// Toggles whether Truncation based on Range Analysis is used.
bool autoTruncate_;
// Toggles whether sincos is used.
bool sincos_;
// Toggles whether sink is used.
bool sink_;
// Describes which register allocator to use.
IonRegisterAllocator registerAllocator_;
// The maximum total bytecode size of an inline call site. We use a lower
// value if off-thread compilation is not available, to avoid stalling the
// main thread.
uint32_t inlineMaxBytecodePerCallSiteOffThread_;
uint32_t inlineMaxBytecodePerCallSiteMainThread_;
// The maximum value we allow for baselineScript->inlinedBytecodeLength_
// when inlining.
uint16_t inlineMaxCalleeInlinedBytecodeLength_;
// The maximum bytecode length we'll inline in a single compilation.
uint32_t inlineMaxTotalBytecodeLength_;
// The maximum bytecode length the caller may have,
// before we stop inlining large functions in that caller.
uint32_t inliningMaxCallerBytecodeLength_;
// The maximum inlining depth.
uint32_t maxInlineDepth_;
// Toggles whether scalar replacement is used.
bool scalarReplacement_;
// The maximum inlining depth for functions.
// Inlining small functions has almost no compiling overhead
// and removes the otherwise needed call overhead.
// The value is currently very low.
// Actually it is only needed to make sure we don't blow out the stack.
uint32_t smallFunctionMaxInlineDepth_;
// How many invocations or loop iterations are needed before functions
// are compiled.
uint32_t compilerWarmUpThreshold_;
// Default compiler warmup threshold, unless it is overridden.
static const uint32_t CompilerWarmupThreshold = 1000;
// How many invocations or loop iterations are needed before calls
// are inlined, as a fraction of compilerWarmUpThreshold.
double inliningWarmUpThresholdFactor_;
// How many invocations or loop iterations are needed before a function
// is hot enough to recompile the outerScript to inline that function,
// as a multiplication of inliningWarmUpThreshold.
uint32_t inliningRecompileThresholdFactor_;
{ }
void initNormalOptimizationInfo();
void initAsmjsOptimizationInfo();
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;
bool eagerSimdUnboxEnabled() const {
return eagerSimdUnbox_ && !JitOptions.disableEagerSimdUnbox;
bool gvnEnabled() const {
return gvn_ && !JitOptions.disableGvn;
bool licmEnabled() const {
return licm_ && !JitOptions.disableLicm;
bool rangeAnalysisEnabled() const {
return rangeAnalysis_ && !JitOptions.disableRangeAnalysis;
bool loopUnrollingEnabled() const {
return loopUnrolling_ && !JitOptions.disableLoopUnrolling;
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 {
if (JitOptions.forcedRegisterAllocator.isSome())
return JitOptions.forcedRegisterAllocator.ref();
return 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)
? inlineMaxBytecodePerCallSiteOffThread_
: inlineMaxBytecodePerCallSiteMainThread_;
uint16_t inlineMaxCalleeInlinedBytecodeLength() const {
return inlineMaxCalleeInlinedBytecodeLength_;
uint32_t inlineMaxTotalBytecodeLength() const {
return inlineMaxTotalBytecodeLength_;
uint32_t inliningMaxCallerBytecodeLength() const {
return inliningMaxCallerBytecodeLength_;
uint32_t inliningWarmUpThreshold() const {
uint32_t compilerWarmUpThreshold = compilerWarmUpThreshold_;
if (JitOptions.forcedDefaultIonWarmUpThreshold.isSome())
compilerWarmUpThreshold = JitOptions.forcedDefaultIonWarmUpThreshold.ref();
return compilerWarmUpThreshold * inliningWarmUpThresholdFactor_;
uint32_t inliningRecompileThreshold() const {
return inliningWarmUpThreshold() * inliningRecompileThresholdFactor_;
class OptimizationInfos
OptimizationInfo infos_[Optimization_Count - 1];
const OptimizationInfo* get(OptimizationLevel level) const {
MOZ_ASSERT(level < Optimization_Count);
MOZ_ASSERT(level != Optimization_DontCompile);
return &infos_[level - 1];
OptimizationLevel nextLevel(OptimizationLevel level) const;
OptimizationLevel firstLevel() const;
bool isLastLevel(OptimizationLevel level) const;
OptimizationLevel levelForScript(JSScript* script, jsbytecode* pc = nullptr) const;
extern OptimizationInfos IonOptimizations;
} // namespace jit
} // namespace js
#endif /* jit_IonOptimizationLevels_h */