Bug 1125481 - Replace FunctionInfo macros by variadic templates. r=Waldo

This commit is contained in:
Nicolas B. Pierron 2015-06-11 13:32:24 +02:00
Родитель b99a5d8da0
Коммит 158182d776
1 изменённых файлов: 83 добавлений и 143 удалений

Просмотреть файл

@ -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_;