diff options
author | Alon Zakai <alonzakai@gmail.com> | 2012-12-10 12:34:54 -0800 |
---|---|---|
committer | Alon Zakai <alonzakai@gmail.com> | 2012-12-21 10:47:39 -0800 |
commit | 34b153227d5343128cb36931b4dbb27e378372a5 (patch) | |
tree | c6f84632bd072e594f38d56a773f1b4496323dbc /system/lib/libcxxabi/src/stdexcept.cpp | |
parent | e9fe31fb2f629a2b94809c7f9a91577425728b1e (diff) |
update libcxxabi
Diffstat (limited to 'system/lib/libcxxabi/src/stdexcept.cpp')
-rw-r--r-- | system/lib/libcxxabi/src/stdexcept.cpp | 77 |
1 files changed, 62 insertions, 15 deletions
diff --git a/system/lib/libcxxabi/src/stdexcept.cpp b/system/lib/libcxxabi/src/stdexcept.cpp index 4aa962d0..de859db4 100644 --- a/system/lib/libcxxabi/src/stdexcept.cpp +++ b/system/lib/libcxxabi/src/stdexcept.cpp @@ -14,6 +14,11 @@ #include <cstdint> #include <cstddef> +#if __APPLE__ +#include <dlfcn.h> +#include <mach-o/dyld.h> +#endif + // Note: optimize for size #pragma GCC visibility push(hidden) @@ -26,13 +31,39 @@ class __libcpp_nmstr private: const char* str_; - typedef std::size_t unused_t; - typedef std::int32_t count_t; - - static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(2*sizeof(unused_t) + - sizeof(count_t)); + typedef int count_t; + + struct _Rep_base + { + std::size_t len; + std::size_t cap; + count_t count; + }; + + static const std::ptrdiff_t offset = static_cast<std::ptrdiff_t>(sizeof(_Rep_base)); + + count_t& count() const _NOEXCEPT {return ((_Rep_base*)(str_ - offset))->count;} + +#if __APPLE__ + static + const void* + compute_gcc_empty_string_storage() _LIBCPP_CANTTHROW + { + void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); + if (handle == 0) + return 0; + return (const char*)dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE") + offset; + } + + static + const void* + get_gcc_empty_string_storage() _LIBCPP_CANTTHROW + { + static const void* p = compute_gcc_empty_string_storage(); + return p; + } +#endif - count_t& count() const _NOEXCEPT {return (count_t&)(*(str_ - sizeof(count_t)));} public: explicit __libcpp_nmstr(const char* msg); __libcpp_nmstr(const __libcpp_nmstr& s) _LIBCPP_CANTTHROW; @@ -44,9 +75,9 @@ public: __libcpp_nmstr::__libcpp_nmstr(const char* msg) { std::size_t len = strlen(msg); - str_ = new char[len + 1 + offset]; - unused_t* c = (unused_t*)str_; - c[0] = c[1] = len; + str_ = static_cast<const char*>(::operator new(len + 1 + offset)); + _Rep_base* c = (_Rep_base*)str_; + c->len = c->cap = len; str_ += offset; count() = 0; std::strcpy(const_cast<char*>(c_str()), msg); @@ -56,7 +87,10 @@ inline __libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) : str_(s.str_) { - __sync_add_and_fetch(&count(), 1); +#if __APPLE__ + if (str_ != get_gcc_empty_string_storage()) +#endif + __sync_add_and_fetch(&count(), 1); } __libcpp_nmstr& @@ -64,17 +98,30 @@ __libcpp_nmstr::operator=(const __libcpp_nmstr& s) { const char* p = str_; str_ = s.str_; - __sync_add_and_fetch(&count(), 1); - if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), -1) < 0) - delete [] (p-offset); +#if __APPLE__ + if (str_ != get_gcc_empty_string_storage()) +#endif + __sync_add_and_fetch(&count(), 1); +#if __APPLE__ + if (p != get_gcc_empty_string_storage()) +#endif + if (__sync_add_and_fetch((count_t*)(p-sizeof(count_t)), count_t(-1)) < 0) + { + ::operator delete(const_cast<char*>(p-offset)); + } return *this; } inline __libcpp_nmstr::~__libcpp_nmstr() { - if (__sync_add_and_fetch(&count(), -1) < 0) - delete [] (str_ - offset); +#if __APPLE__ + if (str_ != get_gcc_empty_string_storage()) +#endif + if (__sync_add_and_fetch(&count(), count_t(-1)) < 0) + { + ::operator delete(const_cast<char*>(str_ - offset)); + } } } |