From 4fd197d956ca03813c78133b01bb9eef5459ffcf Mon Sep 17 00:00:00 2001 From: ThePhD Date: Sun, 10 Feb 2019 16:40:37 -0500 Subject: [PATCH] ebco optimizations for certain classes --- include/sol/call.hpp | 168 +++++++++++--------------- include/sol/ebco.hpp | 31 ++--- include/sol/property.hpp | 31 +++-- include/sol/stack_get_unqualified.hpp | 1 + include/sol/types.hpp | 12 +- tests/compile_tests/source/ebco.cpp | 26 ++++ 6 files changed, 142 insertions(+), 127 deletions(-) create mode 100644 tests/compile_tests/source/ebco.cpp diff --git a/include/sol/call.hpp b/include/sol/call.hpp index e572002f..a550edc6 100644 --- a/include/sol/call.hpp +++ b/include/sol/call.hpp @@ -368,11 +368,11 @@ namespace sol { template static int call(lua_State* L, F&& f) { if constexpr (is_index) { - constexpr bool is_stack = is_stack_based_v>; + constexpr bool is_stack = is_stack_based_v>; 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>) { @@ -381,7 +381,7 @@ namespace sol { else { using R = meta::unwrapped_t; if constexpr (std::is_assignable_v>, R>) { - detail::unwrap(f.get_value()) = stack::unqualified_get>(L, boost + (is_variable ? 3 : 1)); + detail::unwrap(f.value()) = stack::unqualified_get>(L, boost + (is_variable ? 3 : 1)); if (clean_stack) { lua_settop(L, 0); } @@ -482,54 +482,81 @@ namespace sol { } } else if constexpr (std::is_member_object_pointer_v) { - using traits_type = lua_bind_traits; using wrap = wrapper; using object_type = typename wrap::object_type; - using return_type = typename traits_type::return_type; - constexpr bool is_const = std::is_const_v>; - if constexpr (is_const) { - (void)fx; - (void)detail::swallow{ 0, (static_cast(args), 0)... }; - return luaL_error(L, "sol: cannot write to a readonly (const) variable"); - } - else { - using u_return_type = meta::unqualified_t; - constexpr bool is_assignable = std::is_copy_assignable_v || std::is_array_v; - if constexpr (!is_assignable) { - (void)fx; - (void)detail::swallow{ 0, ((void)args, 0)... }; - return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); + if constexpr (is_index) { + if constexpr (sizeof...(Args) < 1) { + using Ta = std::conditional_t, object_type, T>; +#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE + auto maybeo = stack::check_get(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(maybeo.value()); + return call(L, std::forward(fx), *o); +#else + object_type& o = static_cast(*stack::get>(L, 1)); + return call(L, std::forward(fx), o); +#endif // Safety } else { - using args_list = typename wrap::args_list; + using returns_list = typename wrap::returns_list; using caller = typename wrap::caller; - if constexpr (sizeof...(Args) > 0) { - return stack::call_into_lua(types(), - args_list(), - L, - boost + (is_variable ? 3 : 2), - caller(), - std::forward(fx), - std::forward(args)...); + return stack::call_into_lua( + returns_list(), types<>(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(fx), std::forward(args)...); + } + } + else { + using traits_type = lua_bind_traits; + using return_type = typename traits_type::return_type; + constexpr bool is_const = std::is_const_v>; + if constexpr (is_const) { + (void)fx; + (void)detail::swallow{ 0, (static_cast(args), 0)... }; + return luaL_error(L, "sol: cannot write to a readonly (const) variable"); + } + else { + using u_return_type = meta::unqualified_t; + constexpr bool is_assignable = std::is_copy_assignable_v || std::is_array_v; + if constexpr (!is_assignable) { + (void)fx; + (void)detail::swallow{ 0, ((void)args, 0)... }; + return luaL_error(L, "sol: cannot write to this variable: copy assignment/constructor not available"); } else { - using Ta = std::conditional_t, object_type, T>; -#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE - auto maybeo = stack::check_get(L, 1); - if (!maybeo || maybeo.value() == nullptr) { - if (is_variable) { - return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); - } - return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); + using args_list = typename wrap::args_list; + using caller = typename wrap::caller; + if constexpr (sizeof...(Args) > 0) { + return stack::call_into_lua(types(), + args_list(), + L, + boost + (is_variable ? 3 : 2), + caller(), + std::forward(fx), + std::forward(args)...); } - object_type* po = static_cast(maybeo.value()); - object_type& o = *po; -#else - object_type& o = static_cast(*stack::get>(L, 1)); -#endif // Safety + else { + using Ta = std::conditional_t, object_type, T>; + #if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE + auto maybeo = stack::check_get(L, 1); + if (!maybeo || maybeo.value() == nullptr) { + if (is_variable) { + return luaL_error(L, "sol: received nil for 'self' argument (bad '.' access?)"); + } + return luaL_error(L, "sol: received nil for 'self' argument (pass 'self' as first argument)"); + } + object_type* po = static_cast(maybeo.value()); + object_type& o = *po; + #else + object_type& o = static_cast(*stack::get>(L, 1)); + #endif // Safety - return stack::call_into_lua( - types(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(fx), o); + return stack::call_into_lua( + types(), args_list(), L, boost + (is_variable ? 3 : 2), caller(), std::forward(fx), o); + } } } } @@ -541,55 +568,6 @@ namespace sol { } }; - template - struct lua_call_wrapper::value>> { - using traits_type = lua_bind_traits; - using wrap = wrapper; - using object_type = typename wrap::object_type; - - template - 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)); - return stack::call_into_lua(returns_list(), types<>(), L, boost + (is_variable ? 3 : 2), caller(), f, o); - } - - template - static int call(lua_State* L, V&& f) { - using Ta = std::conditional_t::value, object_type, T>; -#if defined(SOL_SAFE_USERTYPE) && SOL_SAFE_USERTYPE - auto maybeo = stack::check_get(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(maybeo.value()); - return call(L, f, *o); -#else - object_type& o = static_cast(*stack::get>(L, 1)); - return call(L, f, o); -#endif // Safety - } - }; - - template - struct lua_call_wrapper, false, is_variable, checked, boost, clean_stack, C> { - using traits_type = lua_bind_traits; - using wrap = wrapper; - using object_type = typename wrap::object_type; - - static int call(lua_State* L, const readonly_wrapper&) { - return luaL_error(L, "sol: cannot write to a sol::readonly variable"); - } - - static int call(lua_State* L, const readonly_wrapper& rw, object_type&) { - return call(L, rw); - } - }; - template struct lua_call_wrapper, is_index, is_variable, checked, boost, clean_stack, C> { using traits_type = lua_bind_traits; @@ -603,7 +581,7 @@ namespace sol { } else { lua_call_wrapper 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 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 lcw; - return lcw.call(L, rw.get_value()); + return lcw.call(L, rw.value()); } } @@ -636,7 +614,7 @@ namespace sol { } else { lua_call_wrapper lcw; - return lcw.call(L, rw.get_value(), o); + return lcw.call(L, rw.value(), o); } } }; diff --git a/include/sol/ebco.hpp b/include/sol/ebco.hpp index 478d3137..c4815d3c 100644 --- a/include/sol/ebco.hpp +++ b/include/sol/ebco.hpp @@ -24,43 +24,44 @@ #ifndef SOL_EBCO_HPP #define SOL_EBCO_HPP +#include #include -namespace sol { +namespace sol { namespace detail { - template + template 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 >, ebco> && !std::is_same_v>, T>>> ebco(Arg&& arg, Args&&... args) : T(std::forward(arg), std::forward(args)...){}; - T& get_value() { - return value; + T& value() { + return value_; } - T const& get_value() const { - return value; + T const& value() const { + return value_; } }; - template - struct ebco && !std::is_final_v>> : T { + template + struct ebco && std::is_class_v && !std::is_final_v>> : T { ebco() = default; ebco(const ebco&) = default; ebco(ebco&&) = default; @@ -80,15 +81,15 @@ namespace sol { static_cast(*this) = std::move(v); }; - T& get_value() { + T& value() { return static_cast(*this); } - T const& get_value() const { + T const& value() const { return static_cast(*this); } }; -} // namespace sol +}} // namespace sol::detail #endif // SOL_EBCO_HPP diff --git a/include/sol/property.hpp b/include/sol/property.hpp index 8b536bab..cebcd6c5 100644 --- a/include/sol/property.hpp +++ b/include/sol/property.hpp @@ -35,26 +35,31 @@ namespace sol { } template - struct property_wrapper : ebco, ebco { + struct property_wrapper : detail::ebco, detail::ebco { + private: + using read_base_t = detail::ebco; + using write_base_t = detail::ebco; + + public: template property_wrapper(Rx&& r, Wx&& w) - : ebco(std::forward(r)), ebco(std::forward(w)) { + : read_base_t(std::forward(r)), write_base_t(std::forward(w)) { } W& write() { - return ebco::get_value(); + return write_base_t::value(); } const W& write() const { - return ebco::get_value(); + return write_base_t::value(); } R& read() { - return ebco::get_value(); + return read_base_t::value(); } const R& read() const { - return ebco::get_value(); + return read_base_t::value(); } }; @@ -92,17 +97,18 @@ namespace sol { } template - struct readonly_wrapper : ebco { + struct readonly_wrapper : detail::ebco { private: - using base_t = ebco; + using base_t = detail::ebco; + 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 - struct var_wrapper : ebco { + struct var_wrapper : detail::ebco { private: - using base_t = ebco; + using base_t = detail::ebco; + public: using base_t::base_t; }; diff --git a/include/sol/stack_get_unqualified.hpp b/include/sol/stack_get_unqualified.hpp index ca291e28..34887d06 100644 --- a/include/sol/stack_get_unqualified.hpp +++ b/include/sol/stack_get_unqualified.hpp @@ -299,6 +299,7 @@ namespace sol { namespace stack { #endif continue; } + push_back_at_end(meta::has_push_back(), t, L, arr, idx); ++idx; lua_pop(L, lua_size::value); diff --git a/include/sol/types.hpp b/include/sol/types.hpp index 78632f82..dc0d399d 100644 --- a/include/sol/types.hpp +++ b/include/sol/types.hpp @@ -33,6 +33,7 @@ #include "string_view.hpp" #include "raii.hpp" #include "filters.hpp" +#include "ebco.hpp" #include #include @@ -496,10 +497,11 @@ namespace sol { } template - struct force_t { - T arg; - - force_t(T value) : arg(value) {} + struct force_t : detail::ebco { + private: + using base_t = detail::ebco; + public: + using base_t::base_t; }; template @@ -1083,7 +1085,7 @@ namespace sol { struct lua_type_of : std::integral_constant {}; #if defined(SOL_CXX17_FEATURES) && SOL_CXX17_FEATURES -#ifdef SOL_STD_VARIANT +#if defined(SOL_STD_VARIANT) && SOL_STD_VARIANT template struct lua_type_of> : std::integral_constant {}; #endif // SOL_STD_VARIANT diff --git a/tests/compile_tests/source/ebco.cpp b/tests/compile_tests/source/ebco.cpp new file mode 100644 index 00000000..e235f92f --- /dev/null +++ b/tests/compile_tests/source/ebco.cpp @@ -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