| | |
| | |
| | |
| |
|
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| | |
| |
|
| | #ifndef INCLUDE_V8_FAST_API_CALLS_H_ |
| | #define INCLUDE_V8_FAST_API_CALLS_H_ |
| |
|
| | #include <stddef.h> |
| | #include <stdint.h> |
| |
|
| | #include "v8config.h" |
| |
|
| | namespace v8 { |
| |
|
| | class CTypeInfo { |
| | public: |
| | enum class Type : char { |
| | kVoid, |
| | kBool, |
| | kInt32, |
| | kUint32, |
| | kInt64, |
| | kUint64, |
| | kFloat32, |
| | kFloat64, |
| | kUnwrappedApiObject, |
| | }; |
| |
|
| | enum class ArgFlags : uint8_t { |
| | kNone = 0, |
| | kIsArrayBit = 1 << 0, |
| | }; |
| |
|
| | static CTypeInfo FromWrapperType(const void* wrapper_type_info, |
| | ArgFlags flags = ArgFlags::kNone) { |
| | uintptr_t wrapper_type_info_ptr = |
| | reinterpret_cast<uintptr_t>(wrapper_type_info); |
| | |
| | CHECK_EQ( |
| | wrapper_type_info_ptr & ~(static_cast<uintptr_t>(~0) |
| | << static_cast<uintptr_t>(kIsWrapperTypeBit)), |
| | 0u); |
| | |
| | |
| | return CTypeInfo(wrapper_type_info_ptr | static_cast<int>(flags) | |
| | kIsWrapperTypeBit); |
| | } |
| |
|
| | static constexpr CTypeInfo FromCType(Type ctype, |
| | ArgFlags flags = ArgFlags::kNone) { |
| | |
| | return CTypeInfo( |
| | ((static_cast<uintptr_t>(ctype) << kTypeOffset) & kTypeMask) | |
| | static_cast<int>(flags)); |
| | } |
| |
|
| | const void* GetWrapperInfo() const; |
| |
|
| | constexpr Type GetType() const { |
| | if (payload_ & kIsWrapperTypeBit) { |
| | return Type::kUnwrappedApiObject; |
| | } |
| | return static_cast<Type>((payload_ & kTypeMask) >> kTypeOffset); |
| | } |
| |
|
| | constexpr bool IsArray() const { |
| | return payload_ & static_cast<int>(ArgFlags::kIsArrayBit); |
| | } |
| |
|
| | private: |
| | explicit constexpr CTypeInfo(uintptr_t payload) : payload_(payload) {} |
| |
|
| | |
| | static constexpr uintptr_t kIsWrapperTypeBit = 1 << 1; |
| | static constexpr uintptr_t kWrapperTypeInfoMask = static_cast<uintptr_t>(~0) |
| | << 2; |
| |
|
| | static constexpr unsigned int kTypeOffset = kIsWrapperTypeBit; |
| | static constexpr unsigned int kTypeSize = 8 - kTypeOffset; |
| | static constexpr uintptr_t kTypeMask = |
| | (~(static_cast<uintptr_t>(~0) << kTypeSize)) << kTypeOffset; |
| |
|
| | const uintptr_t payload_; |
| | }; |
| |
|
| | class CFunctionInfo { |
| | public: |
| | virtual const CTypeInfo& ReturnInfo() const = 0; |
| | virtual unsigned int ArgumentCount() const = 0; |
| | virtual const CTypeInfo& ArgumentInfo(unsigned int index) const = 0; |
| | }; |
| |
|
| | template <typename T> |
| | class WrapperTraits { |
| | public: |
| | static const void* GetTypeInfo() { |
| | static_assert(sizeof(T) != sizeof(T), |
| | "WrapperTraits must be specialized for this type."); |
| | return nullptr; |
| | } |
| | }; |
| |
|
| | namespace internal { |
| |
|
| | template <typename T> |
| | struct GetCType { |
| | static_assert(sizeof(T) != sizeof(T), "Unsupported CType"); |
| | }; |
| |
|
| | #define SPECIALIZE_GET_C_TYPE_FOR(ctype, ctypeinfo) \ |
| | template <> \ |
| | struct GetCType<ctype> { \ |
| | static constexpr CTypeInfo Get() { \ |
| | return CTypeInfo::FromCType(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) |
| |
|
| | SUPPORTED_C_TYPES(SPECIALIZE_GET_C_TYPE_FOR) |
| |
|
| | template <typename T, typename = void> |
| | struct EnableIfHasWrapperTypeInfo {}; |
| |
|
| | template <typename T> |
| | struct EnableIfHasWrapperTypeInfo<T, decltype(WrapperTraits<T>::GetTypeInfo(), |
| | void())> { |
| | typedef void type; |
| | }; |
| |
|
| | |
| | template <typename T, typename = void> |
| | struct GetCTypePointerImpl { |
| | static constexpr CTypeInfo Get() { |
| | return CTypeInfo::FromCType(GetCType<T>::Get().GetType(), |
| | CTypeInfo::ArgFlags::kIsArrayBit); |
| | } |
| | }; |
| |
|
| | |
| | template <typename T> |
| | struct GetCTypePointerImpl<T, typename EnableIfHasWrapperTypeInfo<T>::type> { |
| | static constexpr CTypeInfo Get() { |
| | return CTypeInfo::FromWrapperType(WrapperTraits<T>::GetTypeInfo()); |
| | } |
| | }; |
| |
|
| | |
| | template <typename T, typename = void> |
| | struct GetCTypePointerPointerImpl { |
| | static_assert(sizeof(T**) != sizeof(T**), "Unsupported type"); |
| | }; |
| |
|
| | |
| | template <typename T> |
| | struct GetCTypePointerPointerImpl< |
| | T, typename EnableIfHasWrapperTypeInfo<T>::type> { |
| | static constexpr CTypeInfo Get() { |
| | return CTypeInfo::FromWrapperType(WrapperTraits<T>::GetTypeInfo(), |
| | CTypeInfo::ArgFlags::kIsArrayBit); |
| | } |
| | }; |
| |
|
| | template <typename T> |
| | struct GetCType<T**> : public GetCTypePointerPointerImpl<T> {}; |
| |
|
| | template <typename T> |
| | struct GetCType<T*> : public GetCTypePointerImpl<T> {}; |
| |
|
| | template <typename R, typename... Args> |
| | class CFunctionInfoImpl : public CFunctionInfo { |
| | public: |
| | CFunctionInfoImpl() |
| | : return_info_(internal::GetCType<R>::Get()), |
| | arg_count_(sizeof...(Args)), |
| | arg_info_{internal::GetCType<Args>::Get()...} { |
| | static_assert( |
| | internal::GetCType<R>::Get().GetType() == CTypeInfo::Type::kVoid, |
| | "Only void return types are currently supported."); |
| | } |
| |
|
| | const CTypeInfo& ReturnInfo() const override { return return_info_; } |
| | unsigned int ArgumentCount() const override { return arg_count_; } |
| | const CTypeInfo& ArgumentInfo(unsigned int index) const override { |
| | CHECK_LT(index, ArgumentCount()); |
| | return arg_info_[index]; |
| | } |
| |
|
| | private: |
| | CTypeInfo return_info_; |
| | const unsigned int arg_count_; |
| | CTypeInfo arg_info_[sizeof...(Args)]; |
| | }; |
| |
|
| | } |
| |
|
| | 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); |
| | } |
| |
|
| | 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...>()); |
| | } |
| | }; |
| | }; |
| |
|
| | } |
| |
|
| | #endif |
| |
|