author Sebastian Hengst <archaeopteryx@coole-files.de>
Fri, 22 Apr 2016 19:18:04 +0200
changeset 332452 3ae9a6bb08211560f6c27a362de4243e676266e9
parent 332434 c23b44faa96925d311e0844b14c8dc468f584f14
child 334425 c0c1d923c29220f227da3e520fcae6c737c60566
permissions -rw-r--r--
Backed out changeset c23b44faa969 (bug 1266676) for failing jsreftest regress-476427.js. r=backout

/* -*- 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 http://mozilla.org/MPL/2.0/. */

#ifndef jit_IonOptimizationLevels_h
#define jit_IonOptimizationLevels_h

#include "mozilla/EnumeratedArray.h"

#include "jsbytecode.h"
#include "jstypes.h"

#include "jit/JitOptions.h"
#include "js/TypeDecls.h"

namespace js {
namespace jit {

enum class OptimizationLevel : uint8_t

inline const char*
OptimizationLevelString(OptimizationLevel level)
    switch (level) {
      case OptimizationLevel::DontCompile:
        return "Optimization_DontCompile";
      case OptimizationLevel::Normal:
        return "Optimization_Normal";
      case OptimizationLevel::AsmJS:
        return "Optimization_AsmJS";
      case OptimizationLevel::Count:;
    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 OptimizationLevelInfo
    mozilla::EnumeratedArray<OptimizationLevel, OptimizationLevel::Count, OptimizationInfo> infos_;


    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 OptimizationLevelInfo IonOptimizations;

} // namespace jit
} // namespace js

#endif /* jit_IonOptimizationLevels_h */