Files
AncientCivil/Plugins/Puerts/Source/JsEnv/Public/V8FastCall.hpp
T
2025-02-10 00:44:11 +08:00

216 lines
6.1 KiB
C++

/*
* Tencent is pleased to support the open source community by making Puerts available.
* Copyright (C) 2020 THL A29 Limited, a Tencent company. All rights reserved.
* Puerts is licensed under the BSD 3-Clause License, except for the third-party components listed in the file 'LICENSE' which may
* be subject to their corresponding license terms. This file is subject to the terms and conditions defined in file 'LICENSE',
* which is part of this source code package.
*/
#pragma once
#pragma warning(push, 0)
#include <v8-fast-api-calls.h>
#pragma warning(pop)
#include "DataTransfer.h"
namespace PUERTS_NAMESPACE
{
template <typename T, typename Enable = void>
struct FastCallArgument
{
};
template <typename T>
struct FastCallArgument<T, typename std::enable_if<std::is_pointer<T>::value && !std::is_same<T, const char*>::value &&
!std::is_enum<typename std::remove_pointer<T>::type>::value &&
!std::is_integral<typename std::remove_pointer<T>::type>::value &&
!std::is_floating_point<typename std::remove_pointer<T>::type>::value>::type>
{
using DeclType = v8::Local<v8::Value>;
static T Get(v8::Local<v8::Value> v)
{
if (V8_LIKELY(v->IsObject()))
{
// return static_cast<T>(v.As<v8::Object>()->GetAlignedPointerFromInternalField(1));
return static_cast<T>(DataTransfer::GetPointerFast<void>(v.As<v8::Object>()));
}
return nullptr;
}
};
template <>
struct FastCallArgument<std::string*>
{
};
template <typename T>
struct FastCallArgument<T, typename std::enable_if<std::is_enum<T>::value>::type>
{
using DeclType = int;
static T Get(int i)
{
return static_cast<T>(i);
}
};
template <typename T>
struct FastCallArgument<T, typename std::enable_if<std::is_integral<T>::value || std::is_floating_point<T>::value>::type>
{
using DeclType = typename std::decay<T>::type;
static T Get(typename std::decay<T>::type i)
{
return i;
}
};
template <>
struct FastCallArgument<bool>
{
using DeclType = bool;
static bool Get(bool i)
{
return i;
}
};
namespace internal
{
namespace fastcallutil
{
template <bool _First_value, class _First, class... _Rest>
struct _Conjunction
{ // handle false trait or last trait
using type = _First;
};
template <class _True, class _Next, class... _Rest>
struct _Conjunction<true, _True, _Next, _Rest...>
{ // the first trait is true, try the next one
using type = typename _Conjunction<_Next::value, _Next, _Rest...>::type;
};
template <class... _Traits>
struct Conjunction : std::true_type
{
}; // If _Traits is empty, true_type
template <class _First, class... _Rest>
struct Conjunction<_First, _Rest...> : _Conjunction<_First::value, _First, _Rest...>::type
{
// the first false trait in _Traits, or the last trait if none are false
};
template <class...>
using Void_t = void;
} // namespace fastcallutil
} // namespace internal
template <typename T, typename = void>
struct IsArgSupportedHelper : std::false_type
{
};
template <typename T>
struct IsArgSupportedHelper<T, internal::fastcallutil::Void_t<decltype(&FastCallArgument<T>::Get)>> : std::true_type
{
};
template <typename T, typename = void>
struct IsArgsSupportedHelper : std::false_type
{
};
template <typename... Args>
struct IsArgsSupportedHelper<std::tuple<Args...>,
typename std::enable_if<internal::fastcallutil::Conjunction<IsArgSupportedHelper<Args>...>::value>::type> : std::true_type
{
};
template <typename T, typename = void>
struct IsReturnSupportedHelper : std::false_type
{
};
template <typename T>
struct IsReturnSupportedHelper<T,
typename std::enable_if<IsArgSupportedHelper<T>::value && !std::is_pointer<T>::value && !std::is_integral<T>::value>::type>
: std::true_type
{
};
template <typename T>
struct IsReturnSupportedHelper<T, typename std::enable_if<std::is_integral<T>::value && sizeof(T) < 8>::type> : std::true_type
{
};
template <>
struct IsReturnSupportedHelper<void> : std::true_type
{
};
template <typename T, T, typename Enable = void>
struct V8FastCall
{
static const v8::CFunction* info()
{
return nullptr;
}
};
template <typename Ret, typename... Args, Ret (*func)(Args...)>
struct V8FastCall<Ret (*)(Args...), func,
typename std::enable_if<IsReturnSupportedHelper<Ret>::value && IsArgsSupportedHelper<std::tuple<Args...>>::value &&
(sizeof...(Args) > 0)>::type>
{
static Ret Wrap(v8::Local<v8::Object> receiver_obj, typename FastCallArgument<Args>::DeclType... args)
{
return func(FastCallArgument<Args>::Get(args)...);
}
static const v8::CFunction* info()
{
static v8::CFunction _info = v8::CFunction::Make(Wrap);
return &_info;
}
};
template <typename Inc, typename Ret, typename... Args, Ret (Inc::*func)(Args...)>
struct V8FastCall<Ret (Inc::*)(Args...), func,
typename std::enable_if<IsReturnSupportedHelper<Ret>::value && IsArgsSupportedHelper<std::tuple<Args...>>::value>::type>
{
static Ret Wrap(v8::Local<v8::Object> receiver_obj, typename FastCallArgument<Args>::DeclType... args)
{
auto self = FastCallArgument<Inc*>::Get(receiver_obj);
return (self->*func)(FastCallArgument<Args>::Get(args)...);
}
static const v8::CFunction* info()
{
static v8::CFunction _info = v8::CFunction::Make(Wrap);
return &_info;
}
};
template <typename Inc, typename Ret, typename... Args, Ret (Inc::*func)(Args...) const>
struct V8FastCall<Ret (Inc::*)(Args...) const, func,
typename std::enable_if<IsReturnSupportedHelper<Ret>::value && IsArgsSupportedHelper<std::tuple<Args...>>::value>::type>
{
static Ret Wrap(v8::Local<v8::Object> receiver_obj, typename FastCallArgument<Args>::DeclType... args)
{
auto self = FastCallArgument<Inc*>::Get(receiver_obj);
return (self->*func)(FastCallArgument<Args>::Get(args)...);
}
static const v8::CFunction* info()
{
static v8::CFunction _info = v8::CFunction::Make(Wrap);
return &_info;
}
};
} // namespace PUERTS_NAMESPACE