[fastcall] Introduce a builder pattern for specifying type modifiers
- Add a CFunctionBuilder interface to allow adding modifier flags to argument types. This will be used to support IDL attributes like [EnforceRange], [Clamp], and [AllowShared]. This CL adds only the interface, but the actual modifier flags do not exist yet as they would not be implemented. - Remove the internals of the old CFunction type inference and implement it on top of CFunctionBuilder. Bug: chromium:1052746 Change-Id: I09a7cba07105097517a8426a8eeb891393883ac6 Reviewed-on: https://chromium-review.googlesource.com/c/v8/v8/+/2686686 Reviewed-by: Toon Verwaest <verwaest@chromium.org> Reviewed-by: Maya Lekova <mslekova@chromium.org> Commit-Queue: Austin Eng <enga@chromium.org> Cr-Commit-Position: refs/heads/master@{#73024}
This commit is contained in:
parent
d98b12d3df
commit
db34c5a140
@ -205,39 +205,106 @@ class CTypeInfo {
|
|||||||
kV8Value,
|
kV8Value,
|
||||||
};
|
};
|
||||||
|
|
||||||
// kCallbackOptionsType and kInvalidType are not part of the Type enum
|
// kCallbackOptionsType is not part of the Type enum
|
||||||
// because they are only used internally. Use values 255 and 254 that
|
// because it is only used internally. Use value 255 that is larger
|
||||||
// are larger than any valid Type enum.
|
// than any valid Type enum.
|
||||||
static constexpr Type kCallbackOptionsType = Type(255);
|
static constexpr Type kCallbackOptionsType = Type(255);
|
||||||
static constexpr Type kInvalidType = Type(254);
|
|
||||||
|
|
||||||
enum class ArgFlags : uint8_t {
|
enum class Flags : uint8_t {
|
||||||
kNone = 0,
|
kNone = 0,
|
||||||
};
|
};
|
||||||
|
|
||||||
explicit constexpr CTypeInfo(Type type, ArgFlags flags = ArgFlags::kNone)
|
explicit constexpr CTypeInfo(Type type, Flags flags = Flags::kNone)
|
||||||
: type_(type), flags_(flags) {}
|
: type_(type), flags_(flags) {}
|
||||||
|
|
||||||
constexpr Type GetType() const { return type_; }
|
constexpr Type GetType() const { return type_; }
|
||||||
|
|
||||||
constexpr ArgFlags GetFlags() const { return flags_; }
|
constexpr Flags GetFlags() const { return flags_; }
|
||||||
|
|
||||||
static const CTypeInfo& Invalid() {
|
|
||||||
static CTypeInfo invalid = CTypeInfo(kInvalidType);
|
|
||||||
return invalid;
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
Type type_;
|
Type type_;
|
||||||
ArgFlags flags_;
|
Flags flags_;
|
||||||
};
|
};
|
||||||
|
|
||||||
class CFunctionInfo {
|
class V8_EXPORT CFunctionInfo {
|
||||||
public:
|
public:
|
||||||
virtual const CTypeInfo& ReturnInfo() const = 0;
|
// Construct a struct to hold a CFunction's type information.
|
||||||
virtual unsigned int ArgumentCount() const = 0;
|
// |return_info| describes the function's return type.
|
||||||
virtual const CTypeInfo& ArgumentInfo(unsigned int index) const = 0;
|
// |arg_info| is an array of |arg_count| CTypeInfos describing the
|
||||||
virtual bool HasOptions() const = 0;
|
// arguments. Only the last argument may be of the special type
|
||||||
|
// CTypeInfo::kCallbackOptionsType.
|
||||||
|
CFunctionInfo(const CTypeInfo& return_info, unsigned int arg_count,
|
||||||
|
const CTypeInfo* arg_info);
|
||||||
|
|
||||||
|
const CTypeInfo& ReturnInfo() const { return return_info_; }
|
||||||
|
|
||||||
|
// The argument count, not including the v8::FastApiCallbackOptions
|
||||||
|
// if present.
|
||||||
|
unsigned int ArgumentCount() const {
|
||||||
|
return HasOptions() ? arg_count_ - 1 : arg_count_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// |index| must be less than ArgumentCount().
|
||||||
|
// Note: if the last argument passed on construction of CFunctionInfo
|
||||||
|
// has type CTypeInfo::kCallbackOptionsType, it is not included in
|
||||||
|
// ArgumentCount().
|
||||||
|
const CTypeInfo& ArgumentInfo(unsigned int index) const;
|
||||||
|
|
||||||
|
bool HasOptions() const {
|
||||||
|
// The options arg is always the last one.
|
||||||
|
return arg_count_ > 0 && arg_info_[arg_count_ - 1].GetType() ==
|
||||||
|
CTypeInfo::kCallbackOptionsType;
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const CTypeInfo return_info_;
|
||||||
|
const unsigned int arg_count_;
|
||||||
|
const CTypeInfo* arg_info_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class V8_EXPORT CFunction {
|
||||||
|
public:
|
||||||
|
constexpr CFunction() : address_(nullptr), type_info_(nullptr) {}
|
||||||
|
|
||||||
|
const CTypeInfo& ReturnInfo() const { return type_info_->ReturnInfo(); }
|
||||||
|
|
||||||
|
const CTypeInfo& ArgumentInfo(unsigned int index) const {
|
||||||
|
return type_info_->ArgumentInfo(index);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned int ArgumentCount() const { return type_info_->ArgumentCount(); }
|
||||||
|
|
||||||
|
const void* GetAddress() const { return address_; }
|
||||||
|
const CFunctionInfo* GetTypeInfo() const { return type_info_; }
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
static CFunction Make(F* func) {
|
||||||
|
return ArgUnwrap<F*>::Make(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
V8_DEPRECATED("Use CFunctionBuilder instead.")
|
||||||
|
static CFunction MakeWithFallbackSupport(F* func) {
|
||||||
|
return ArgUnwrap<F*>::Make(func);
|
||||||
|
}
|
||||||
|
|
||||||
|
CFunction(const void* address, const CFunctionInfo* type_info);
|
||||||
|
|
||||||
|
private:
|
||||||
|
const void* address_;
|
||||||
|
const CFunctionInfo* type_info_;
|
||||||
|
|
||||||
|
template <typename F>
|
||||||
|
class ArgUnwrap {
|
||||||
|
static_assert(sizeof(F) != sizeof(F),
|
||||||
|
"CFunction must be created from a function pointer.");
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename R, typename... Args>
|
||||||
|
class ArgUnwrap<R (*)(Args...)> {
|
||||||
|
public:
|
||||||
|
static CFunction Make(R (*func)(Args...));
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ApiObject {
|
struct ApiObject {
|
||||||
@ -272,37 +339,6 @@ struct FastApiCallbackOptions {
|
|||||||
|
|
||||||
namespace internal {
|
namespace internal {
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
struct GetCType;
|
|
||||||
|
|
||||||
#define SPECIALIZE_GET_C_TYPE_FOR(ctype, ctypeinfo) \
|
|
||||||
template <> \
|
|
||||||
struct GetCType<ctype> { \
|
|
||||||
static constexpr CTypeInfo Get() { \
|
|
||||||
return CTypeInfo(CTypeInfo::Type::ctypeinfo); \
|
|
||||||
} \
|
|
||||||
};
|
|
||||||
|
|
||||||
#define SUPPORTED_C_TYPES(V) \
|
|
||||||
V(void, kVoid) \
|
|
||||||
V(bool, kBool) \
|
|
||||||
V(int32_t, kInt32) \
|
|
||||||
V(uint32_t, kUint32) \
|
|
||||||
V(int64_t, kInt64) \
|
|
||||||
V(uint64_t, kUint64) \
|
|
||||||
V(float, kFloat32) \
|
|
||||||
V(double, kFloat64) \
|
|
||||||
V(ApiObject, kV8Value)
|
|
||||||
|
|
||||||
SUPPORTED_C_TYPES(SPECIALIZE_GET_C_TYPE_FOR)
|
|
||||||
|
|
||||||
template <>
|
|
||||||
struct GetCType<FastApiCallbackOptions&> {
|
|
||||||
static constexpr CTypeInfo Get() {
|
|
||||||
return CTypeInfo(CTypeInfo::kCallbackOptionsType);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
// Helper to count the number of occurances of `T` in `List`
|
// Helper to count the number of occurances of `T` in `List`
|
||||||
template <typename T, typename... List>
|
template <typename T, typename... List>
|
||||||
struct count : std::integral_constant<int, 0> {};
|
struct count : std::integral_constant<int, 0> {};
|
||||||
@ -312,107 +348,178 @@ struct count<T, T, Args...>
|
|||||||
template <typename T, typename U, typename... Args>
|
template <typename T, typename U, typename... Args>
|
||||||
struct count<T, U, Args...> : count<T, Args...> {};
|
struct count<T, U, Args...> : count<T, Args...> {};
|
||||||
|
|
||||||
template <typename R, typename... Args>
|
template <typename RetBuilder, typename... ArgBuilders>
|
||||||
class CFunctionInfoImpl : public CFunctionInfo {
|
class CFunctionInfoImpl : public CFunctionInfo {
|
||||||
public:
|
|
||||||
static constexpr int kOptionsArgCount =
|
static constexpr int kOptionsArgCount =
|
||||||
count<FastApiCallbackOptions&, Args...>();
|
count<FastApiCallbackOptions&, ArgBuilders...>();
|
||||||
static constexpr int kReceiverCount = 1;
|
static constexpr int kReceiverCount = 1;
|
||||||
CFunctionInfoImpl()
|
|
||||||
: return_info_(internal::GetCType<R>::Get()),
|
static_assert(kOptionsArgCount == 0 || kOptionsArgCount == 1,
|
||||||
arg_count_(sizeof...(Args) - kOptionsArgCount),
|
"Only one options parameter is supported.");
|
||||||
arg_info_{internal::GetCType<Args>::Get()...} {
|
|
||||||
static_assert(kOptionsArgCount == 0 || kOptionsArgCount == 1,
|
static_assert(sizeof...(ArgBuilders) >= kOptionsArgCount + kReceiverCount,
|
||||||
"Only one options parameter is supported.");
|
"The receiver or the options argument is missing.");
|
||||||
static_assert(sizeof...(Args) >= kOptionsArgCount + kReceiverCount,
|
|
||||||
"The receiver or the fallback argument is missing.");
|
public:
|
||||||
constexpr CTypeInfo::Type type = internal::GetCType<R>::Get().GetType();
|
constexpr CFunctionInfoImpl()
|
||||||
static_assert(type == CTypeInfo::Type::kVoid ||
|
: CFunctionInfo(RetBuilder::Build(), sizeof...(ArgBuilders),
|
||||||
type == CTypeInfo::Type::kBool ||
|
arg_info_storage_),
|
||||||
type == CTypeInfo::Type::kInt32 ||
|
arg_info_storage_{ArgBuilders::Build()...} {
|
||||||
type == CTypeInfo::Type::kUint32 ||
|
constexpr CTypeInfo::Type kReturnType = RetBuilder::Build().GetType();
|
||||||
type == CTypeInfo::Type::kFloat32 ||
|
static_assert(kReturnType == CTypeInfo::Type::kVoid ||
|
||||||
type == CTypeInfo::Type::kFloat64,
|
kReturnType == CTypeInfo::Type::kBool ||
|
||||||
|
kReturnType == CTypeInfo::Type::kInt32 ||
|
||||||
|
kReturnType == CTypeInfo::Type::kUint32 ||
|
||||||
|
kReturnType == CTypeInfo::Type::kFloat32 ||
|
||||||
|
kReturnType == CTypeInfo::Type::kFloat64,
|
||||||
"64-bit int and api object values are not currently "
|
"64-bit int and api object values are not currently "
|
||||||
"supported return types.");
|
"supported return types.");
|
||||||
}
|
}
|
||||||
|
|
||||||
const CTypeInfo& ReturnInfo() const override { return return_info_; }
|
private:
|
||||||
unsigned int ArgumentCount() const override { return arg_count_; }
|
const CTypeInfo arg_info_storage_[sizeof...(ArgBuilders)];
|
||||||
const CTypeInfo& ArgumentInfo(unsigned int index) const override {
|
};
|
||||||
if (index >= ArgumentCount()) {
|
|
||||||
return CTypeInfo::Invalid();
|
template <typename T>
|
||||||
}
|
struct TypeInfoHelper {
|
||||||
return arg_info_[index];
|
static_assert(sizeof(T) != sizeof(T), "This type is not supported");
|
||||||
|
};
|
||||||
|
|
||||||
|
#define SPECIALIZE_GET_TYPE_INFO_HELPER_FOR(T, Enum) \
|
||||||
|
template <> \
|
||||||
|
struct TypeInfoHelper<T> { \
|
||||||
|
static constexpr CTypeInfo::Flags Flags() { \
|
||||||
|
return CTypeInfo::Flags::kNone; \
|
||||||
|
} \
|
||||||
|
\
|
||||||
|
static constexpr CTypeInfo::Type Type() { return CTypeInfo::Type::Enum; } \
|
||||||
|
};
|
||||||
|
|
||||||
|
#define BASIC_C_TYPES(V) \
|
||||||
|
V(void, kVoid) \
|
||||||
|
V(bool, kBool) \
|
||||||
|
V(int32_t, kInt32) \
|
||||||
|
V(uint32_t, kUint32) \
|
||||||
|
V(int64_t, kInt64) \
|
||||||
|
V(uint64_t, kUint64) \
|
||||||
|
V(float, kFloat32) \
|
||||||
|
V(double, kFloat64) \
|
||||||
|
V(ApiObject, kV8Value)
|
||||||
|
|
||||||
|
BASIC_C_TYPES(SPECIALIZE_GET_TYPE_INFO_HELPER_FOR)
|
||||||
|
|
||||||
|
#undef BASIC_C_TYPES
|
||||||
|
|
||||||
|
template <>
|
||||||
|
struct TypeInfoHelper<FastApiCallbackOptions&> {
|
||||||
|
static constexpr CTypeInfo::Flags Flags() { return CTypeInfo::Flags::kNone; }
|
||||||
|
|
||||||
|
static constexpr CTypeInfo::Type Type() {
|
||||||
|
return CTypeInfo::kCallbackOptionsType;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename T, CTypeInfo::Flags... Flags>
|
||||||
|
class CTypeInfoBuilder {
|
||||||
|
public:
|
||||||
|
using BaseType = T;
|
||||||
|
|
||||||
|
static constexpr CTypeInfo Build() {
|
||||||
|
// Get the flags and merge in any additional flags.
|
||||||
|
uint8_t flags = uint8_t(TypeInfoHelper<T>::Flags());
|
||||||
|
int unused[] = {0, (flags |= uint8_t(Flags), 0)...};
|
||||||
|
// With C++17, we could use a "..." fold expression over a parameter pack.
|
||||||
|
// Since we're still using C++14, we have to evaluate an OR expresion while
|
||||||
|
// constructing an unused list of 0's. This applies the binary operator
|
||||||
|
// for each value in Flags.
|
||||||
|
(void)unused;
|
||||||
|
|
||||||
|
// Return the same type with the merged flags.
|
||||||
|
return CTypeInfo(TypeInfoHelper<T>::Type(), CTypeInfo::Flags(flags));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename RetBuilder, typename... ArgBuilders>
|
||||||
|
class CFunctionBuilderWithFunction {
|
||||||
|
public:
|
||||||
|
explicit constexpr CFunctionBuilderWithFunction(const void* fn) : fn_(fn) {}
|
||||||
|
|
||||||
|
template <CTypeInfo::Flags... Flags>
|
||||||
|
constexpr auto Ret() {
|
||||||
|
return CFunctionBuilderWithFunction<
|
||||||
|
CTypeInfoBuilder<typename RetBuilder::BaseType, Flags...>,
|
||||||
|
ArgBuilders...>(fn_);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <unsigned int N, CTypeInfo::Flags... Flags>
|
||||||
|
constexpr auto Arg() {
|
||||||
|
// Return a copy of the builder with the Nth arg builder merged with
|
||||||
|
// template parameter pack Flags.
|
||||||
|
return ArgImpl<N, Flags...>(
|
||||||
|
std::make_index_sequence<sizeof...(ArgBuilders)>());
|
||||||
|
}
|
||||||
|
|
||||||
|
auto Build() {
|
||||||
|
static CFunctionInfoImpl<RetBuilder, ArgBuilders...> instance;
|
||||||
|
return CFunction(fn_, &instance);
|
||||||
}
|
}
|
||||||
bool HasOptions() const override { return kOptionsArgCount == 1; }
|
|
||||||
|
|
||||||
private:
|
private:
|
||||||
const CTypeInfo return_info_;
|
template <bool Merge, unsigned int N, CTypeInfo::Flags... Flags>
|
||||||
const unsigned int arg_count_;
|
struct GetArgBuilder;
|
||||||
const CTypeInfo arg_info_[sizeof...(Args)];
|
|
||||||
|
// Returns the same ArgBuilder as the one at index N, including its flags.
|
||||||
|
// Flags in the template parameter pack are ignored.
|
||||||
|
template <unsigned int N, CTypeInfo::Flags... Flags>
|
||||||
|
struct GetArgBuilder<false, N, Flags...> {
|
||||||
|
using type =
|
||||||
|
typename std::tuple_element<N, std::tuple<ArgBuilders...>>::type;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Returns an ArgBuilder with the same base type as the one at index N,
|
||||||
|
// but merges the flags with the flags in the template parameter pack.
|
||||||
|
template <unsigned int N, CTypeInfo::Flags... Flags>
|
||||||
|
struct GetArgBuilder<true, N, Flags...> {
|
||||||
|
using type = CTypeInfoBuilder<
|
||||||
|
typename std::tuple_element<N,
|
||||||
|
std::tuple<ArgBuilders...>>::type::BaseType,
|
||||||
|
std::tuple_element<N, std::tuple<ArgBuilders...>>::type::Build()
|
||||||
|
.GetFlags(),
|
||||||
|
Flags...>;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Return a copy of the CFunctionBuilder, but merges the Flags on ArgBuilder
|
||||||
|
// index N with the new Flags passed in the template parameter pack.
|
||||||
|
template <unsigned int N, CTypeInfo::Flags... Flags, size_t... I>
|
||||||
|
constexpr auto ArgImpl(std::index_sequence<I...>) {
|
||||||
|
return CFunctionBuilderWithFunction<
|
||||||
|
RetBuilder, typename GetArgBuilder<N == I, I, Flags...>::type...>(fn_);
|
||||||
|
}
|
||||||
|
|
||||||
|
const void* fn_;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CFunctionBuilder {
|
||||||
|
public:
|
||||||
|
constexpr CFunctionBuilder() {}
|
||||||
|
|
||||||
|
template <typename R, typename... Args>
|
||||||
|
constexpr auto Fn(R (*fn)(Args...)) {
|
||||||
|
return CFunctionBuilderWithFunction<CTypeInfoBuilder<R>,
|
||||||
|
CTypeInfoBuilder<Args>...>(
|
||||||
|
reinterpret_cast<const void*>(fn));
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace internal
|
} // namespace internal
|
||||||
|
|
||||||
class V8_EXPORT CFunction {
|
// static
|
||||||
public:
|
template <typename R, typename... Args>
|
||||||
constexpr CFunction() : address_(nullptr), type_info_(nullptr) {}
|
CFunction CFunction::ArgUnwrap<R (*)(Args...)>::Make(R (*func)(Args...)) {
|
||||||
|
return internal::CFunctionBuilder().Fn(func).Build();
|
||||||
|
}
|
||||||
|
|
||||||
const CTypeInfo& ReturnInfo() const { return type_info_->ReturnInfo(); }
|
using CFunctionBuilder = internal::CFunctionBuilder;
|
||||||
|
|
||||||
const CTypeInfo& ArgumentInfo(unsigned int index) const {
|
|
||||||
return type_info_->ArgumentInfo(index);
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int ArgumentCount() const { return type_info_->ArgumentCount(); }
|
|
||||||
|
|
||||||
const void* GetAddress() const { return address_; }
|
|
||||||
const CFunctionInfo* GetTypeInfo() const { return type_info_; }
|
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
static CFunction Make(F* func) {
|
|
||||||
return ArgUnwrap<F*>::Make(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
V8_DEPRECATED("Use CFunction::Make instead.")
|
|
||||||
static CFunction MakeWithFallbackSupport(F* func) {
|
|
||||||
return ArgUnwrap<F*>::Make(func);
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
static CFunction Make(F* func, const CFunctionInfo* type_info) {
|
|
||||||
return CFunction(reinterpret_cast<const void*>(func), type_info);
|
|
||||||
}
|
|
||||||
|
|
||||||
private:
|
|
||||||
const void* address_;
|
|
||||||
const CFunctionInfo* type_info_;
|
|
||||||
|
|
||||||
CFunction(const void* address, const CFunctionInfo* type_info);
|
|
||||||
|
|
||||||
template <typename R, typename... Args>
|
|
||||||
static CFunctionInfo* GetCFunctionInfo() {
|
|
||||||
static internal::CFunctionInfoImpl<R, Args...> instance;
|
|
||||||
return &instance;
|
|
||||||
}
|
|
||||||
|
|
||||||
template <typename F>
|
|
||||||
class ArgUnwrap {
|
|
||||||
static_assert(sizeof(F) != sizeof(F),
|
|
||||||
"CFunction must be created from a function pointer.");
|
|
||||||
};
|
|
||||||
|
|
||||||
template <typename R, typename... Args>
|
|
||||||
class ArgUnwrap<R (*)(Args...)> {
|
|
||||||
public:
|
|
||||||
static CFunction Make(R (*func)(Args...)) {
|
|
||||||
return CFunction(reinterpret_cast<const void*>(func),
|
|
||||||
GetCFunctionInfo<R, Args...>());
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
} // namespace v8
|
} // namespace v8
|
||||||
|
|
||||||
|
@ -9987,6 +9987,21 @@ CFunction::CFunction(const void* address, const CFunctionInfo* type_info)
|
|||||||
CHECK_NOT_NULL(type_info_);
|
CHECK_NOT_NULL(type_info_);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CFunctionInfo::CFunctionInfo(const CTypeInfo& return_info,
|
||||||
|
unsigned int arg_count, const CTypeInfo* arg_info)
|
||||||
|
: return_info_(return_info), arg_count_(arg_count), arg_info_(arg_info) {
|
||||||
|
if (arg_count_ > 0) {
|
||||||
|
for (unsigned int i = 0; i < arg_count_ - 1; ++i) {
|
||||||
|
DCHECK(arg_info_[i].GetType() != CTypeInfo::kCallbackOptionsType);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const CTypeInfo& CFunctionInfo::ArgumentInfo(unsigned int index) const {
|
||||||
|
DCHECK_LT(index, ArgumentCount());
|
||||||
|
return arg_info_[index];
|
||||||
|
}
|
||||||
|
|
||||||
RegisterState::RegisterState()
|
RegisterState::RegisterState()
|
||||||
: pc(nullptr), sp(nullptr), fp(nullptr), lr(nullptr) {}
|
: pc(nullptr), sp(nullptr), fp(nullptr), lr(nullptr) {}
|
||||||
RegisterState::~RegisterState() = default;
|
RegisterState::~RegisterState() = default;
|
||||||
|
@ -27937,37 +27937,28 @@ void CallWithUnexpectedObjectType(v8::Local<v8::Value> receiver) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
class TestCFunctionInfo : public v8::CFunctionInfo {
|
class TestCFunctionInfo : public v8::CFunctionInfo {
|
||||||
const v8::CTypeInfo& ReturnInfo() const override {
|
static constexpr unsigned int kArgCount = 2u;
|
||||||
static v8::CTypeInfo return_info =
|
|
||||||
v8::CTypeInfo(v8::CTypeInfo::Type::kVoid);
|
|
||||||
return return_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
unsigned int ArgumentCount() const override { return 2; }
|
public:
|
||||||
|
TestCFunctionInfo()
|
||||||
|
: v8::CFunctionInfo(v8::CTypeInfo(v8::CTypeInfo::Type::kVoid), kArgCount,
|
||||||
|
arg_info_storage_),
|
||||||
|
arg_info_storage_{
|
||||||
|
v8::CTypeInfo(v8::CTypeInfo::Type::kV8Value),
|
||||||
|
v8::CTypeInfo(v8::CTypeInfo::Type::kBool),
|
||||||
|
} {}
|
||||||
|
|
||||||
const v8::CTypeInfo& ArgumentInfo(unsigned int index) const override {
|
private:
|
||||||
static v8::CTypeInfo type_info0 =
|
const v8::CTypeInfo arg_info_storage_[kArgCount];
|
||||||
v8::CTypeInfo(v8::CTypeInfo::Type::kV8Value);
|
|
||||||
static v8::CTypeInfo type_info1 = v8::CTypeInfo(v8::CTypeInfo::Type::kBool);
|
|
||||||
switch (index) {
|
|
||||||
case 0:
|
|
||||||
return type_info0;
|
|
||||||
case 1:
|
|
||||||
return type_info1;
|
|
||||||
default:
|
|
||||||
UNREACHABLE();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool HasOptions() const override { return false; }
|
|
||||||
};
|
};
|
||||||
|
|
||||||
void CheckDynamicTypeInfo() {
|
void CheckDynamicTypeInfo() {
|
||||||
LocalContext env;
|
LocalContext env;
|
||||||
|
|
||||||
static TestCFunctionInfo type_info;
|
static TestCFunctionInfo type_info;
|
||||||
v8::CFunction c_func =
|
v8::CFunction c_func = v8::CFunction(
|
||||||
v8::CFunction::Make(ApiNumberChecker<bool>::FastCallback, &type_info);
|
reinterpret_cast<const void*>(ApiNumberChecker<bool>::FastCallback),
|
||||||
|
&type_info);
|
||||||
CHECK_EQ(c_func.ArgumentCount(), 2);
|
CHECK_EQ(c_func.ArgumentCount(), 2);
|
||||||
CHECK_EQ(c_func.ArgumentInfo(0).GetType(), v8::CTypeInfo::Type::kV8Value);
|
CHECK_EQ(c_func.ArgumentInfo(0).GetType(), v8::CTypeInfo::Type::kV8Value);
|
||||||
CHECK_EQ(c_func.ArgumentInfo(1).GetType(), v8::CTypeInfo::Type::kBool);
|
CHECK_EQ(c_func.ArgumentInfo(1).GetType(), v8::CTypeInfo::Type::kBool);
|
||||||
|
Loading…
Reference in New Issue
Block a user