From 6f7a1d6456b4ac90fecfc634370b42c40faea569 Mon Sep 17 00:00:00 2001 From: Nikolas Klauser Date: Sun, 5 Jan 2025 13:14:32 +0100 Subject: [PATCH] [libc++] Refactor num_get optimization to not be ABI breaking --- libcxx/include/__configuration/abi.h | 2 - libcxx/include/locale | 97 ++++++++++++---------------- libcxx/src/locale.cpp | 10 +++ 3 files changed, 52 insertions(+), 57 deletions(-) diff --git a/libcxx/include/__configuration/abi.h b/libcxx/include/__configuration/abi.h index c6ef6fdcdf96e..5e40e308c8926 100644 --- a/libcxx/include/__configuration/abi.h +++ b/libcxx/include/__configuration/abi.h @@ -57,8 +57,6 @@ // because it changes the mangling of the virtual function located in the vtable, which // changes how it gets signed. # define _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE -// Enable optimized version of __do_get_(un)signed which avoids redundant copies. -# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET // Give reverse_iterator one data member of type T, not two. // Also, in C++17 and later, don't derive iterator types from std::iterator. # define _LIBCPP_ABI_NO_ITERATOR_BASES diff --git a/libcxx/include/locale b/libcxx/include/locale index 5af674d19414b..be0f31cece671 100644 --- a/libcxx/include/locale +++ b/libcxx/include/locale @@ -400,8 +400,9 @@ struct __num_get : protected __num_get_base { unsigned*& __g_end, unsigned& __dc, _CharT* __atoms); -# ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET - static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep); + + [[__deprecated__("This exists only for ABI compatibility")]] static string + __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep); static int __stage2_int_loop( _CharT __ct, int __base, @@ -414,55 +415,32 @@ struct __num_get : protected __num_get_base { unsigned*& __g_end, _CharT* __atoms); -# else - static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) { + _LIBCPP_HIDE_FROM_ABI static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) { locale __loc = __iob.getloc(); const numpunct<_CharT>& __np = use_facet >(__loc); __thousands_sep = __np.thousands_sep(); return __np.grouping(); } - const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const { return __do_widen_p(__iob, __atoms); } - - static int __stage2_int_loop( - _CharT __ct, - int __base, - char* __a, - char*& __a_end, - unsigned& __dc, - _CharT __thousands_sep, - const string& __grouping, - unsigned* __g, - unsigned*& __g_end, - const _CharT* __atoms); + _LIBCPP_HIDE_FROM_ABI const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const { + return __do_widen_p(__iob, __atoms); + } private: template - const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const { + _LIBCPP_HIDE_FROM_ABI const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const { locale __loc = __iob.getloc(); use_facet >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); return __atoms; } - const char* __do_widen_p(ios_base& __iob, char* __atoms) const { + _LIBCPP_HIDE_FROM_ABI const char* __do_widen_p(ios_base& __iob, char* __atoms) const { (void)__iob; (void)__atoms; return __src; } -# endif }; -# ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET -template -string __num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep) { - locale __loc = __iob.getloc(); - std::use_facet >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); - const numpunct<_CharT>& __np = std::use_facet >(__loc); - __thousands_sep = __np.thousands_sep(); - return __np.grouping(); -} -# endif - template string __num_get<_CharT>::__stage2_float_prep( ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep) { @@ -475,18 +453,17 @@ string __num_get<_CharT>::__stage2_float_prep( } template -int -# ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET -__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end, - unsigned& __dc, _CharT __thousands_sep, const string& __grouping, - unsigned* __g, unsigned*& __g_end, _CharT* __atoms) -# else -__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end, - unsigned& __dc, _CharT __thousands_sep, const string& __grouping, - unsigned* __g, unsigned*& __g_end, const _CharT* __atoms) - -# endif -{ +int __num_get<_CharT>::__stage2_int_loop( + _CharT __ct, + int __base, + char* __a, + char*& __a_end, + unsigned& __dc, + _CharT __thousands_sep, + const string& __grouping, + unsigned* __g, + unsigned*& __g_end, + _CharT* __atoms) { if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) { *__a_end++ = __ct == __atoms[24] ? '+' : '-'; __dc = 0; @@ -856,14 +833,9 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_signed( // Stage 2 char_type __thousands_sep; const int __atoms_size = __num_get_base::__int_chr_cnt; -# ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET char_type __atoms1[__atoms_size]; const char_type* __atoms = this->__do_widen(__iob, __atoms1); string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); -# else - char_type __atoms[__atoms_size]; - string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep); -# endif string __buf; __buf.resize(__buf.capacity()); char* __a = &__buf[0]; @@ -879,7 +851,17 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_signed( __a = &__buf[0]; __a_end = __a + __tmp; } - if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms)) + if (this->__stage2_int_loop( + *__b, + __base, + __a, + __a_end, + __dc, + __thousands_sep, + __grouping, + __g, + __g_end, + const_cast(__atoms))) break; } if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) @@ -905,14 +887,9 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_unsigned( // Stage 2 char_type __thousands_sep; const int __atoms_size = __num_get_base::__int_chr_cnt; -# ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET char_type __atoms1[__atoms_size]; const char_type* __atoms = this->__do_widen(__iob, __atoms1); string __grouping = this->__stage2_int_prep(__iob, __thousands_sep); -# else - char_type __atoms[__atoms_size]; - string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep); -# endif string __buf; __buf.resize(__buf.capacity()); char* __a = &__buf[0]; @@ -928,7 +905,17 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_unsigned( __a = &__buf[0]; __a_end = __a + __tmp; } - if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms)) + if (this->__stage2_int_loop( + *__b, + __base, + __a, + __a_end, + __dc, + __thousands_sep, + __grouping, + __g, + __g_end, + const_cast(__atoms))) break; } if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz) diff --git a/libcxx/src/locale.cpp b/libcxx/src/locale.cpp index 81f3ad4974390..b5908bf8be725 100644 --- a/libcxx/src/locale.cpp +++ b/libcxx/src/locale.cpp @@ -5650,6 +5650,16 @@ void moneypunct_byname::init(const char* nm) { void __do_nothing(void*) {} +// Legacy ABI __num_get functions - the new ones are _LIBCPP_HIDE_FROM_ABI +template +string __num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep) { + locale __loc = __iob.getloc(); + std::use_facet >(__loc).widen(__src, __src + __int_chr_cnt, __atoms); + const numpunct<_CharT>& __np = std::use_facet >(__loc); + __thousands_sep = __np.thousands_sep(); + return __np.grouping(); +} + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate; _LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate;)