From c37514ff623f1d8ea7cf9fa5a5af15ab70e4902b Mon Sep 17 00:00:00 2001 From: Benjamin Kosnik Date: Fri, 13 Jun 2003 05:45:57 +0000 Subject: [PATCH] allocator-inst.cc: Explicitly instantiate. 2003-06-12 Benjamin Kosnik * src/allocator-inst.cc: Explicitly instantiate. * include/ext/pool_allocator.h: Inhibit implicit instantiations. Tweaks. * config/linker-map.gnu: Add __pool_alloc bits. Tweaks. From-SVN: r67882 --- libstdc++-v3/ChangeLog | 7 ++ libstdc++-v3/config/linker-map.gnu | 122 ++++++++++++-------- libstdc++-v3/include/ext/pool_allocator.h | 182 ++++++++++++++++-------------- libstdc++-v3/src/allocator-inst.cc | 5 + 4 files changed, 181 insertions(+), 135 deletions(-) diff --git a/libstdc++-v3/ChangeLog b/libstdc++-v3/ChangeLog index 49d6ade..6397b28 100644 --- a/libstdc++-v3/ChangeLog +++ b/libstdc++-v3/ChangeLog @@ -1,3 +1,10 @@ +2003-06-12 Benjamin Kosnik + + * src/allocator-inst.cc: Explicitly instantiate. + * include/ext/pool_allocator.h: Inhibit implicit instantiations. + Tweaks. + * config/linker-map.gnu: Add __pool_alloc bits. Tweaks. + 2003-06-11 Benjamin Kosnik * acinclude.m4 (GLIBCPP_ENABLE_CSTDIO): Simplify. diff --git a/libstdc++-v3/config/linker-map.gnu b/libstdc++-v3/config/linker-map.gnu index 6723a05..2245cd2 100644 --- a/libstdc++-v3/config/linker-map.gnu +++ b/libstdc++-v3/config/linker-map.gnu @@ -55,12 +55,7 @@ GLIBCPP_3.4 { std::__num_base::_S_format_float*; std::__num_base::_S_format_int*; std::__num_base::_S_atoms_in; - std::__num_base::_S_atoms_out; - - # Needed only when generic cpu's atomicity.h is in use. - __gnu_cxx::_Atomic_add_mutex; - __gnu_cxx::_Atomic_add_mutex_once; - __gnu_cxx::__gthread_atomic_add_mutex_once + std::__num_base::_S_atoms_out }; # Names not in an 'extern' block are mangled names. @@ -78,28 +73,7 @@ GLIBCPP_3.4 { # bool has_facet _ZSt9has_facet*; - # operator new(size_t) - _Znw[jm]; - # operator new(size_t, std::nothrow_t const&) - _Znw[jm]RKSt9nothrow_t; - - # operator delete(void*) - _ZdlPv; - # operator delete(void*, std::nothrow_t const&) - _ZdlPvRKSt9nothrow_t; - - # operator new[](size_t) - _Zna[jm]; - # operator new[](size_t, std::nothrow_t const&) - _Zna[jm]RKSt9nothrow_t; - - # operator delete[](void*) - _ZdaPv; - # operator delete[](void*, std::nothrow_t const&) - _ZdaPvRKSt9nothrow_t; - - # vtable - _ZTVN9__gnu_cxx*; + # virtual table _ZTVNSt8ios_base7failureE; _ZTVNSt6locale5facetE; _ZTVS[a-z]; @@ -109,18 +83,15 @@ GLIBCPP_3.4 { _ZTVSt23__codecvt_abstract_baseI[cw]c11__mbstate_tE; _ZTVSt21__ctype_abstract_baseI[cw]E; + # VTT structure _ZTTS[a-z]; _ZTTSt[0-9][A-Za-z]*; _ZTTSt[0-9][0-9][A-Za-z]*; - # typeinfo - _ZTI[a-z]; + # typeinfo structure + _ZTIS[a-z]; _ZTINSt8ios_base7failureE; _ZTINSt6locale5facetE; - _ZTIN9__gnu_cxx*; - _ZTIP[a-z]; - _ZTIPK[a-z]; - _ZTIS[a-z]; _ZTISt[0-9][A-Za-z]*; _ZTISt[0-9][0-9][A-Za-z]*; _ZTISt11__timepunctI[cw]E; @@ -128,12 +99,9 @@ GLIBCPP_3.4 { _ZTISt21__ctype_abstract_baseI[cw]E; _ZTISt23__codecvt_abstract_baseI[cw]c11__mbstate_tE; - _ZTS[a-z]; + # typeinfo name _ZTSNSt8ios_base7failureE; _ZTSNSt6locale5facetE; - _ZTSN9__gnu_cxx*; - _ZTSP[a-z]; - _ZTSPK[a-z]; _ZTSS[a-z]; _ZTSSt[0-9][A-Za-z]*; _ZTSSt[0-9][0-9][A-Za-z]*; @@ -143,12 +111,11 @@ GLIBCPP_3.4 { _ZTSSt23__codecvt_abstract_baseI[cw]c11__mbstate_tE; # function-scope static objects requires a guard variable. - _ZGV*; + _ZGVNSt*; # virtual function thunks - _ZTh*; - _ZTv*; - _ZTc*; + _ZThn8_NS*; + _ZTv0_n12_NS*; # std::__convert_to_v _ZSt14__convert_to_v*; @@ -187,6 +154,18 @@ GLIBCPP_3.4 { __signbitf; __signbitl; + # __gnu_cxx::__pool_alloc + _ZN9__gnu_cxx12__pool_allocILb1ELi0EE8allocateE[jm]; + _ZN9__gnu_cxx12__pool_allocILb1ELi0EE10deallocateEPv[jm]; + + # __gnu_cxx::stdio_sync_filebuf + _ZTVN9__gnu_cxx18stdio_sync_filebufI[cw]St11char_traitsI[cw]EEE; + + # Needed only when generic cpu's atomicity.h is in use. + _ZN9__gnu_cxx17_Atomic_add_mutexE; + _ZN9__gnu_cxx22_Atomic_add_mutex_onceE; + _ZN9__gnu_cxx31__gthread_atomic_add_mutex_onceEv; + local: *; }; @@ -227,15 +206,60 @@ CXXABI_1.3 { __gxx_personality_sj0; __dynamic_cast; - # __gnu_cxx::_verbose_terminate_handler() - _ZN9__gnu_cxx27__verbose_terminate_handlerEv; + # operator new(size_t) + _Znw[jm]; + # operator new(size_t, std::nothrow_t const&) + _Znw[jm]RKSt9nothrow_t; + + # operator delete(void*) + _ZdlPv; + # operator delete(void*, std::nothrow_t const&) + _ZdlPvRKSt9nothrow_t; - # typeinfo - _ZTIN10__cxxabi*; - _ZTSN10__cxxabi*; + # operator new[](size_t) + _Zna[jm]; + # operator new[](size_t, std::nothrow_t const&) + _Zna[jm]RKSt9nothrow_t; - # vtable - _ZTVN10__cxxabi*; + # operator delete[](void*) + _ZdaPv; + # operator delete[](void*, std::nothrow_t const&) + _ZdaPvRKSt9nothrow_t; + + # virtual table + _ZTVN10__cxxabiv117__class_type_infoE; + _ZTVN10__cxxabiv120__si_class_type_infoE; + _ZTVN10__cxxabiv121__vmi_class_type_infoE; + _ZTVN10__cxxabiv123__fundamental_type_infoE; + _ZTVN10__cxxabiv117__array_type_infoE; + _ZTVN10__cxxabiv120__function_type_infoE; + _ZTVN10__cxxabiv116__enum_type_infoE; + _ZTVN10__cxxabiv117__pbase_type_infoE; + _ZTVN10__cxxabiv119__pointer_type_infoE; + _ZTVN10__cxxabiv129__pointer_to_member_type_infoE; + + # typeinfo structure (and some names) + _ZTI[a-z]; + _ZTIP[a-z]; + _ZTIPK[a-z]; + _ZTIN10__cxxabiv117__class_type_infoE; + _ZTIN10__cxxabiv120__si_class_type_infoE; + _ZTIN10__cxxabiv121__vmi_class_type_infoE; + _ZTIN10__cxxabiv123__fundamental_type_infoE; + _ZTIN10__cxxabiv117__array_type_infoE; + _ZTIN10__cxxabiv120__function_type_infoE; + _ZTIN10__cxxabiv116__enum_type_infoE; + _ZTIN10__cxxabiv117__pbase_type_infoE; + _ZTIN10__cxxabiv119__pointer_type_infoE; + _ZTIN10__cxxabiv129__pointer_to_member_type_infoE; + + # typeinfo name + _ZTS[a-z]; + _ZTSP[a-z]; + _ZTSPK[a-z]; + + # __gnu_cxx::_verbose_terminate_handler() + _ZN9__gnu_cxx27__verbose_terminate_handlerEv; local: *; diff --git a/libstdc++-v3/include/ext/pool_allocator.h b/libstdc++-v3/include/ext/pool_allocator.h index 77d354f..2c6f87e 100644 --- a/libstdc++-v3/include/ext/pool_allocator.h +++ b/libstdc++-v3/include/ext/pool_allocator.h @@ -129,7 +129,7 @@ namespace __gnu_cxx // Allocates a chunk for nobjs of size size. nobjs may be reduced // if it is inconvenient to allocate the requested number. static char* - _S_chunk_alloc(size_t __size, int& __nobjs); + _S_chunk_alloc(size_t __n, int& __nobjs); // It would be nice to use _STL_auto_lock here. But we need a // test whether threads are in use. @@ -143,70 +143,13 @@ namespace __gnu_cxx public: // __n must be > 0 static void* - allocate(size_t __n) - { - void* __ret = 0; - - // If there is a race through here, assume answer from getenv - // will resolve in same direction. Inspired by techniques - // to efficiently support threading found in basic_string.h. - if (_S_force_new == 0) - { - if (getenv("GLIBCPP_FORCE_NEW")) - __atomic_add(&_S_force_new, 1); - else - __atomic_add(&_S_force_new, -1); - } - - if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0)) - __ret = __new_alloc::allocate(__n); - else - { - _Obj* volatile* __my_free_list = _S_free_list - + _S_freelist_index(__n); - // Acquire the lock here with a constructor call. This - // ensures that it is released in exit or during stack - // unwinding. - _Lock __lock_instance; - _Obj* __restrict__ __result = *__my_free_list; - if (__builtin_expect(__result == 0, 0)) - __ret = _S_refill(_S_round_up(__n)); - else - { - *__my_free_list = __result -> _M_free_list_link; - __ret = __result; - } - if (__builtin_expect(__ret == 0, 0)) - __throw_bad_alloc(); - } - return __ret; - } + allocate(size_t __n); // __p may not be 0 static void - deallocate(void* __p, size_t __n) - { - if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0)) - __new_alloc::deallocate(__p, __n); - else - { - _Obj* volatile* __my_free_list = _S_free_list - + _S_freelist_index(__n); - _Obj* __q = (_Obj*)__p; - - // Acquire the lock here with a constructor call. This - // ensures that it is released in exit or during stack - // unwinding. - _Lock __lock_instance; - __q -> _M_free_list_link = *__my_free_list; - *__my_free_list = __q; - } - } + deallocate(void* __p, size_t __n); }; - template _Atomic_word - __pool_alloc<__threads, __inst>::_S_force_new = 0; - template inline bool operator==(const __pool_alloc<__threads,__inst>&, @@ -220,16 +163,15 @@ namespace __gnu_cxx { return false; } - // We allocate memory in large chunks in order to avoid fragmenting the - // heap too much. We assume that __size is properly aligned. We hold + // Allocate memory in large chunks in order to avoid fragmenting the + // heap too much. Assume that __n is properly aligned. We hold // the allocation lock. template char* - __pool_alloc<__threads, __inst>:: - _S_chunk_alloc(size_t __size, int& __nobjs) + __pool_alloc<__threads, __inst>::_S_chunk_alloc(size_t __n, int& __nobjs) { char* __result; - size_t __total_bytes = __size * __nobjs; + size_t __total_bytes = __n * __nobjs; size_t __bytes_left = _S_end_free - _S_start_free; if (__bytes_left >= __total_bytes) @@ -238,10 +180,10 @@ namespace __gnu_cxx _S_start_free += __total_bytes; return __result ; } - else if (__bytes_left >= __size) + else if (__bytes_left >= __n) { - __nobjs = (int)(__bytes_left/__size); - __total_bytes = __size * __nobjs; + __nobjs = (int)(__bytes_left/__n); + __total_bytes = __n * __nobjs; __result = _S_start_free; _S_start_free += __total_bytes; return __result; @@ -253,32 +195,32 @@ namespace __gnu_cxx // Try to make use of the left-over piece. if (__bytes_left > 0) { - _Obj* volatile* __my_free_list = + _Obj* volatile* __free_list = _S_free_list + _S_freelist_index(__bytes_left); - ((_Obj*)(void*)_S_start_free) -> _M_free_list_link = *__my_free_list; - *__my_free_list = (_Obj*)(void*)_S_start_free; + ((_Obj*)(void*)_S_start_free)->_M_free_list_link = *__free_list; + *__free_list = (_Obj*)(void*)_S_start_free; } _S_start_free = (char*) __new_alloc::allocate(__bytes_to_get); if (_S_start_free == 0) { size_t __i; - _Obj* volatile* __my_free_list; + _Obj* volatile* __free_list; _Obj* __p; // Try to make do with what we have. That can't hurt. We // do not try smaller requests, since that tends to result // in disaster on multi-process machines. - __i = __size; + __i = __n; for (; __i <= (size_t) _S_max_bytes; __i += (size_t) _S_align) { - __my_free_list = _S_free_list + _S_freelist_index(__i); - __p = *__my_free_list; + __free_list = _S_free_list + _S_freelist_index(__i); + __p = *__free_list; if (__p != 0) { - *__my_free_list = __p -> _M_free_list_link; + *__free_list = __p -> _M_free_list_link; _S_start_free = (char*)__p; _S_end_free = _S_start_free + __i; - return _S_chunk_alloc(__size, __nobjs); + return _S_chunk_alloc(__n, __nobjs); // Any leftover piece will eventually make it to the // right free list. } @@ -290,11 +232,10 @@ namespace __gnu_cxx } _S_heap_size += __bytes_to_get; _S_end_free = _S_start_free + __bytes_to_get; - return _S_chunk_alloc(__size, __nobjs); + return _S_chunk_alloc(__n, __nobjs); } } - // Returns an object of size __n, and optionally adds to "size // __n"'s free list. We assume that __n is properly aligned. We // hold the allocation lock. @@ -304,7 +245,7 @@ namespace __gnu_cxx { int __nobjs = 20; char* __chunk = _S_chunk_alloc(__n, __nobjs); - _Obj* volatile* __my_free_list; + _Obj* volatile* __free_list; _Obj* __result; _Obj* __current_obj; _Obj* __next_obj; @@ -312,11 +253,11 @@ namespace __gnu_cxx if (1 == __nobjs) return __chunk; - __my_free_list = _S_free_list + _S_freelist_index(__n); + __free_list = _S_free_list + _S_freelist_index(__n); // Build free list in chunk. __result = (_Obj*)(void*)__chunk; - *__my_free_list = __next_obj = (_Obj*)(void*)(__chunk + __n); + *__free_list = __next_obj = (_Obj*)(void*)(__chunk + __n); for (__i = 1; ; __i++) { __current_obj = __next_obj; @@ -332,10 +273,69 @@ namespace __gnu_cxx return __result; } + template + void* + __pool_alloc<__threads, __inst>::allocate(size_t __n) + { + void* __ret = 0; + + // If there is a race through here, assume answer from getenv + // will resolve in same direction. Inspired by techniques + // to efficiently support threading found in basic_string.h. + if (_S_force_new == 0) + { + if (getenv("GLIBCPP_FORCE_NEW")) + __atomic_add(&_S_force_new, 1); + else + __atomic_add(&_S_force_new, -1); + } + + if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0)) + __ret = __new_alloc::allocate(__n); + else + { + _Obj* volatile* __free_list = _S_free_list + _S_freelist_index(__n); + // Acquire the lock here with a constructor call. This + // ensures that it is released in exit or during stack + // unwinding. + _Lock __lock_instance; + _Obj* __restrict__ __result = *__free_list; + if (__builtin_expect(__result == 0, 0)) + __ret = _S_refill(_S_round_up(__n)); + else + { + *__free_list = __result -> _M_free_list_link; + __ret = __result; + } + if (__builtin_expect(__ret == 0, 0)) + __throw_bad_alloc(); + } + return __ret; + } + + template + void + __pool_alloc<__threads, __inst>::deallocate(void* __p, size_t __n) + { + if ((__n > (size_t) _S_max_bytes) || (_S_force_new > 0)) + __new_alloc::deallocate(__p, __n); + else + { + _Obj* volatile* __free_list = _S_free_list + _S_freelist_index(__n); + _Obj* __q = (_Obj*)__p; + + // Acquire the lock here with a constructor call. This + // ensures that it is released in exit or during stack + // unwinding. + _Lock __lock_instance; + __q -> _M_free_list_link = *__free_list; + *__free_list = __q; + } + } template - _STL_mutex_lock - __pool_alloc<__threads, __inst>::_S_lock __STL_MUTEX_INITIALIZER; + typename __pool_alloc<__threads, __inst>::_Obj* volatile + __pool_alloc<__threads, __inst>::_S_free_list[_S_freelists]; template char* __pool_alloc<__threads, __inst>::_S_start_free = 0; @@ -347,8 +347,18 @@ namespace __gnu_cxx size_t __pool_alloc<__threads, __inst>::_S_heap_size = 0; template - typename __pool_alloc<__threads, __inst>::_Obj* volatile - __pool_alloc<__threads, __inst>::_S_free_list[_S_freelists]; + _STL_mutex_lock + __pool_alloc<__threads, __inst>::_S_lock __STL_MUTEX_INITIALIZER; + + template _Atomic_word + __pool_alloc<__threads, __inst>::_S_force_new = 0; + + // Inhibit implicit instantiations for required instantiations, + // which are defined via explicit instantiations elsewhere. + // NB: This syntax is a GNU extension. +#if _GLIBCPP_EXTERN_TEMPLATE + extern template class __pool_alloc; +#endif } // namespace __gnu_cxx namespace std diff --git a/libstdc++-v3/src/allocator-inst.cc b/libstdc++-v3/src/allocator-inst.cc index da8aeda..24a7b41 100644 --- a/libstdc++-v3/src/allocator-inst.cc +++ b/libstdc++-v3/src/allocator-inst.cc @@ -39,3 +39,8 @@ namespace std template class allocator; template class allocator; } // namespace std + +namespace __gnu_cxx +{ + template class __pool_alloc; +} // namespace __gnu_cxx -- 2.7.4