зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1125481 - Replace FunctionInfo macros by variadic templates. r=Waldo
This commit is contained in:
Родитель
b99a5d8da0
Коммит
158182d776
|
@ -7,6 +7,8 @@
|
|||
#ifndef jit_VMFunctions_h
|
||||
#define jit_VMFunctions_h
|
||||
|
||||
#include "mozilla/Attributes.h"
|
||||
|
||||
#include "jspubtd.h"
|
||||
|
||||
#include "jit/CompileInfo.h"
|
||||
|
@ -440,176 +442,114 @@ template <> struct MatchContext<ExclusiveContext*> {
|
|||
static const bool valid = true;
|
||||
};
|
||||
|
||||
#define FOR_EACH_ARGS_1(Macro, Sep, Last) Macro(1) Last(1)
|
||||
#define FOR_EACH_ARGS_2(Macro, Sep, Last) FOR_EACH_ARGS_1(Macro, Sep, Sep) Macro(2) Last(2)
|
||||
#define FOR_EACH_ARGS_3(Macro, Sep, Last) FOR_EACH_ARGS_2(Macro, Sep, Sep) Macro(3) Last(3)
|
||||
#define FOR_EACH_ARGS_4(Macro, Sep, Last) FOR_EACH_ARGS_3(Macro, Sep, Sep) Macro(4) Last(4)
|
||||
#define FOR_EACH_ARGS_5(Macro, Sep, Last) FOR_EACH_ARGS_4(Macro, Sep, Sep) Macro(5) Last(5)
|
||||
#define FOR_EACH_ARGS_6(Macro, Sep, Last) FOR_EACH_ARGS_5(Macro, Sep, Sep) Macro(6) Last(6)
|
||||
#define FOR_EACH_ARGS_7(Macro, Sep, Last) FOR_EACH_ARGS_6(Macro, Sep, Sep) Macro(7) Last(7)
|
||||
// Extract the last element of a list of types.
|
||||
template <typename... ArgTypes>
|
||||
struct LastArg;
|
||||
|
||||
#define COMPUTE_INDEX(NbArg) NbArg
|
||||
#define COMPUTE_OUTPARAM_RESULT(NbArg) OutParamToDataType<A ## NbArg>::result
|
||||
#define COMPUTE_OUTPARAM_ROOT(NbArg) OutParamToRootType<A ## NbArg>::result
|
||||
#define COMPUTE_ARG_PROP(NbArg) (TypeToArgProperties<A ## NbArg>::result << (2 * (NbArg - 1)))
|
||||
#define COMPUTE_ARG_ROOT(NbArg) (uint64_t(TypeToRootType<A ## NbArg>::result) << (3 * (NbArg - 1)))
|
||||
#define COMPUTE_ARG_FLOAT(NbArg) (TypeToPassInFloatReg<A ## NbArg>::result) << (NbArg - 1)
|
||||
#define SEP_OR(_) |
|
||||
#define NOTHING(_)
|
||||
|
||||
#define FUNCTION_INFO_STRUCT_BODY(ForEachNb) \
|
||||
static inline DataType returnType() { \
|
||||
return TypeToDataType<R>::result; \
|
||||
} \
|
||||
static inline DataType outParam() { \
|
||||
return ForEachNb(NOTHING, NOTHING, COMPUTE_OUTPARAM_RESULT); \
|
||||
} \
|
||||
static inline RootType outParamRootType() { \
|
||||
return ForEachNb(NOTHING, NOTHING, COMPUTE_OUTPARAM_ROOT); \
|
||||
} \
|
||||
static inline size_t NbArgs() { \
|
||||
return ForEachNb(NOTHING, NOTHING, COMPUTE_INDEX); \
|
||||
} \
|
||||
static inline size_t explicitArgs() { \
|
||||
return NbArgs() - (outParam() != Type_Void ? 1 : 0); \
|
||||
} \
|
||||
static inline uint32_t argumentProperties() { \
|
||||
return ForEachNb(COMPUTE_ARG_PROP, SEP_OR, NOTHING); \
|
||||
} \
|
||||
static inline uint32_t argumentPassedInFloatRegs() { \
|
||||
return ForEachNb(COMPUTE_ARG_FLOAT, SEP_OR, NOTHING); \
|
||||
} \
|
||||
static inline uint64_t argumentRootTypes() { \
|
||||
return ForEachNb(COMPUTE_ARG_ROOT, SEP_OR, NOTHING); \
|
||||
} \
|
||||
explicit FunctionInfo(pf fun, MaybeTailCall expectTailCall, \
|
||||
PopValues extraValuesToPop = PopValues(0)) \
|
||||
: VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), explicitArgs(), \
|
||||
argumentProperties(), argumentPassedInFloatRegs(), \
|
||||
argumentRootTypes(), outParam(), outParamRootType(), \
|
||||
returnType(), extraValuesToPop.numValues, expectTailCall) \
|
||||
{ \
|
||||
static_assert(MatchContext<Context>::valid, "Invalid cx type in VMFunction"); \
|
||||
} \
|
||||
explicit FunctionInfo(pf fun, PopValues extraValuesToPop = PopValues(0)) \
|
||||
: VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), explicitArgs(), \
|
||||
argumentProperties(), argumentPassedInFloatRegs(), \
|
||||
argumentRootTypes(), outParam(), outParamRootType(), \
|
||||
returnType(), extraValuesToPop.numValues, NonTailCall) \
|
||||
{ \
|
||||
static_assert(MatchContext<Context>::valid, "Invalid cx type in VMFunction"); \
|
||||
}
|
||||
|
||||
template <typename Fun>
|
||||
struct FunctionInfo {
|
||||
template <>
|
||||
struct LastArg<>
|
||||
{
|
||||
typedef void Type;
|
||||
static MOZ_CONSTEXPR_VAR size_t nbArgs = 0;
|
||||
};
|
||||
|
||||
// VMFunction wrapper with no explicit arguments.
|
||||
template <class R, class Context>
|
||||
struct FunctionInfo<R (*)(Context)> : public VMFunction {
|
||||
typedef R (*pf)(Context);
|
||||
template <typename HeadType>
|
||||
struct LastArg<HeadType>
|
||||
{
|
||||
typedef HeadType Type;
|
||||
static MOZ_CONSTEXPR_VAR size_t nbArgs = 1;
|
||||
};
|
||||
|
||||
template <typename HeadType, typename... TailTypes>
|
||||
struct LastArg<HeadType, TailTypes...>
|
||||
{
|
||||
typedef typename LastArg<TailTypes...>::Type Type;
|
||||
static MOZ_CONSTEXPR_VAR size_t nbArgs = LastArg<TailTypes...>::nbArgs + 1;
|
||||
};
|
||||
|
||||
// Construct a bit mask from a list of types. The mask is constructed as an OR
|
||||
// of the mask produced for each argument. The result of each argument is
|
||||
// shifted by its index, such that the result of the first argument is on the
|
||||
// low bits of the mask, and the result of the last argument in part of the
|
||||
// high bits of the mask.
|
||||
template <template<typename> class Each, typename ResultType, size_t Shift,
|
||||
typename... Args>
|
||||
struct BitMask;
|
||||
|
||||
template <template<typename> class Each, typename ResultType, size_t Shift>
|
||||
struct BitMask<Each, ResultType, Shift>
|
||||
{
|
||||
static MOZ_CONSTEXPR_VAR ResultType result = ResultType();
|
||||
};
|
||||
|
||||
template <template<typename> class Each, typename ResultType, size_t Shift,
|
||||
typename HeadType, typename... TailTypes>
|
||||
struct BitMask<Each, ResultType, Shift, HeadType, TailTypes...>
|
||||
{
|
||||
static_assert(ResultType(Each<HeadType>::result) < (1 << Shift),
|
||||
"not enough bits reserved by the shift for individual results");
|
||||
static_assert(LastArg<TailTypes...>::nbArgs < (8 * sizeof(ResultType) / Shift),
|
||||
"not enough bits in the result type to store all bit masks");
|
||||
|
||||
static MOZ_CONSTEXPR_VAR ResultType result =
|
||||
ResultType(Each<HeadType>::result) |
|
||||
(BitMask<Each, ResultType, Shift, TailTypes...>::result << Shift);
|
||||
};
|
||||
|
||||
// Extract VMFunction properties based on the signature of the function. The
|
||||
// properties are used to generate the logic for calling the VM function, and
|
||||
// also for marking the stack during GCs.
|
||||
template <typename... Args>
|
||||
struct FunctionInfo;
|
||||
|
||||
template <class R, class Context, typename... Args>
|
||||
struct FunctionInfo<R (*)(Context, Args...)> : public VMFunction
|
||||
{
|
||||
typedef R (*pf)(Context, Args...);
|
||||
|
||||
static inline DataType returnType() {
|
||||
return TypeToDataType<R>::result;
|
||||
}
|
||||
static inline DataType outParam() {
|
||||
return Type_Void;
|
||||
return OutParamToDataType<typename LastArg<Args...>::Type>::result;
|
||||
}
|
||||
static inline RootType outParamRootType() {
|
||||
return RootNone;
|
||||
return OutParamToRootType<typename LastArg<Args...>::Type>::result;
|
||||
}
|
||||
static inline size_t NbArgs() {
|
||||
return LastArg<Args...>::nbArgs;
|
||||
}
|
||||
static inline size_t explicitArgs() {
|
||||
return 0;
|
||||
return NbArgs() - (outParam() != Type_Void ? 1 : 0);
|
||||
}
|
||||
static inline uint32_t argumentProperties() {
|
||||
return 0;
|
||||
return BitMask<TypeToArgProperties, uint32_t, 2, Args...>::result;
|
||||
}
|
||||
static inline uint32_t argumentPassedInFloatRegs() {
|
||||
return 0;
|
||||
return BitMask<TypeToPassInFloatReg, uint32_t, 2, Args...>::result;
|
||||
}
|
||||
static inline uint64_t argumentRootTypes() {
|
||||
return 0;
|
||||
return BitMask<TypeToRootType, uint64_t, 3, Args...>::result;
|
||||
}
|
||||
explicit FunctionInfo(pf fun)
|
||||
: VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), explicitArgs(),
|
||||
argumentProperties(), argumentPassedInFloatRegs(),
|
||||
argumentRootTypes(), outParam(), outParamRootType(),
|
||||
returnType(), 0, NonTailCall)
|
||||
explicit FunctionInfo(pf fun, PopValues extraValuesToPop = PopValues(0))
|
||||
: VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), explicitArgs(),
|
||||
argumentProperties(), argumentPassedInFloatRegs(),
|
||||
argumentRootTypes(), outParam(), outParamRootType(),
|
||||
returnType(), extraValuesToPop.numValues, NonTailCall)
|
||||
{
|
||||
static_assert(MatchContext<Context>::valid, "Invalid cx type in VMFunction");
|
||||
}
|
||||
explicit FunctionInfo(pf fun, MaybeTailCall expectTailCall)
|
||||
: VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), explicitArgs(),
|
||||
argumentProperties(), argumentPassedInFloatRegs(),
|
||||
argumentRootTypes(), outParam(), outParamRootType(),
|
||||
returnType(), expectTailCall)
|
||||
explicit FunctionInfo(pf fun, MaybeTailCall expectTailCall,
|
||||
PopValues extraValuesToPop = PopValues(0))
|
||||
: VMFunction(JS_FUNC_TO_DATA_PTR(void*, fun), explicitArgs(),
|
||||
argumentProperties(), argumentPassedInFloatRegs(),
|
||||
argumentRootTypes(), outParam(), outParamRootType(),
|
||||
returnType(), extraValuesToPop.numValues, expectTailCall)
|
||||
{
|
||||
static_assert(MatchContext<Context>::valid, "Invalid cx type in VMFunction");
|
||||
}
|
||||
};
|
||||
|
||||
// Specialize the class for each number of argument used by VMFunction.
|
||||
// Keep it verbose unless you find a readable macro for it.
|
||||
template <class R, class Context, class A1>
|
||||
struct FunctionInfo<R (*)(Context, A1)> : public VMFunction {
|
||||
typedef R (*pf)(Context, A1);
|
||||
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_1)
|
||||
};
|
||||
|
||||
template <class R, class Context, class A1, class A2>
|
||||
struct FunctionInfo<R (*)(Context, A1, A2)> : public VMFunction {
|
||||
typedef R (*pf)(Context, A1, A2);
|
||||
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_2)
|
||||
};
|
||||
|
||||
template <class R, class Context, class A1, class A2, class A3>
|
||||
struct FunctionInfo<R (*)(Context, A1, A2, A3)> : public VMFunction {
|
||||
typedef R (*pf)(Context, A1, A2, A3);
|
||||
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_3)
|
||||
};
|
||||
|
||||
template <class R, class Context, class A1, class A2, class A3, class A4>
|
||||
struct FunctionInfo<R (*)(Context, A1, A2, A3, A4)> : public VMFunction {
|
||||
typedef R (*pf)(Context, A1, A2, A3, A4);
|
||||
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_4)
|
||||
};
|
||||
|
||||
template <class R, class Context, class A1, class A2, class A3, class A4, class A5>
|
||||
struct FunctionInfo<R (*)(Context, A1, A2, A3, A4, A5)> : public VMFunction {
|
||||
typedef R (*pf)(Context, A1, A2, A3, A4, A5);
|
||||
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_5)
|
||||
};
|
||||
|
||||
template <class R, class Context, class A1, class A2, class A3, class A4, class A5, class A6>
|
||||
struct FunctionInfo<R (*)(Context, A1, A2, A3, A4, A5, A6)> : public VMFunction {
|
||||
typedef R (*pf)(Context, A1, A2, A3, A4, A5, A6);
|
||||
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_6)
|
||||
};
|
||||
|
||||
template <class R, class Context, class A1, class A2, class A3, class A4, class A5, class A6, class A7>
|
||||
struct FunctionInfo<R (*)(Context, A1, A2, A3, A4, A5, A6, A7)> : public VMFunction {
|
||||
typedef R (*pf)(Context, A1, A2, A3, A4, A5, A6, A7);
|
||||
FUNCTION_INFO_STRUCT_BODY(FOR_EACH_ARGS_7)
|
||||
};
|
||||
|
||||
#undef FUNCTION_INFO_STRUCT_BODY
|
||||
|
||||
#undef FOR_EACH_ARGS_7
|
||||
#undef FOR_EACH_ARGS_6
|
||||
#undef FOR_EACH_ARGS_5
|
||||
#undef FOR_EACH_ARGS_4
|
||||
#undef FOR_EACH_ARGS_3
|
||||
#undef FOR_EACH_ARGS_2
|
||||
#undef FOR_EACH_ARGS_1
|
||||
|
||||
#undef COMPUTE_INDEX
|
||||
#undef COMPUTE_OUTPARAM_RESULT
|
||||
#undef COMPUTE_OUTPARAM_ROOT
|
||||
#undef COMPUTE_ARG_PROP
|
||||
#undef COMPUTE_ARG_FLOAT
|
||||
#undef SEP_OR
|
||||
#undef NOTHING
|
||||
|
||||
class AutoDetectInvalidation
|
||||
{
|
||||
JSContext* cx_;
|
||||
|
|
Загрузка…
Ссылка в новой задаче