[gcc r10-10930] libstdc++: Optimize std::any_cast by replacing indirect call

Jonathan Wakely redi@gcc.gnu.org
Wed Aug 3 12:30:47 GMT 2022


https://gcc.gnu.org/g:d1b51c15312940779b1288b59973d88b9592dd23

commit r10-10930-gd1b51c15312940779b1288b59973d88b9592dd23
Author: Tim Adye <Tim.Adye@cern.ch>
Date:   Fri Jun 4 15:59:38 2021 +0100

    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.
    
    (cherry picked from commit f6bb145c0bff19767931d37733be11c8acc6fa00)

Diff:
---
 libstdc++-v3/include/std/any | 26 +++++++++++++++++---------
 1 file changed, 17 insertions(+), 9 deletions(-)

diff --git a/libstdc++-v3/include/std/any b/libstdc++-v3/include/std/any
index 1428858d600..de9569b6d40 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);
+	}
       };
   };
 
@@ -516,9 +526,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;
     }


More information about the Libstdc++-cvs mailing list