#ifndef JITCode_h
#define JITCode_h
#include "ArityCheckMode.h"
#include "CallFrame.h"
#include "Disassembler.h"
#include "JITStubs.h"
#include "JSCJSValue.h"
#include "LegacyProfiler.h"
#include "MacroAssemblerCodeRef.h"
#include "RegisterPreservationMode.h"
namespace JSC {
namespace DFG {
class CommonData;
class JITCode;
}
namespace FTL {
class ForOSREntryJITCode;
class JITCode;
}
struct ProtoCallFrame;
class VM;
class JITCode : public ThreadSafeRefCounted<JITCode> {
public:
typedef MacroAssemblerCodeRef CodeRef;
typedef MacroAssemblerCodePtr CodePtr;
enum JITType : uint8_t {
None,
HostCallThunk,
InterpreterThunk,
BaselineJIT,
DFGJIT,
FTLJIT
};
static JITType bottomTierJIT()
{
return BaselineJIT;
}
static JITType topTierJIT()
{
return FTLJIT;
}
static JITType nextTierJIT(JITType jitType)
{
switch (jitType) {
case BaselineJIT:
return DFGJIT;
case DFGJIT:
return FTLJIT;
default:
RELEASE_ASSERT_NOT_REACHED();
return None;
}
}
static bool isExecutableScript(JITType jitType)
{
switch (jitType) {
case None:
case HostCallThunk:
return false;
default:
return true;
}
}
static bool couldBeInterpreted(JITType jitType)
{
switch (jitType) {
case InterpreterThunk:
case BaselineJIT:
return true;
default:
return false;
}
}
static bool isJIT(JITType jitType)
{
switch (jitType) {
case BaselineJIT:
case DFGJIT:
case FTLJIT:
return true;
default:
return false;
}
}
static bool isLowerTier(JITType expectedLower, JITType expectedHigher)
{
RELEASE_ASSERT(isExecutableScript(expectedLower));
RELEASE_ASSERT(isExecutableScript(expectedHigher));
return expectedLower < expectedHigher;
}
static bool isHigherTier(JITType expectedHigher, JITType expectedLower)
{
return isLowerTier(expectedLower, expectedHigher);
}
static bool isLowerOrSameTier(JITType expectedLower, JITType expectedHigher)
{
return !isHigherTier(expectedLower, expectedHigher);
}
static bool isHigherOrSameTier(JITType expectedHigher, JITType expectedLower)
{
return isLowerOrSameTier(expectedLower, expectedHigher);
}
static bool isOptimizingJIT(JITType jitType)
{
return jitType == DFGJIT || jitType == FTLJIT;
}
static bool isBaselineCode(JITType jitType)
{
return jitType == InterpreterThunk || jitType == BaselineJIT;
}
protected:
JITCode(JITType);
public:
virtual ~JITCode();
JITType jitType() const
{
return m_jitType;
}
template<typename PointerType>
static JITType jitTypeFor(PointerType jitCode)
{
if (!jitCode)
return None;
return jitCode->jitType();
}
virtual CodePtr addressForCall(VM&, ExecutableBase*, ArityCheckMode, RegisterPreservationMode) = 0;
virtual void* executableAddressAtOffset(size_t offset) = 0;
void* executableAddress() { return executableAddressAtOffset(0); }
virtual void* dataAddressAtOffset(size_t offset) = 0;
virtual unsigned offsetOf(void* pointerIntoCode) = 0;
virtual DFG::CommonData* dfgCommon();
virtual DFG::JITCode* dfg();
virtual FTL::JITCode* ftl();
virtual FTL::ForOSREntryJITCode* ftlForOSREntry();
JSValue execute(VM*, ProtoCallFrame*);
void* start() { return dataAddressAtOffset(0); }
virtual size_t size() = 0;
void* end() { return reinterpret_cast<void*>(reinterpret_cast<uintptr_t>(start()) + size()); }
virtual bool contains(void*) = 0;
private:
JITType m_jitType;
};
class JITCodeWithCodeRef : public JITCode {
protected:
JITCodeWithCodeRef(JITType);
JITCodeWithCodeRef(CodeRef, JITType);
public:
virtual ~JITCodeWithCodeRef();
virtual void* executableAddressAtOffset(size_t offset) override;
virtual void* dataAddressAtOffset(size_t offset) override;
virtual unsigned offsetOf(void* pointerIntoCode) override;
virtual size_t size() override;
virtual bool contains(void*) override;
protected:
CodeRef m_ref;
};
class DirectJITCode : public JITCodeWithCodeRef {
public:
DirectJITCode(JITType);
DirectJITCode(CodeRef, CodePtr withArityCheck, JITType);
virtual ~DirectJITCode();
void initializeCodeRef(CodeRef, CodePtr withArityCheck);
virtual CodePtr addressForCall(VM&, ExecutableBase*, ArityCheckMode, RegisterPreservationMode) override;
private:
struct RegisterPreservationWrappers {
CodeRef withoutArityCheck;
CodeRef withArityCheck;
};
RegisterPreservationWrappers* ensureWrappers();
CodePtr m_withArityCheck;
std::unique_ptr<RegisterPreservationWrappers> m_wrappers;
};
class NativeJITCode : public JITCodeWithCodeRef {
public:
NativeJITCode(JITType);
NativeJITCode(CodeRef, JITType);
virtual ~NativeJITCode();
void initializeCodeRef(CodeRef);
virtual CodePtr addressForCall(VM&, ExecutableBase*, ArityCheckMode, RegisterPreservationMode) override;
};
}
namespace WTF {
class PrintStream;
void printInternal(PrintStream&, JSC::JITCode::JITType);
}
#endif