ebco optimizations for certain classes

This commit is contained in:
ThePhD 2019-02-10 16:40:37 -05:00
parent b4e83ca866
commit 4fd197d956
No known key found for this signature in database
GPG Key ID: 1509DB1C0F702BFA
6 changed files with 142 additions and 127 deletions

View File

@ -368,11 +368,11 @@ namespace sol {
template <typename F>
static int call(lua_State* L, F&& f) {
if constexpr (is_index) {
constexpr bool is_stack = is_stack_based_v<meta::unqualified_t<decltype(detail::unwrap(f.get_value()))>>;
constexpr bool is_stack = is_stack_based_v<meta::unqualified_t<decltype(detail::unwrap(f.value()))>>;
if constexpr (clean_stack && !is_stack) {
lua_settop(L, 0);
}
return stack::push_reference(L, detail::unwrap(f.get_value()));
return stack::push_reference(L, detail::unwrap(f.value()));
}
else {
if constexpr (std::is_const_v<meta::unwrapped_t<T>>) {
@ -381,7 +381,7 @@ namespace sol {
else {
using R = meta::unwrapped_t<T>;
if constexpr (std::is_assignable_v<std::add_lvalue_reference_t<meta::unqualified_t<R>>, R>) {
detail::unwrap(f.get_value()) = stack::unqualified_get<meta::unwrapped_t<T>>(L, boost + (is_variable ? 3 : 1));
detail::unwrap(f.value()) = stack::unqualified_get<meta::unwrapped_t<T>>(L, boost + (is_variable ? 3 : 1));
if (clean_stack) {
lua_settop(L, 0);
}
@ -482,9 +482,35 @@ namespace sol {
}
}
else if constexpr (std::is_member_object_pointer_v<F>) {
using traits_type = lua_bind_traits<F>;
using wrap = wrapper<F>;
using object_type = typename wrap::object_type;
if constexpr (is_index) {
if constexpr (sizeof...(Args) < 1) {
using Ta = std::conditional_t<std::is_void_v<T>, object_type, T>;
#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE
auto maybeo = stack::check_get<Ta*>(L, 1);
if (!maybeo || maybeo.value() == nullptr) {
if (is_variable) {
return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)");
}
return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)");
}
object_type* o = static_cast<object_type*>(maybeo.value());
return call(L, std::forward<Fx>(fx), *o);
#else
object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
return call(L, std::forward<Fx>(fx), o);
#endif // Safety
}
else {
using returns_list = typename wrap::returns_list;
using caller = typename wrap::caller;
return stack::call_into_lua<checked, clean_stack>(
returns_list(), types<>(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), std::forward<Args>(args)...);
}
}
else {
using traits_type = lua_bind_traits<F>;
using return_type = typename traits_type::return_type;
constexpr bool is_const = std::is_const_v<std::remove_reference_t<return_type>>;
if constexpr (is_const) {
@ -514,7 +540,7 @@ namespace sol {
}
else {
using Ta = std::conditional_t<std::is_void_v<T>, object_type, T>;
#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE
#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE
auto maybeo = stack::check_get<Ta*>(L, 1);
if (!maybeo || maybeo.value() == nullptr) {
if (is_variable) {
@ -524,9 +550,9 @@ namespace sol {
}
object_type* po = static_cast<object_type*>(maybeo.value());
object_type& o = *po;
#else
#else
object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
#endif // Safety
#endif // Safety
return stack::call_into_lua<checked, clean_stack>(
types<void>(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward<Fx>(fx), o);
@ -534,6 +560,7 @@ namespace sol {
}
}
}
}
else {
agnostic_lua_call_wrapper<F, is_index, is_variable, checked, boost, clean_stack> alcw{};
return alcw.call(L, std::forward<Fx>(fx), std::forward<Args>(args)...);
@ -541,55 +568,6 @@ namespace sol {
}
};
template <typename T, typename F, bool is_variable, bool checked, int boost, bool clean_stack>
struct lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, std::enable_if_t<std::is_member_object_pointer<F>::value>> {
using traits_type = lua_bind_traits<F>;
using wrap = wrapper<F>;
using object_type = typename wrap::object_type;
template <typename V>
static int call(lua_State* L, V&& v, object_type& o) {
using returns_list = typename wrap::returns_list;
using caller = typename wrap::caller;
F f(std::forward<V>(v));
return stack::call_into_lua<checked, clean_stack>(returns_list(), types<>(), L, boost + (is_variable ? 3 : 2), caller(), f, o);
}
template <typename V>
static int call(lua_State* L, V&& f) {
using Ta = std::conditional_t<std::is_void<T>::value, object_type, T>;
#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE
auto maybeo = stack::check_get<Ta*>(L, 1);
if (!maybeo || maybeo.value() == nullptr) {
if (is_variable) {
return luaL_error(L, "sol: 'self' argument is lua_nil (bad '.' access?)");
}
return luaL_error(L, "sol: 'self' argument is lua_nil (pass 'self' as first argument)");
}
object_type* o = static_cast<object_type*>(maybeo.value());
return call(L, f, *o);
#else
object_type& o = static_cast<object_type&>(*stack::get<non_null<Ta*>>(L, 1));
return call(L, f, o);
#endif // Safety
}
};
template <typename T, typename F, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
struct lua_call_wrapper<T, readonly_wrapper<F>, false, is_variable, checked, boost, clean_stack, C> {
using traits_type = lua_bind_traits<F>;
using wrap = wrapper<F>;
using object_type = typename wrap::object_type;
static int call(lua_State* L, const readonly_wrapper<F>&) {
return luaL_error(L, "sol: cannot write to a sol::readonly variable");
}
static int call(lua_State* L, const readonly_wrapper<F>& rw, object_type&) {
return call(L, rw);
}
};
template <typename T, typename F, bool is_index, bool is_variable, bool checked, int boost, bool clean_stack, typename C>
struct lua_call_wrapper<T, readonly_wrapper<F>, is_index, is_variable, checked, boost, clean_stack, C> {
using traits_type = lua_bind_traits<F>;
@ -603,7 +581,7 @@ namespace sol {
}
else {
lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
return lcw.call(L, std::move(rw.get_value()), o);
return lcw.call(L, std::move(rw.value()), o);
}
}
@ -614,7 +592,7 @@ namespace sol {
}
else {
lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
return lcw.call(L, rw.get_value(), o);
return lcw.call(L, rw.value(), o);
}
}
@ -625,7 +603,7 @@ namespace sol {
}
else {
lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
return lcw.call(L, rw.get_value());
return lcw.call(L, rw.value());
}
}
@ -636,7 +614,7 @@ namespace sol {
}
else {
lua_call_wrapper<T, F, true, is_variable, checked, boost, clean_stack, C> lcw;
return lcw.call(L, rw.get_value(), o);
return lcw.call(L, rw.value(), o);
}
}
};

View File

@ -24,43 +24,44 @@
#ifndef SOL_EBCO_HPP
#define SOL_EBCO_HPP
#include <type_traits>
#include <utility>
namespace sol {
namespace sol { namespace detail {
template <typename T, typename = void>
template <typename T, std::size_t tag = 0, typename = void>
struct ebco {
T value;
T value_;
ebco() = default;
ebco(const ebco&) = default;
ebco(ebco&&) = default;
ebco& operator=(const ebco&) = default;
ebco& operator=(ebco&&) = default;
ebco(const T& v) : value(v){};
ebco(T&& v) : value(std::move(v)){};
ebco(const T& v) : value_(v){};
ebco(T&& v) : value_(std::move(v)){};
ebco& operator=(const T& v) {
value = v;
}
ebco& operator=(T&& v) {
value = std::move(v);
value_ = std::move(v);
};
template <typename Arg, typename... Args,
typename = std::enable_if_t<!std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>,
ebco> && !std::is_same_v<std::remove_reference_t<std::remove_cv_t<Arg>>, T>>>
ebco(Arg&& arg, Args&&... args) : T(std::forward<Arg>(arg), std::forward<Args>(args)...){};
T& get_value() {
return value;
T& value() {
return value_;
}
T const& get_value() const {
return value;
T const& value() const {
return value_;
}
};
template <typename T>
struct ebco<T, std::enable_if_t<std::is_class_v<T> && !std::is_final_v<T>>> : T {
template <typename T, std::size_t tag>
struct ebco<T, tag, std::enable_if_t<!std::is_reference_v<T> && std::is_class_v<T> && !std::is_final_v<T>>> : T {
ebco() = default;
ebco(const ebco&) = default;
ebco(ebco&&) = default;
@ -80,15 +81,15 @@ namespace sol {
static_cast<T&>(*this) = std::move(v);
};
T& get_value() {
T& value() {
return static_cast<T&>(*this);
}
T const& get_value() const {
T const& value() const {
return static_cast<T const&>(*this);
}
};
} // namespace sol
}} // namespace sol::detail
#endif // SOL_EBCO_HPP

View File

@ -35,26 +35,31 @@ namespace sol {
}
template <typename R, typename W>
struct property_wrapper : ebco<R>, ebco<W> {
struct property_wrapper : detail::ebco<R, 0>, detail::ebco<W, 1> {
private:
using read_base_t = detail::ebco<R, 0>;
using write_base_t = detail::ebco<W, 1>;
public:
template <typename Rx, typename Wx>
property_wrapper(Rx&& r, Wx&& w)
: ebco<R>(std::forward<Rx>(r)), ebco<W>(std::forward<Wx>(w)) {
: read_base_t(std::forward<Rx>(r)), write_base_t(std::forward<Wx>(w)) {
}
W& write() {
return ebco<W>::get_value();
return write_base_t::value();
}
const W& write() const {
return ebco<W>::get_value();
return write_base_t::value();
}
R& read() {
return ebco<R>::get_value();
return read_base_t::value();
}
const R& read() const {
return ebco<R>::get_value();
return read_base_t::value();
}
};
@ -92,17 +97,18 @@ namespace sol {
}
template <typename T>
struct readonly_wrapper : ebco<T> {
struct readonly_wrapper : detail::ebco<T> {
private:
using base_t = ebco<T>;
using base_t = detail::ebco<T>;
public:
using base_t::base_t;
operator T&() {
return base_t::get_value();
return base_t::value();
}
operator const T&() const {
return base_t::get_value();
return base_t::value();
}
};
@ -113,9 +119,10 @@ namespace sol {
}
template <typename T>
struct var_wrapper : ebco<T> {
struct var_wrapper : detail::ebco<T> {
private:
using base_t = ebco<T>;
using base_t = detail::ebco<T>;
public:
using base_t::base_t;
};

View File

@ -299,6 +299,7 @@ namespace sol { namespace stack {
#endif
continue;
}
push_back_at_end(meta::has_push_back<Tu>(), t, L, arr, idx);
++idx;
lua_pop(L, lua_size<V>::value);

View File

@ -33,6 +33,7 @@
#include "string_view.hpp"
#include "raii.hpp"
#include "filters.hpp"
#include "ebco.hpp"
#include <array>
#include <initializer_list>
@ -496,10 +497,11 @@ namespace sol {
}
template <typename T>
struct force_t {
T arg;
force_t(T value) : arg(value) {}
struct force_t : detail::ebco<T> {
private:
using base_t = detail::ebco<T>;
public:
using base_t::base_t;
};
template <typename T>
@ -1083,7 +1085,7 @@ namespace sol {
struct lua_type_of<meta_function> : std::integral_constant<type, type::string> {};
#if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES
#ifdef SOL_STD_VARIANT
#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT
template <typename... Tn>
struct lua_type_of<std::variant<Tn...>> : std::integral_constant<type, type::poly> {};
#endif // SOL_STD_VARIANT

View File

@ -0,0 +1,26 @@
// sol3
// The MIT License (MIT)
// Copyright (c) 2013-2018 Rapptz, ThePhD and contributors
// Permission is hereby granted, free of charge, to any person obtaining a copy of
// this software and associated documentation files (the "Software"), to deal in
// the Software without restriction, including without limitation the rights to
// use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
// the Software, and to permit persons to whom the Software is furnished to do so,
// subject to the following conditions:
// The above copyright notice and this permission notice shall be included in all
// copies or substantial portions of the Software.
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
// FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
// COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER
// IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
// CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
#include "sol_defines.hpp"
#include <sol/ebco.hpp>