221 lines
6.3 KiB
C++
221 lines
6.3 KiB
C++
/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 4 -*-
|
|
* 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_Ion_h
|
|
#define jit_Ion_h
|
|
|
|
#include "mozilla/MemoryReporting.h"
|
|
|
|
#include "jscntxt.h"
|
|
#include "jscompartment.h"
|
|
|
|
#include "jit/CompileWrappers.h"
|
|
#include "jit/JitOptions.h"
|
|
|
|
namespace js {
|
|
namespace jit {
|
|
|
|
class TempAllocator;
|
|
|
|
enum MethodStatus
|
|
{
|
|
Method_Error,
|
|
Method_CantCompile,
|
|
Method_Skipped,
|
|
Method_Compiled
|
|
};
|
|
|
|
enum AbortReason {
|
|
AbortReason_Alloc,
|
|
AbortReason_Inlining,
|
|
AbortReason_PreliminaryObjects,
|
|
AbortReason_Disable,
|
|
AbortReason_Error,
|
|
AbortReason_NoAbort
|
|
};
|
|
|
|
// A JIT context is needed to enter into either an JIT method or an instance
|
|
// of a JIT compiler. It points to a temporary allocator and the active
|
|
// JSContext, either of which may be nullptr, and the active compartment, which
|
|
// will not be nullptr.
|
|
|
|
class JitContext
|
|
{
|
|
public:
|
|
JitContext(JSContext* cx, TempAllocator* temp);
|
|
JitContext(ExclusiveContext* cx, TempAllocator* temp);
|
|
JitContext(CompileRuntime* rt, CompileCompartment* comp, TempAllocator* temp);
|
|
JitContext(CompileRuntime* rt, TempAllocator* temp);
|
|
explicit JitContext(CompileRuntime* rt);
|
|
explicit JitContext(TempAllocator* temp);
|
|
JitContext();
|
|
~JitContext();
|
|
|
|
// Running context when executing on the main thread. Not available during
|
|
// compilation.
|
|
JSContext* cx;
|
|
|
|
// Allocator for temporary memory during compilation.
|
|
TempAllocator* temp;
|
|
|
|
// Wrappers with information about the current runtime/compartment for use
|
|
// during compilation.
|
|
CompileRuntime* runtime;
|
|
CompileCompartment* compartment;
|
|
|
|
bool onMainThread() const {
|
|
return runtime && runtime->onMainThread();
|
|
}
|
|
bool hasProfilingScripts() const {
|
|
return runtime && !!runtime->profilingScripts();
|
|
}
|
|
|
|
int getNextAssemblerId() {
|
|
return assemblerCount_++;
|
|
}
|
|
private:
|
|
JitContext* prev_;
|
|
int assemblerCount_;
|
|
};
|
|
|
|
// Initialize Ion statically for all JSRuntimes.
|
|
MOZ_MUST_USE bool InitializeIon();
|
|
|
|
// Get and set the current JIT context.
|
|
JitContext* GetJitContext();
|
|
JitContext* MaybeGetJitContext();
|
|
|
|
void SetJitContext(JitContext* ctx);
|
|
|
|
bool CanIonCompileScript(JSContext* cx, JSScript* script, bool osr);
|
|
|
|
MOZ_MUST_USE bool IonCompileScriptForBaseline(JSContext* cx, BaselineFrame* frame, jsbytecode* pc);
|
|
|
|
MethodStatus CanEnter(JSContext* cx, RunState& state);
|
|
MethodStatus CanEnterUsingFastInvoke(JSContext* cx, HandleScript script, uint32_t numActualArgs);
|
|
|
|
MethodStatus
|
|
Recompile(JSContext* cx, HandleScript script, BaselineFrame* osrFrame, jsbytecode* osrPc,
|
|
bool force);
|
|
|
|
enum JitExecStatus
|
|
{
|
|
// The method call had to be aborted due to a stack limit check. This
|
|
// error indicates that Ion never attempted to clean up frames.
|
|
JitExec_Aborted,
|
|
|
|
// The method call resulted in an error, and IonMonkey has cleaned up
|
|
// frames.
|
|
JitExec_Error,
|
|
|
|
// The method call succeeded and returned a value.
|
|
JitExec_Ok
|
|
};
|
|
|
|
static inline bool
|
|
IsErrorStatus(JitExecStatus status)
|
|
{
|
|
return status == JitExec_Error || status == JitExec_Aborted;
|
|
}
|
|
|
|
struct EnterJitData;
|
|
|
|
MOZ_MUST_USE bool SetEnterJitData(JSContext* cx, EnterJitData& data, RunState& state,
|
|
MutableHandle<GCVector<Value>> vals);
|
|
|
|
JitExecStatus IonCannon(JSContext* cx, RunState& state);
|
|
|
|
// Used to enter Ion from C++ natives like Array.map. Called from FastInvokeGuard.
|
|
JitExecStatus FastInvoke(JSContext* cx, HandleFunction fun, CallArgs& args);
|
|
|
|
// Walk the stack and invalidate active Ion frames for the invalid scripts.
|
|
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);
|
|
|
|
void ToggleBarriers(JS::Zone* zone, bool needs);
|
|
|
|
class IonBuilder;
|
|
class MIRGenerator;
|
|
class LIRGraph;
|
|
class CodeGenerator;
|
|
|
|
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 LinkIonScript(JSContext* cx, HandleScript calleescript);
|
|
uint8_t* LazyLinkTopActivation(JSContext* cx);
|
|
|
|
static inline bool
|
|
IsIonEnabled(JSContext* cx)
|
|
{
|
|
// The ARM64 Ion engine is not yet implemented.
|
|
#if defined(JS_CODEGEN_NONE) || defined(JS_CODEGEN_ARM64)
|
|
return false;
|
|
#else
|
|
return cx->options().ion() &&
|
|
cx->options().baseline() &&
|
|
cx->runtime()->jitSupportsFloatingPoint;
|
|
#endif
|
|
}
|
|
|
|
inline bool
|
|
IsIonInlinablePC(jsbytecode* pc) {
|
|
// CALL, FUNCALL, FUNAPPLY, EVAL, NEW (Normal Callsites)
|
|
// GETPROP, CALLPROP, and LENGTH. (Inlined Getters)
|
|
// SETPROP, SETNAME, SETGNAME (Inlined Setters)
|
|
return IsCallPC(pc) || IsGetPropPC(pc) || IsSetPropPC(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 /* this */ + script->nfixed();
|
|
if (JSFunction* fun = script->functionNonDelazifying())
|
|
num += fun->nargs();
|
|
return num;
|
|
}
|
|
|
|
bool OffThreadCompilationAvailable(JSContext* cx);
|
|
|
|
void ForbidCompilation(JSContext* cx, JSScript* script);
|
|
|
|
void PurgeCaches(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();
|
|
|
|
} // namespace jit
|
|
} // namespace js
|
|
|
|
#endif /* jit_Ion_h */
|