Skip to content

Commit 956cfa6

Browse files
authored
[libc++] Refactor num_get optimization to not be ABI breaking (#121690)
``` ---------------------------------------------------- Benchmark old new ---------------------------------------------------- BM_num_get<bool> 81.8 ns 79.6 ns BM_num_get<long> 80.2 ns 75.4 ns BM_num_get<long long> 81.5 ns 76.4 ns BM_num_get<unsigned short> 82.5 ns 78.4 ns BM_num_get<unsigned int> 82.8 ns 78.6 ns BM_num_get<unsigned long> 81.2 ns 78.1 ns BM_num_get<unsigned long long> 83.6 ns 76.7 ns BM_num_get<float> 119 ns 120 ns BM_num_get<double> 113 ns 109 ns BM_num_get<long double> 115 ns 119 ns BM_num_get<void*> 147 ns 139 ns ```
1 parent 467b3d0 commit 956cfa6

File tree

3 files changed

+52
-57
lines changed

3 files changed

+52
-57
lines changed

Diff for: libcxx/include/__configuration/abi.h

-2
Original file line numberDiff line numberDiff line change
@@ -57,8 +57,6 @@
5757
// because it changes the mangling of the virtual function located in the vtable, which
5858
// changes how it gets signed.
5959
# define _LIBCPP_ABI_BAD_FUNCTION_CALL_GOOD_WHAT_MESSAGE
60-
// Enable optimized version of __do_get_(un)signed which avoids redundant copies.
61-
# define _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
6260
// Give reverse_iterator<T> one data member of type T, not two.
6361
// Also, in C++17 and later, don't derive iterator types from std::iterator.
6462
# define _LIBCPP_ABI_NO_ITERATOR_BASES

Diff for: libcxx/include/locale

+42-55
Original file line numberDiff line numberDiff line change
@@ -400,8 +400,9 @@ struct __num_get : protected __num_get_base {
400400
unsigned*& __g_end,
401401
unsigned& __dc,
402402
_CharT* __atoms);
403-
# ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
404-
static string __stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
403+
404+
[[__deprecated__("This exists only for ABI compatibility")]] static string
405+
__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep);
405406
static int __stage2_int_loop(
406407
_CharT __ct,
407408
int __base,
@@ -414,55 +415,32 @@ struct __num_get : protected __num_get_base {
414415
unsigned*& __g_end,
415416
_CharT* __atoms);
416417

417-
# else
418-
static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) {
418+
_LIBCPP_HIDE_FROM_ABI static string __stage2_int_prep(ios_base& __iob, _CharT& __thousands_sep) {
419419
locale __loc = __iob.getloc();
420420
const numpunct<_CharT>& __np = use_facet<numpunct<_CharT> >(__loc);
421421
__thousands_sep = __np.thousands_sep();
422422
return __np.grouping();
423423
}
424424

425-
const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const { return __do_widen_p(__iob, __atoms); }
426-
427-
static int __stage2_int_loop(
428-
_CharT __ct,
429-
int __base,
430-
char* __a,
431-
char*& __a_end,
432-
unsigned& __dc,
433-
_CharT __thousands_sep,
434-
const string& __grouping,
435-
unsigned* __g,
436-
unsigned*& __g_end,
437-
const _CharT* __atoms);
425+
_LIBCPP_HIDE_FROM_ABI const _CharT* __do_widen(ios_base& __iob, _CharT* __atoms) const {
426+
return __do_widen_p(__iob, __atoms);
427+
}
438428

439429
private:
440430
template <typename _Tp>
441-
const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const {
431+
_LIBCPP_HIDE_FROM_ABI const _Tp* __do_widen_p(ios_base& __iob, _Tp* __atoms) const {
442432
locale __loc = __iob.getloc();
443433
use_facet<ctype<_Tp> >(__loc).widen(__src, __src + __int_chr_cnt, __atoms);
444434
return __atoms;
445435
}
446436

447-
const char* __do_widen_p(ios_base& __iob, char* __atoms) const {
437+
_LIBCPP_HIDE_FROM_ABI const char* __do_widen_p(ios_base& __iob, char* __atoms) const {
448438
(void)__iob;
449439
(void)__atoms;
450440
return __src;
451441
}
452-
# endif
453442
};
454443

455-
# ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
456-
template <class _CharT>
457-
string __num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep) {
458-
locale __loc = __iob.getloc();
459-
std::use_facet<ctype<_CharT> >(__loc).widen(__src, __src + __int_chr_cnt, __atoms);
460-
const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__loc);
461-
__thousands_sep = __np.thousands_sep();
462-
return __np.grouping();
463-
}
464-
# endif
465-
466444
template <class _CharT>
467445
string __num_get<_CharT>::__stage2_float_prep(
468446
ios_base& __iob, _CharT* __atoms, _CharT& __decimal_point, _CharT& __thousands_sep) {
@@ -475,18 +453,17 @@ string __num_get<_CharT>::__stage2_float_prep(
475453
}
476454

477455
template <class _CharT>
478-
int
479-
# ifndef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
480-
__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
481-
unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
482-
unsigned* __g, unsigned*& __g_end, _CharT* __atoms)
483-
# else
484-
__num_get<_CharT>::__stage2_int_loop(_CharT __ct, int __base, char* __a, char*& __a_end,
485-
unsigned& __dc, _CharT __thousands_sep, const string& __grouping,
486-
unsigned* __g, unsigned*& __g_end, const _CharT* __atoms)
487-
488-
# endif
489-
{
456+
int __num_get<_CharT>::__stage2_int_loop(
457+
_CharT __ct,
458+
int __base,
459+
char* __a,
460+
char*& __a_end,
461+
unsigned& __dc,
462+
_CharT __thousands_sep,
463+
const string& __grouping,
464+
unsigned* __g,
465+
unsigned*& __g_end,
466+
_CharT* __atoms) {
490467
if (__a_end == __a && (__ct == __atoms[24] || __ct == __atoms[25])) {
491468
*__a_end++ = __ct == __atoms[24] ? '+' : '-';
492469
__dc = 0;
@@ -856,14 +833,9 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_signed(
856833
// Stage 2
857834
char_type __thousands_sep;
858835
const int __atoms_size = __num_get_base::__int_chr_cnt;
859-
# ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
860836
char_type __atoms1[__atoms_size];
861837
const char_type* __atoms = this->__do_widen(__iob, __atoms1);
862838
string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
863-
# else
864-
char_type __atoms[__atoms_size];
865-
string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
866-
# endif
867839
string __buf;
868840
__buf.resize(__buf.capacity());
869841
char* __a = &__buf[0];
@@ -879,7 +851,17 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_signed(
879851
__a = &__buf[0];
880852
__a_end = __a + __tmp;
881853
}
882-
if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms))
854+
if (this->__stage2_int_loop(
855+
*__b,
856+
__base,
857+
__a,
858+
__a_end,
859+
__dc,
860+
__thousands_sep,
861+
__grouping,
862+
__g,
863+
__g_end,
864+
const_cast<char_type*>(__atoms)))
883865
break;
884866
}
885867
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(
905887
// Stage 2
906888
char_type __thousands_sep;
907889
const int __atoms_size = __num_get_base::__int_chr_cnt;
908-
# ifdef _LIBCPP_ABI_OPTIMIZED_LOCALE_NUM_GET
909890
char_type __atoms1[__atoms_size];
910891
const char_type* __atoms = this->__do_widen(__iob, __atoms1);
911892
string __grouping = this->__stage2_int_prep(__iob, __thousands_sep);
912-
# else
913-
char_type __atoms[__atoms_size];
914-
string __grouping = this->__stage2_int_prep(__iob, __atoms, __thousands_sep);
915-
# endif
916893
string __buf;
917894
__buf.resize(__buf.capacity());
918895
char* __a = &__buf[0];
@@ -928,7 +905,17 @@ _InputIterator num_get<_CharT, _InputIterator>::__do_get_unsigned(
928905
__a = &__buf[0];
929906
__a_end = __a + __tmp;
930907
}
931-
if (this->__stage2_int_loop(*__b, __base, __a, __a_end, __dc, __thousands_sep, __grouping, __g, __g_end, __atoms))
908+
if (this->__stage2_int_loop(
909+
*__b,
910+
__base,
911+
__a,
912+
__a_end,
913+
__dc,
914+
__thousands_sep,
915+
__grouping,
916+
__g,
917+
__g_end,
918+
const_cast<char_type*>(__atoms)))
932919
break;
933920
}
934921
if (__grouping.size() != 0 && __g_end - __g < __num_get_base::__num_get_buf_sz)

Diff for: libcxx/src/locale.cpp

+10
Original file line numberDiff line numberDiff line change
@@ -5650,6 +5650,16 @@ void moneypunct_byname<wchar_t, true>::init(const char* nm) {
56505650

56515651
void __do_nothing(void*) {}
56525652

5653+
// Legacy ABI __num_get functions - the new ones are _LIBCPP_HIDE_FROM_ABI
5654+
template <class _CharT>
5655+
string __num_get<_CharT>::__stage2_int_prep(ios_base& __iob, _CharT* __atoms, _CharT& __thousands_sep) {
5656+
locale __loc = __iob.getloc();
5657+
std::use_facet<ctype<_CharT> >(__loc).widen(__src, __src + __int_chr_cnt, __atoms);
5658+
const numpunct<_CharT>& __np = std::use_facet<numpunct<_CharT> >(__loc);
5659+
__thousands_sep = __np.thousands_sep();
5660+
return __np.grouping();
5661+
}
5662+
56535663
template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<char>;
56545664
_LIBCPP_IF_WIDE_CHARACTERS(template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS collate<wchar_t>;)
56555665

0 commit comments

Comments
 (0)