aboutsummaryrefslogtreecommitdiff
path: root/system/lib/libcxxabi/src/stdexcept.cpp
diff options
context:
space:
mode:
authorAlon Zakai <alonzakai@gmail.com>2012-12-10 12:34:54 -0800
committerAlon Zakai <alonzakai@gmail.com>2012-12-21 10:47:39 -0800
commit34b153227d5343128cb36931b4dbb27e378372a5 (patch)
treec6f84632bd072e594f38d56a773f1b4496323dbc /system/lib/libcxxabi/src/stdexcept.cpp
parente9fe31fb2f629a2b94809c7f9a91577425728b1e (diff)
update libcxxabi
Diffstat (limited to 'system/lib/libcxxabi/src/stdexcept.cpp')
-rw-r--r--system/lib/libcxxabi/src/stdexcept.cpp77
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));
+ }
}
}