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_Ion_h michael@0: #define jit_Ion_h michael@0: michael@0: #ifdef JS_ION michael@0: michael@0: #include "mozilla/MemoryReporting.h" michael@0: michael@0: #include "jscntxt.h" michael@0: #include "jscompartment.h" michael@0: michael@0: #include "jit/CompileInfo.h" michael@0: #include "jit/CompileWrappers.h" michael@0: #include "jit/JitOptions.h" michael@0: michael@0: namespace js { michael@0: namespace jit { michael@0: michael@0: class TempAllocator; michael@0: michael@0: enum MethodStatus michael@0: { michael@0: Method_Error, michael@0: Method_CantCompile, michael@0: Method_Skipped, michael@0: Method_Compiled michael@0: }; michael@0: michael@0: enum AbortReason { michael@0: AbortReason_Alloc, michael@0: AbortReason_Inlining, michael@0: AbortReason_Disable, michael@0: AbortReason_Error, michael@0: AbortReason_NoAbort michael@0: }; michael@0: michael@0: // An Ion context is needed to enter into either an Ion method or an instance michael@0: // of the Ion compiler. It points to a temporary allocator and the active michael@0: // JSContext, either of which may be nullptr, and the active compartment, which michael@0: // will not be nullptr. michael@0: michael@0: class IonContext michael@0: { michael@0: public: michael@0: IonContext(JSContext *cx, TempAllocator *temp); michael@0: IonContext(ExclusiveContext *cx, TempAllocator *temp); michael@0: IonContext(CompileRuntime *rt, CompileCompartment *comp, TempAllocator *temp); michael@0: IonContext(CompileRuntime *rt); michael@0: ~IonContext(); michael@0: michael@0: // Running context when executing on the main thread. Not available during michael@0: // compilation. michael@0: JSContext *cx; michael@0: michael@0: // Allocator for temporary memory during compilation. michael@0: TempAllocator *temp; michael@0: michael@0: // Wrappers with information about the current runtime/compartment for use michael@0: // during compilation. michael@0: CompileRuntime *runtime; michael@0: CompileCompartment *compartment; michael@0: michael@0: int getNextAssemblerId() { michael@0: return assemblerCount_++; michael@0: } michael@0: private: michael@0: IonContext *prev_; michael@0: int assemblerCount_; michael@0: }; michael@0: michael@0: // Initialize Ion statically for all JSRuntimes. michael@0: bool InitializeIon(); michael@0: michael@0: // Get and set the current Ion context. michael@0: IonContext *GetIonContext(); michael@0: IonContext *MaybeGetIonContext(); michael@0: michael@0: void SetIonContext(IonContext *ctx); michael@0: michael@0: bool CanIonCompileScript(JSContext *cx, JSScript *script, bool osr); michael@0: michael@0: MethodStatus CanEnterAtBranch(JSContext *cx, JSScript *script, michael@0: BaselineFrame *frame, jsbytecode *pc, bool isConstructing); michael@0: MethodStatus CanEnter(JSContext *cx, RunState &state); michael@0: MethodStatus CompileFunctionForBaseline(JSContext *cx, HandleScript script, BaselineFrame *frame, michael@0: bool isConstructing); michael@0: MethodStatus CanEnterUsingFastInvoke(JSContext *cx, HandleScript script, uint32_t numActualArgs); michael@0: michael@0: MethodStatus CanEnterInParallel(JSContext *cx, HandleScript script); michael@0: michael@0: MethodStatus michael@0: Recompile(JSContext *cx, HandleScript script, BaselineFrame *osrFrame, jsbytecode *osrPc, michael@0: bool constructing); michael@0: michael@0: enum IonExecStatus michael@0: { michael@0: // The method call had to be aborted due to a stack limit check. This michael@0: // error indicates that Ion never attempted to clean up frames. michael@0: IonExec_Aborted, michael@0: michael@0: // The method call resulted in an error, and IonMonkey has cleaned up michael@0: // frames. michael@0: IonExec_Error, michael@0: michael@0: // The method call succeeed and returned a value. michael@0: IonExec_Ok michael@0: }; michael@0: michael@0: static inline bool michael@0: IsErrorStatus(IonExecStatus status) michael@0: { michael@0: return status == IonExec_Error || status == IonExec_Aborted; michael@0: } michael@0: michael@0: struct EnterJitData; michael@0: michael@0: bool SetEnterJitData(JSContext *cx, EnterJitData &data, RunState &state, AutoValueVector &vals); michael@0: michael@0: IonExecStatus IonCannon(JSContext *cx, RunState &state); michael@0: michael@0: // Used to enter Ion from C++ natives like Array.map. Called from FastInvokeGuard. michael@0: IonExecStatus FastInvoke(JSContext *cx, HandleFunction fun, CallArgs &args); michael@0: michael@0: // Walk the stack and invalidate active Ion frames for the invalid scripts. michael@0: void Invalidate(types::TypeZone &types, FreeOp *fop, michael@0: const Vector &invalid, bool resetUses = true, michael@0: bool cancelOffThread = true); michael@0: void Invalidate(JSContext *cx, const Vector &invalid, bool resetUses = true, michael@0: bool cancelOffThread = true); michael@0: bool Invalidate(JSContext *cx, JSScript *script, ExecutionMode mode, bool resetUses = true, michael@0: bool cancelOffThread = true); michael@0: bool Invalidate(JSContext *cx, JSScript *script, bool resetUses = true, michael@0: bool cancelOffThread = true); michael@0: michael@0: void MarkValueFromIon(JSRuntime *rt, Value *vp); michael@0: void MarkShapeFromIon(JSRuntime *rt, Shape **shapep); michael@0: michael@0: void ToggleBarriers(JS::Zone *zone, bool needs); michael@0: michael@0: class IonBuilder; michael@0: class MIRGenerator; michael@0: class LIRGraph; michael@0: class CodeGenerator; michael@0: michael@0: bool OptimizeMIR(MIRGenerator *mir); michael@0: LIRGraph *GenerateLIR(MIRGenerator *mir); michael@0: CodeGenerator *GenerateCode(MIRGenerator *mir, LIRGraph *lir); michael@0: CodeGenerator *CompileBackEnd(MIRGenerator *mir); michael@0: michael@0: void AttachFinishedCompilations(JSContext *cx); michael@0: void FinishOffThreadBuilder(IonBuilder *builder); michael@0: void StopAllOffThreadCompilations(JSCompartment *comp); michael@0: michael@0: static inline bool michael@0: IsIonEnabled(JSContext *cx) michael@0: { michael@0: return cx->runtime()->options().ion() && michael@0: cx->runtime()->options().baseline() && michael@0: cx->runtime()->jitSupportsFloatingPoint; michael@0: } michael@0: michael@0: inline bool michael@0: IsIonInlinablePC(jsbytecode *pc) { michael@0: // CALL, FUNCALL, FUNAPPLY, EVAL, NEW (Normal Callsites) michael@0: // GETPROP, CALLPROP, and LENGTH. (Inlined Getters) michael@0: // SETPROP, SETNAME, SETGNAME (Inlined Setters) michael@0: return IsCallPC(pc) || IsGetPropPC(pc) || IsSetPropPC(pc); michael@0: } michael@0: michael@0: inline bool michael@0: TooManyArguments(unsigned nargs) michael@0: { michael@0: return nargs >= SNAPSHOT_MAX_NARGS || nargs > js_JitOptions.maxStackArgs; michael@0: } michael@0: michael@0: void ForbidCompilation(JSContext *cx, JSScript *script); michael@0: void ForbidCompilation(JSContext *cx, JSScript *script, ExecutionMode mode); michael@0: michael@0: void PurgeCaches(JSScript *script); michael@0: size_t SizeOfIonData(JSScript *script, mozilla::MallocSizeOf mallocSizeOf); michael@0: void DestroyIonScripts(FreeOp *fop, JSScript *script); michael@0: void TraceIonScripts(JSTracer* trc, JSScript *script); michael@0: michael@0: void RequestInterruptForIonCode(JSRuntime *rt, JSRuntime::InterruptMode mode); michael@0: michael@0: bool RematerializeAllFrames(JSContext *cx, JSCompartment *comp); michael@0: bool UpdateForDebugMode(JSContext *maybecx, JSCompartment *comp, michael@0: AutoDebugModeInvalidation &invalidate); michael@0: michael@0: } // namespace jit michael@0: } // namespace js michael@0: michael@0: #endif // JS_ION michael@0: michael@0: #endif /* jit_Ion_h */