Index: libcxx/include/__config =================================================================== --- libcxx/include/__config +++ libcxx/include/__config @@ -102,6 +102,9 @@ # define _LIBCPP_ABI_OPTIMIZED_FUNCTION // All the regex constants must be distinct and nonzero. # define _LIBCPP_ABI_REGEX_CONSTANTS_NONZERO +// Re-worked external template instantiations for std::string with a focus on +// performance and fast-path inlining. +# define _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATIONS #elif _LIBCPP_ABI_VERSION == 1 # if !defined(_LIBCPP_OBJECT_FORMAT_COFF) // Enable compiling copies of now inline methods into the dylib to support Index: libcxx/include/__string =================================================================== --- libcxx/include/__string +++ libcxx/include/__string @@ -70,17 +70,23 @@ _LIBCPP_BEGIN_NAMESPACE_STD + +#ifdef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATIONS +#define _LIBCPP_STRING_EXTERN_TEMPLATE_LIST_ADDITIONAL(_Func, _CharType) \ + _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init_long_external(value_type const*, size_type)) +#else +#define _LIBCPP_STRING_EXTERN_TEMPLATE_LIST_ADDITIONAL(_Func, _CharType) +#endif + // The the extern template ABI lists are kept outside of to improve the // readability of that header. #define _LIBCPP_STRING_EXTERN_TEMPLATE_LIST(_Func, _CharType) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*, size_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::rfind(value_type const*, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::__init(value_type const*, size_type, size_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, value_type const*)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&, std::allocator<_CharType> const&)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_last_not_of(value_type const*, size_type, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find_first_not_of(value_type const*, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, size_type, value_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(value_type)) \ @@ -115,13 +121,12 @@ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::size_type basic_string<_CharType>::find(value_type const*, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, basic_string const&, size_type, size_type) const) \ _Func(_LIBCPP_FUNC_VIS int basic_string<_CharType>::compare(size_type, size_type, value_type const*, size_type) const) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::append(value_type const*)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::replace(size_type, size_type, basic_string const&, size_type, size_type)) \ _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::iterator basic_string<_CharType>::insert(basic_string::const_iterator, value_type)) \ _Func(_LIBCPP_FUNC_VIS void basic_string<_CharType>::resize(size_type, value_type)) \ - _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type)) - + _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::insert(size_type, basic_string const&, size_type, size_type)) \ + _LIBCPP_STRING_EXTERN_TEMPLATE_LIST_ADDITIONAL(_Func, _CharType) // char_traits Index: libcxx/include/string =================================================================== --- libcxx/include/string +++ libcxx/include/string @@ -872,7 +872,8 @@ basic_string(initializer_list<_CharT> __il, const _Allocator& __a); #endif // _LIBCPP_CXX03_LANG - inline ~basic_string(); + + ~basic_string(); _LIBCPP_INLINE_VISIBILITY operator __self_view() const _NOEXCEPT { return __self_view(data(), size()); } Index: libcxx/src/string.cpp =================================================================== --- libcxx/src/string.cpp +++ libcxx/src/string.cpp @@ -18,11 +18,26 @@ _LIBCPP_BEGIN_NAMESPACE_STD + template class _LIBCPP_CLASS_TEMPLATE_INSTANTIATION_VIS __basic_string_common; _LIBCPP_STRING_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) _LIBCPP_STRING_EXTERN_TEMPLATE_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) +#define _LIBCPP_STRING_EXTERN_TEMPLATE_LEGACY_DEFINITION_LIST(_Func, _CharType) \ + _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::basic_string(basic_string const&)) \ + _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>::~basic_string()) \ + _Func(_LIBCPP_FUNC_VIS basic_string<_CharType>& basic_string<_CharType>::operator=(basic_string const&)) + +#ifndef _LIBCPP_ABI_STRING_OPTIMIZED_EXTERNAL_INSTANTIATIONS + // These functions are no longer declared as external in ABI v1, but still need + // to be defined in the dylib to maintain ABI compatibility with older libc++ versions. + _LIBCPP_STRING_EXTERN_TEMPLATE_LEGACY_DEFINITION_LIST(_LIBCPP_EXTERN_TEMPLATE, char) + _LIBCPP_STRING_EXTERN_TEMPLATE_LEGACY_DEFINITION_LIST(_LIBCPP_EXTERN_TEMPLATE, wchar_t) + _LIBCPP_STRING_EXTERN_TEMPLATE_LEGACY_DEFINITION_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, char) + _LIBCPP_STRING_EXTERN_TEMPLATE_LEGACY_DEFINITION_LIST(_LIBCPP_EXTERN_TEMPLATE_DEFINE, wchar_t) +#endif + template string operator+, allocator >(char const*, string const&);