#ifndef jit_Ion_h
#define jit_Ion_h
#include "mozilla/MemoryReporting.h"
#include "mozilla/Result.h"
#include "jit/CompileWrappers.h"
#include "jit/JitOptions.h"
#include "vm/JSContext.h"
#include "vm/Realm.h"
namespace js {
namespace jit {
class TempAllocator;
enum MethodStatus {
Method_Error,
Method_CantCompile,
Method_Skipped,
Method_Compiled
};
enum class AbortReason : uint8_t {
Alloc,
Inlining,
PreliminaryObjects,
Disable,
Error,
NoAbort
};
template <typename V>
using AbortReasonOr = mozilla::Result<V, AbortReason>;
using mozilla::Err;
using mozilla::Ok;
static_assert(sizeof(AbortReasonOr<Ok>) <= sizeof(uintptr_t),
"Unexpected size of AbortReasonOr<Ok>");
static_assert(sizeof(AbortReasonOr<bool>) <= sizeof(uintptr_t),
"Unexpected size of AbortReasonOr<bool>");
class JitContext {
public:
JitContext(JSContext* cx, TempAllocator* temp);
JitContext(CompileRuntime* rt, CompileRealm* realm, TempAllocator* temp);
explicit JitContext(TempAllocator* temp);
JitContext();
~JitContext();
JSContext* cx;
TempAllocator* temp;
CompileRuntime* runtime;
int getNextAssemblerId() { return assemblerCount_++; }
CompileRealm* maybeRealm() const { return realm_; }
CompileRealm* realm() const {
MOZ_ASSERT(maybeRealm());
return maybeRealm();
}
#ifdef DEBUG
bool isCompilingWasm() { return isCompilingWasm_; }
#endif
private:
JitContext* prev_;
CompileRealm* realm_;
#ifdef DEBUG
bool isCompilingWasm_;
#endif
int assemblerCount_;
};
MOZ_MUST_USE bool InitializeIon();
JitContext* GetJitContext();
JitContext* MaybeGetJitContext();
void SetJitContext(JitContext* ctx);
bool CanIonCompileScript(JSContext* cx, JSScript* script);
bool CanIonInlineScript(JSScript* script);
MOZ_MUST_USE bool IonCompileScriptForBaseline(JSContext* cx,
BaselineFrame* frame,
jsbytecode* pc);
MethodStatus CanEnterIon(JSContext* cx, RunState& state);
MethodStatus Recompile(JSContext* cx, HandleScript script,
BaselineFrame* osrFrame, jsbytecode* osrPc, bool force);
enum JitExecStatus {
JitExec_Aborted,
JitExec_Error,
JitExec_Ok
};
static inline bool IsErrorStatus(JitExecStatus status) {
return status == JitExec_Error || status == JitExec_Aborted;
}
struct EnterJitData;
void Invalidate(TypeZone& types, FreeOp* fop,
const RecompileInfoVector& invalid, bool resetUses = true,
bool cancelOffThread = true);
void Invalidate(JSContext* cx, const RecompileInfoVector& invalid,
bool resetUses = true, bool cancelOffThread = true);
void Invalidate(JSContext* cx, JSScript* script, bool resetUses = true,
bool cancelOffThread = true);
class IonBuilder;
class MIRGenerator;
class LIRGraph;
class CodeGenerator;
class LazyLinkExitFrameLayout;
MOZ_MUST_USE bool OptimizeMIR(MIRGenerator* mir);
LIRGraph* GenerateLIR(MIRGenerator* mir);
CodeGenerator* GenerateCode(MIRGenerator* mir, LIRGraph* lir);
CodeGenerator* CompileBackEnd(MIRGenerator* mir);
void AttachFinishedCompilations(JSContext* cx);
void FinishOffThreadBuilder(JSRuntime* runtime, IonBuilder* builder,
const AutoLockHelperThreadState& lock);
void FreeIonBuilder(IonBuilder* builder);
void LinkIonScript(JSContext* cx, HandleScript calleescript);
uint8_t* LazyLinkTopActivation(JSContext* cx, LazyLinkExitFrameLayout* frame);
static inline bool IsIonEnabled(JSContext* cx) {
#if defined(JS_CODEGEN_NONE)
return false;
#else
return cx->options().ion() && cx->options().baseline() &&
cx->runtime()->jitSupportsFloatingPoint;
#endif
}
inline bool IsIonInlinableGetterOrSetterPC(jsbytecode* pc) {
return IsGetPropPC(pc) || IsGetElemPC(pc) || IsSetPropPC(pc);
}
inline bool IsIonInlinablePC(jsbytecode* pc) {
return (IsCallPC(pc) && !IsSpreadCallPC(pc)) ||
IsIonInlinableGetterOrSetterPC(pc);
}
inline bool TooManyActualArguments(unsigned nargs) {
return nargs > JitOptions.maxStackArgs;
}
inline bool TooManyFormalArguments(unsigned nargs) {
return nargs >= SNAPSHOT_MAX_NARGS || TooManyActualArguments(nargs);
}
inline size_t NumLocalsAndArgs(JSScript* script) {
size_t num = 1 + script->nfixed();
if (JSFunction* fun = script->functionNonDelazifying()) {
num += fun->nargs();
}
return num;
}
bool OffThreadCompilationAvailable(JSContext* cx);
void ForbidCompilation(JSContext* cx, JSScript* script);
size_t SizeOfIonData(JSScript* script, mozilla::MallocSizeOf mallocSizeOf);
void DestroyJitScripts(FreeOp* fop, JSScript* script);
void TraceJitScripts(JSTracer* trc, JSScript* script);
bool JitSupportsFloatingPoint();
bool JitSupportsUnalignedAccesses();
bool JitSupportsSimd();
bool JitSupportsAtomics();
} }
#endif