Bug 1661256 part 14 - Add typed callWithABI functions calls for computed function pointer. r=jandem

Differential Revision: https://phabricator.services.mozilla.com/D91794
This commit is contained in:
Nicolas B. Pierron 2020-10-05 16:55:39 +00:00
Родитель f91e2f9be9
Коммит 091ec266a9
12 изменённых файлов: 77 добавлений и 11 удалений

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

@ -81,6 +81,10 @@ namespace jit {
#define ABIFUNCTION_AND_TYPE_LIST(_) \
_(JS::ToInt32, int32_t (*)(double))
// List of all ABI function signature which are using a computed function
// pointer instead of a statically known function pointer.
#define ABIFUNCTIONSIG_LIST(_) \
// GCC warns when the signature does not have matching attributes (for example
// MOZ_MUST_USE). Squelch this warning to avoid a GCC-only footgun.
#if MOZ_IS_GCC
@ -106,6 +110,15 @@ ABIFUNCTION_LIST(DEF_TEMPLATE)
ABIFUNCTION_AND_TYPE_LIST(DEF_TEMPLATE)
#undef DEF_TEMPLATE
// Define a known list of function signatures.
#define DEF_TEMPLATE(...) \
template <> \
struct ABIFunctionSignatureData<__VA_ARGS__> { \
static constexpr bool registered = true; \
};
ABIFUNCTIONSIG_LIST(DEF_TEMPLATE)
#undef DEF_TEMPLATE
#if MOZ_IS_GCC
# pragma GCC diagnostic pop
#endif

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

@ -34,6 +34,37 @@ struct ABIFunction {
"ABI function is not registered.");
};
template <typename Sig>
struct ABIFunctionSignatureData {
static const bool registered = false;
};
template <typename Sig>
struct ABIFunctionSignature {
void* address(Sig fun) const { return JS_FUNC_TO_DATA_PTR(void*, fun); }
// If this assertion fails, you are likely in the context of a
// `DynamicFunction<Sig>(fn)` call. This error indicates that
// ABIFunctionSignature has not been specialized for `Sig` by the time of this
// call.
//
// This can be fixed by adding the function signature to ABIFUNCTIONSIG_LIST
// within `ABIFunctionList-inl.h` and to add an `#include` statement of this
// header in the file which is making the call to `DynamicFunction<Sig>(fn)`.
static_assert(ABIFunctionSignatureData<Sig>::registered,
"ABI function signature is not registered.");
};
// This is a structure created to ensure that the dynamically computed
// function pointer is well typed.
//
// It is meant to be created only through DynamicFunction function calls. In
// extremelly rare cases, such as VMFunctions, it might be produced as a result
// of GetVMFunctionTarget.
struct DynFn {
void* address;
};
} // namespace jit
} // namespace js

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

@ -15,6 +15,7 @@
#include <utility>
#include "builtin/TypedObject.h"
#include "jit/ABIFunctions.h"
#include "jit/BaselineICList.h"
#include "jit/BaselineJIT.h"
#include "jit/CompileInfo.h"
@ -273,7 +274,7 @@ class JitRuntime {
JitCode* generateDebugTrapHandler(JSContext* cx, DebugTrapHandlerKind kind);
bool generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunctionData& f, void* nativeFun,
const VMFunctionData& f, DynFn nativeFun,
uint32_t* wrapperOffset);
template <typename IdT>

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

@ -38,6 +38,12 @@
namespace js {
namespace jit {
template <typename Sig>
DynFn DynamicFunction(Sig fun) {
ABIFunctionSignature<Sig> sig;
return DynFn{sig.address(fun)};
}
//{{{ check_macroassembler_style
// ===============================================================
// Stack manipulation functions.
@ -101,6 +107,12 @@ void MacroAssembler::callWithABI(void* fun, MoveOp::Type result,
callWithABINoProfiler(fun, result, check);
}
void MacroAssembler::callWithABI(DynFn fun, MoveOp::Type result,
CheckUnsafeCallWithABI check) {
AutoProfilerCallInstrumentation profiler(*this);
callWithABINoProfiler(fun.address, result, check);
}
template <typename Sig, Sig fun>
void MacroAssembler::callWithABI(MoveOp::Type result,
CheckUnsafeCallWithABI check) {

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

@ -228,6 +228,12 @@ enum class CheckUnsafeCallWithABI {
DontCheckOther,
};
// This is a global function made to create the DynFn type in a controlled
// environment which would check if the function signature has been registered
// as an ABI function signature.
template <typename Sig>
static inline DynFn DynamicFunction(Sig fun);
enum class CharEncoding { Latin1, TwoByte };
// The public entrypoint for emitting assembly. Note that a MacroAssembler can
@ -620,6 +626,9 @@ class MacroAssembler : public MacroAssemblerSpecific {
inline void callWithABI(
void* fun, MoveOp::Type result = MoveOp::GENERAL,
CheckUnsafeCallWithABI check = CheckUnsafeCallWithABI::Check);
inline void callWithABI(
DynFn fun, MoveOp::Type result = MoveOp::GENERAL,
CheckUnsafeCallWithABI check = CheckUnsafeCallWithABI::Check);
template <typename Sig, Sig fun>
inline void callWithABI(
MoveOp::Type result = MoveOp::GENERAL,

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

@ -131,12 +131,12 @@ const VMFunctionData& GetVMFunction(TailCallVMFunctionId id) {
return tailCallVMFunctions[size_t(id)];
}
static void* GetVMFunctionTarget(VMFunctionId id) {
return vmFunctionTargets[size_t(id)];
static DynFn GetVMFunctionTarget(VMFunctionId id) {
return DynFn{vmFunctionTargets[size_t(id)]};
}
static void* GetVMFunctionTarget(TailCallVMFunctionId id) {
return tailCallVMFunctionTargets[size_t(id)];
static DynFn GetVMFunctionTarget(TailCallVMFunctionId id) {
return DynFn{tailCallVMFunctionTargets[size_t(id)]};
}
template <typename IdT>

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

@ -736,7 +736,7 @@ void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
}
bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunctionData& f, void* nativeFun,
const VMFunctionData& f, DynFn nativeFun,
uint32_t* wrapperOffset) {
*wrapperOffset = startTrampolineCode(masm);

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

@ -563,7 +563,7 @@ void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
}
bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunctionData& f, void* nativeFun,
const VMFunctionData& f, DynFn nativeFun,
uint32_t* wrapperOffset) {
*wrapperOffset = startTrampolineCode(masm);

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

@ -705,7 +705,7 @@ void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
}
bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunctionData& f, void* nativeFun,
const VMFunctionData& f, DynFn nativeFun,
uint32_t* wrapperOffset) {
*wrapperOffset = startTrampolineCode(masm);

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

@ -684,7 +684,7 @@ void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
}
bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunctionData& f, void* nativeFun,
const VMFunctionData& f, DynFn nativeFun,
uint32_t* wrapperOffset) {
*wrapperOffset = startTrampolineCode(masm);

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

@ -625,7 +625,7 @@ void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
}
bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunctionData& f, void* nativeFun,
const VMFunctionData& f, DynFn nativeFun,
uint32_t* wrapperOffset) {
*wrapperOffset = startTrampolineCode(masm);

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

@ -641,7 +641,7 @@ void JitRuntime::generateBailoutHandler(MacroAssembler& masm,
}
bool JitRuntime::generateVMWrapper(JSContext* cx, MacroAssembler& masm,
const VMFunctionData& f, void* nativeFun,
const VMFunctionData& f, DynFn nativeFun,
uint32_t* wrapperOffset) {
*wrapperOffset = startTrampolineCode(masm);