aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorTim Adye <Tim.Adye@cern.ch>2021-06-04 15:59:38 +0100
committerJonathan Wakely <jwakely@redhat.com>2021-06-04 15:59:38 +0100
commitf6bb145c0bff19767931d37733be11c8acc6fa00 (patch)
tree369f46cbe40b2b8c2ee3bc73467bcebb07570723
parentf78f25f43864f38ae5a6a9fcce8f26c94fe45bcd (diff)
downloadgcc-f6bb145c0bff19767931d37733be11c8acc6fa00.zip
gcc-f6bb145c0bff19767931d37733be11c8acc6fa00.tar.gz
gcc-f6bb145c0bff19767931d37733be11c8acc6fa00.tar.bz2
libstdc++: Optimize std::any_cast by replacing indirect call
This significantly improves the performance of std::any_cast, by avoiding an indirect call to the _S_manage function through a function pointer. Before we make that indirect call we've already established that the contained value has the expected type, which means we also know the manager type, and so can call one of its members directly. We also know the precise type in the any::emplace functions, because we've just constructed that type, so we can use the new member there too. That doesn't seem to affect performance, but we might as well use the new _S_access function anyway. Signed-off-by: Tim Adye <Tim.Adye@cern.ch> Signed-off-by: Jonathan Wakely <jwakely@redhat.com> libstdc++-v3/ChangeLog: * include/std/any (any::_Manager::_S_access): New static function to access the contained value. (any::emplace, __any_caster): Use _S_access member of the manager type.
-rw-r--r--libstdc++-v3/include/std/any26
1 files changed, 17 insertions, 9 deletions
diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any
index 391e433..21120a9 100644
--- a/libstdc++-v3/include/std/any
+++ b/libstdc++-v3/include/std/any
@@ -263,9 +263,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
using _VTp = decay_t<_Tp>;
__do_emplace<_VTp>(std::forward<_Args>(__args)...);
- any::_Arg __arg;
- this->_M_manager(any::_Op_access, this, &__arg);
- return *static_cast<_VTp*>(__arg._M_obj);
+ return *any::_Manager<_VTp>::_S_access(_M_storage);
}
/// Emplace with an object created from @p __il and @p __args as
@@ -276,9 +274,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
using _VTp = decay_t<_Tp>;
__do_emplace<_VTp, _Up>(__il, std::forward<_Args>(__args)...);
- any::_Arg __arg;
- this->_M_manager(any::_Op_access, this, &__arg);
- return *static_cast<_VTp*>(__arg._M_obj);
+ return *any::_Manager<_VTp>::_S_access(_M_storage);
}
// modifiers
@@ -384,6 +380,14 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
void* __addr = &__storage._M_buffer;
::new (__addr) _Tp(std::forward<_Args>(__args)...);
}
+
+ static _Tp*
+ _S_access(const _Storage& __storage)
+ {
+ // The contained object is in __storage._M_buffer
+ const void* __addr = &__storage._M_buffer;
+ return static_cast<_Tp*>(const_cast<void*>(__addr));
+ }
};
// Manage external contained object.
@@ -405,6 +409,12 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
{
__storage._M_ptr = new _Tp(std::forward<_Args>(__args)...);
}
+ static _Tp*
+ _S_access(const _Storage& __storage)
+ {
+ // The contained object is in *__storage._M_ptr
+ return static_cast<_Tp*>(__storage._M_ptr);
+ }
};
};
@@ -511,9 +521,7 @@ _GLIBCXX_BEGIN_NAMESPACE_VERSION
#endif
)
{
- any::_Arg __arg;
- __any->_M_manager(any::_Op_access, __any, &__arg);
- return __arg._M_obj;
+ return any::_Manager<_Up>::_S_access(__any->_M_storage);
}
return nullptr;
}