michael@0: /* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*- michael@0: * vim: set ts=8 sts=4 et sw=4 tw=99: michael@0: * This Source Code Form is subject to the terms of the Mozilla Public michael@0: * License, v. 2.0. If a copy of the MPL was not distributed with this michael@0: * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ michael@0: michael@0: #ifndef jit_IonOptimizationLevels_h michael@0: #define jit_IonOptimizationLevels_h michael@0: michael@0: #include "jsbytecode.h" michael@0: #include "jstypes.h" michael@0: michael@0: #include "jit/JitOptions.h" michael@0: #include "js/TypeDecls.h" michael@0: michael@0: namespace js { michael@0: namespace jit { michael@0: michael@0: enum OptimizationLevel michael@0: { michael@0: Optimization_DontCompile, michael@0: Optimization_Normal, michael@0: Optimization_AsmJS, michael@0: Optimization_Count michael@0: }; michael@0: michael@0: #ifdef JS_ION michael@0: michael@0: #ifdef DEBUG michael@0: inline const char * michael@0: OptimizationLevelString(OptimizationLevel level) michael@0: { michael@0: switch (level) { michael@0: case Optimization_DontCompile: michael@0: return "Optimization_DontCompile"; michael@0: case Optimization_Normal: michael@0: return "Optimization_Normal"; michael@0: case Optimization_AsmJS: michael@0: return "Optimization_AsmJS"; michael@0: default: michael@0: MOZ_ASSUME_UNREACHABLE("Invalid OptimizationLevel"); michael@0: } michael@0: } michael@0: #endif michael@0: michael@0: class OptimizationInfo michael@0: { michael@0: public: michael@0: OptimizationLevel level_; michael@0: michael@0: // Toggles whether Effective Address Analysis is performed. michael@0: bool eaa_; michael@0: michael@0: // Toggles whether Edge Case Analysis is used. michael@0: bool edgeCaseAnalysis_; michael@0: michael@0: // Toggles whether redundant checks get removed. michael@0: bool eliminateRedundantChecks_; michael@0: michael@0: // Toggles whether interpreted scripts get inlined. michael@0: bool inlineInterpreted_; michael@0: michael@0: // Toggles whether native scripts get inlined. michael@0: bool inlineNative_; michael@0: michael@0: // Toggles whether global value numbering is used. michael@0: bool gvn_; michael@0: michael@0: // Toggles whether global value numbering is optimistic or pessimistic. michael@0: IonGvnKind gvnKind_; michael@0: michael@0: // Toggles whether loop invariant code motion is performed. michael@0: bool licm_; michael@0: michael@0: // Toggles whether Unreachable Code Elimination is performed. michael@0: bool uce_; michael@0: michael@0: // Toggles whether Range Analysis is used. michael@0: bool rangeAnalysis_; michael@0: michael@0: // Describes which register allocator to use. michael@0: IonRegisterAllocator registerAllocator_; michael@0: michael@0: // The maximum total bytecode size of an inline call site. michael@0: uint32_t inlineMaxTotalBytecodeLength_; michael@0: michael@0: // The maximum bytecode length the caller may have, michael@0: // before we stop inlining large functions in that caller. michael@0: uint32_t inliningMaxCallerBytecodeLength_; michael@0: michael@0: // The maximum inlining depth. michael@0: uint32_t maxInlineDepth_; michael@0: michael@0: // The maximum inlining depth for functions. michael@0: // michael@0: // Inlining small functions has almost no compiling overhead michael@0: // and removes the otherwise needed call overhead. michael@0: // The value is currently very low. michael@0: // Actually it is only needed to make sure we don't blow out the stack. michael@0: uint32_t smallFunctionMaxInlineDepth_; michael@0: michael@0: // How many invocations or loop iterations are needed before functions michael@0: // are compiled. michael@0: uint32_t usesBeforeCompile_; michael@0: michael@0: // How many invocations or loop iterations are needed before calls michael@0: // are inlined, as a fraction of usesBeforeCompile. michael@0: double usesBeforeInliningFactor_; michael@0: michael@0: OptimizationInfo() michael@0: { } michael@0: michael@0: void initNormalOptimizationInfo(); michael@0: void initAsmjsOptimizationInfo(); michael@0: michael@0: OptimizationLevel level() const { michael@0: return level_; michael@0: } michael@0: michael@0: bool inlineInterpreted() const { michael@0: return inlineInterpreted_ && !js_JitOptions.disableInlining; michael@0: } michael@0: michael@0: bool inlineNative() const { michael@0: return inlineNative_ && !js_JitOptions.disableInlining; michael@0: } michael@0: michael@0: uint32_t usesBeforeCompile(JSScript *script, jsbytecode *pc = nullptr) const; michael@0: michael@0: bool gvnEnabled() const { michael@0: return gvn_ && !js_JitOptions.disableGvn; michael@0: } michael@0: michael@0: bool licmEnabled() const { michael@0: return licm_ && !js_JitOptions.disableLicm; michael@0: } michael@0: michael@0: bool uceEnabled() const { michael@0: return uce_ && !js_JitOptions.disableUce; michael@0: } michael@0: michael@0: bool rangeAnalysisEnabled() const { michael@0: return rangeAnalysis_ && !js_JitOptions.disableRangeAnalysis; michael@0: } michael@0: michael@0: bool eaaEnabled() const { michael@0: return eaa_ && !js_JitOptions.disableEaa; michael@0: } michael@0: michael@0: bool edgeCaseAnalysisEnabled() const { michael@0: return edgeCaseAnalysis_ && !js_JitOptions.disableEdgeCaseAnalysis; michael@0: } michael@0: michael@0: bool eliminateRedundantChecksEnabled() const { michael@0: return eliminateRedundantChecks_; michael@0: } michael@0: michael@0: IonGvnKind gvnKind() const { michael@0: if (!js_JitOptions.forceGvnKind) michael@0: return gvnKind_; michael@0: return js_JitOptions.forcedGvnKind; michael@0: } michael@0: michael@0: IonRegisterAllocator registerAllocator() const { michael@0: if (!js_JitOptions.forceRegisterAllocator) michael@0: return registerAllocator_; michael@0: return js_JitOptions.forcedRegisterAllocator; michael@0: } michael@0: michael@0: uint32_t smallFunctionMaxInlineDepth() const { michael@0: return smallFunctionMaxInlineDepth_; michael@0: } michael@0: michael@0: bool isSmallFunction(JSScript *script) const; michael@0: michael@0: uint32_t maxInlineDepth() const { michael@0: return maxInlineDepth_; michael@0: } michael@0: michael@0: uint32_t inlineMaxTotalBytecodeLength() const { michael@0: return inlineMaxTotalBytecodeLength_; michael@0: } michael@0: michael@0: uint32_t inliningMaxCallerBytecodeLength() const { michael@0: return inlineMaxTotalBytecodeLength_; michael@0: } michael@0: michael@0: uint32_t usesBeforeInlining() const { michael@0: uint32_t usesBeforeCompile = usesBeforeCompile_; michael@0: if (js_JitOptions.forceDefaultIonUsesBeforeCompile) michael@0: usesBeforeCompile = js_JitOptions.forcedDefaultIonUsesBeforeCompile; michael@0: return usesBeforeCompile * usesBeforeInliningFactor_; michael@0: } michael@0: }; michael@0: michael@0: class OptimizationInfos michael@0: { michael@0: private: michael@0: OptimizationInfo infos_[Optimization_Count - 1]; michael@0: michael@0: public: michael@0: OptimizationInfos(); michael@0: michael@0: const OptimizationInfo *get(OptimizationLevel level) const { michael@0: JS_ASSERT(level < Optimization_Count); michael@0: JS_ASSERT(level != Optimization_DontCompile); michael@0: michael@0: return &infos_[level - 1]; michael@0: } michael@0: michael@0: OptimizationLevel nextLevel(OptimizationLevel level) const; michael@0: OptimizationLevel firstLevel() const; michael@0: bool isLastLevel(OptimizationLevel level) const; michael@0: OptimizationLevel levelForScript(JSScript *script, jsbytecode *pc = nullptr) const; michael@0: }; michael@0: michael@0: extern OptimizationInfos js_IonOptimizations; michael@0: michael@0: #endif // JS_ION michael@0: michael@0: } // namespace jit michael@0: } // namespace js michael@0: michael@0: #endif /* jit_IonOptimizationLevels_h */