Index: include/__refstring =================================================================== --- include/__refstring (revision 0) +++ include/__refstring (working copy) @@ -0,0 +1,139 @@ +//===------------------------ __refstring ---------------------------------===// +// +// The LLVM Compiler Infrastructure +// +// This file is dual licensed under the MIT and the University of Illinois Open +// Source Licenses. See LICENSE.TXT for details. +// +//===----------------------------------------------------------------------===// + +#ifndef _LIBCPP___REFSTRING +#define _LIBCPP___REFSTRING + +#include <__config> +#include +#include +#if __APPLE__ +#include +#include +#endif + +_LIBCPP_BEGIN_NAMESPACE_STD + +class _LIBCPP_HIDDEN __libcpp_refstring +{ +private: + const char* str_; + + typedef int count_t; + + struct _Rep_base + { + std::size_t len; + std::size_t cap; + count_t count; + }; + + static + _Rep_base* + rep_from_data(const char *data_) _NOEXCEPT + { + char *data = const_cast(data_); + return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); + } + static + char * + data_from_rep(_Rep_base *rep) _NOEXCEPT + { + char *data = reinterpret_cast(rep); + return data + sizeof(*rep); + } + +#if __APPLE__ + static + const char* + compute_gcc_empty_string_storage() _NOEXCEPT + { + void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); + if (handle == nullptr) + return nullptr; + void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); + if (sym == nullptr) + return nullptr; + return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); + } + + static + const char* + get_gcc_empty_string_storage() _NOEXCEPT + { + static const char* p = compute_gcc_empty_string_storage(); + return p; + } + + bool + uses_refcount() const + { + return str_ != get_gcc_empty_string_storage(); + } +#else + bool + uses_refcount() const + { + return true; + } +#endif + +public: + explicit __libcpp_refstring(const char* msg) { + std::size_t len = strlen(msg); + _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); + rep->len = len; + rep->cap = len; + rep->count = 0; + char *data = data_from_rep(rep); + std::memcpy(data, msg, len + 1); + str_ = data; + } + + __libcpp_refstring(const __libcpp_refstring& s) _NOEXCEPT : str_(s.str_) + { + if (uses_refcount()) + __sync_add_and_fetch(&rep_from_data(str_)->count, 1); + } + + __libcpp_refstring& operator=(const __libcpp_refstring& s) _NOEXCEPT + { + bool adjust_old_count = uses_refcount(); + struct _Rep_base *old_rep = rep_from_data(str_); + str_ = s.str_; + if (uses_refcount()) + __sync_add_and_fetch(&rep_from_data(str_)->count, 1); + if (adjust_old_count) + { + if (__sync_add_and_fetch(&old_rep->count, count_t(-1)) < 0) + { + ::operator delete(old_rep); + } + } + return *this; + } + + ~__libcpp_refstring() + { + if (uses_refcount()) + { + _Rep_base* rep = rep_from_data(str_); + if (__sync_add_and_fetch(&rep->count, count_t(-1)) < 0) + { + ::operator delete(rep); + } + } + } + + const char* c_str() const _NOEXCEPT {return str_;} +}; + +_LIBCPP_END_NAMESPACE_STD + +#endif //_LIBCPP___REFSTRING Index: include/stdexcept =================================================================== --- include/stdexcept (revision 206802) +++ include/stdexcept (working copy) @@ -50,6 +50,14 @@ #pragma GCC system_header #endif +#ifndef _LIBCPP___REFSTRING +_LIBCPP_BEGIN_NAMESPACE_STD +class _LIBCPP_HIDDEN __libcpp_refstring { + const char *__imp_; +}; +_LIBCPP_END_NAMESPACE_STD +#endif + namespace std // purposefully not using versioning namespace { @@ -57,7 +65,7 @@ : public exception { private: - void* __imp_; + _VSTD::__libcpp_refstring __imp_; public: explicit logic_error(const string&); explicit logic_error(const char*); @@ -74,7 +82,7 @@ : public exception { private: - void* __imp_; + _VSTD::__libcpp_refstring __imp_; public: explicit runtime_error(const string&); explicit runtime_error(const char*); Index: src/stdexcept.cpp =================================================================== --- src/stdexcept.cpp (revision 206802) +++ src/stdexcept.cpp (working copy) @@ -7,124 +7,42 @@ // //===----------------------------------------------------------------------===// +#include "__refstring" #include "stdexcept" #include "new" #include "string" -#include -#include -#include -#include #include "system_error" #ifndef __has_include #define __has_include(inc) 0 #endif -#ifdef __APPLE__ +/* For _LIBCPPABI_VERSION */ +#if __has_include() || defined(__APPLE_) || defined(LIBCXXRT) #include -#elif defined(LIBCXXRT) || __has_include() -#include #endif -// Note: optimize for size +static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), ""); -#if ! defined(_LIBCPP_MSVC) -#pragma GCC visibility push(hidden) -#endif - -namespace -{ - -class __libcpp_nmstr -{ -private: - const char* str_; - - typedef std::size_t unused_t; - typedef std::ptrdiff_t count_t; - - static const std::ptrdiff_t offset = static_cast(2*sizeof(unused_t) + - sizeof(count_t)); - - count_t& count() const _NOEXCEPT {return *const_cast(reinterpret_cast(str_ - sizeof(count_t)));} -public: - explicit __libcpp_nmstr(const char* msg); - __libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT; - __libcpp_nmstr& operator=(const __libcpp_nmstr& s) _NOEXCEPT; - ~__libcpp_nmstr(); - const char* c_str() const _NOEXCEPT {return str_;} -}; - -__libcpp_nmstr::__libcpp_nmstr(const char* msg) -{ - std::size_t len = strlen(msg); - str_ = new char[len + 1 + offset]; - unused_t* c = reinterpret_cast(const_cast(str_)); - c[0] = c[1] = len; - str_ += offset; - count() = 0; - std::memcpy(const_cast(c_str()), msg, len + 1); -} - -inline -__libcpp_nmstr::__libcpp_nmstr(const __libcpp_nmstr& s) _NOEXCEPT - : str_(s.str_) -{ - __sync_add_and_fetch(&count(), 1); -} - -__libcpp_nmstr& -__libcpp_nmstr::operator=(const __libcpp_nmstr& s) _NOEXCEPT -{ - const char* p = str_; - str_ = s.str_; - __sync_add_and_fetch(&count(), 1); - if (__sync_add_and_fetch(reinterpret_cast(const_cast(p)-sizeof(count_t)), count_t(-1)) < 0) - delete [] (p-offset); - return *this; -} - -inline -__libcpp_nmstr::~__libcpp_nmstr() -{ - if (__sync_add_and_fetch(&count(), count_t(-1)) < 0) - delete [] (str_ - offset); -} - -} - -#if ! defined(_LIBCPP_MSVC) -#pragma GCC visibility pop -#endif - namespace std // purposefully not using versioning namespace { -logic_error::logic_error(const string& msg) +logic_error::logic_error(const string& msg) : __imp_(msg.c_str()) { - __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_); - ::new(s) __libcpp_nmstr(msg.c_str()); } -logic_error::logic_error(const char* msg) +logic_error::logic_error(const char* msg) : __imp_(msg) { - __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_); - ::new(s) __libcpp_nmstr(msg); } -logic_error::logic_error(const logic_error& le) _NOEXCEPT +logic_error::logic_error(const logic_error& le) _NOEXCEPT : __imp_(le.__imp_) { - __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_); - const __libcpp_nmstr *s2 = reinterpret_cast(&le.__imp_); - ::new(s) __libcpp_nmstr(*s2); } logic_error& logic_error::operator=(const logic_error& le) _NOEXCEPT { - __libcpp_nmstr *s1 = reinterpret_cast<__libcpp_nmstr *>(&__imp_); - const __libcpp_nmstr *s2 = reinterpret_cast(&le.__imp_); - *s1 = *s2; + __imp_ = le.__imp_; return *this; } @@ -132,44 +50,33 @@ logic_error::~logic_error() _NOEXCEPT { - __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_); - s->~__libcpp_nmstr(); } const char* logic_error::what() const _NOEXCEPT { - const __libcpp_nmstr *s = reinterpret_cast(&__imp_); - return s->c_str(); + return __imp_.c_str(); } #endif -runtime_error::runtime_error(const string& msg) +runtime_error::runtime_error(const string& msg) : __imp_(msg.c_str()) { - __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_); - ::new(s) __libcpp_nmstr(msg.c_str()); } -runtime_error::runtime_error(const char* msg) +runtime_error::runtime_error(const char* msg) : __imp_(msg) { - __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_); - ::new(s) __libcpp_nmstr(msg); } runtime_error::runtime_error(const runtime_error& le) _NOEXCEPT + : __imp_(le.__imp_) { - __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_); - const __libcpp_nmstr *s2 = reinterpret_cast(&le.__imp_); - ::new(s) __libcpp_nmstr(*s2); } runtime_error& runtime_error::operator=(const runtime_error& le) _NOEXCEPT { - __libcpp_nmstr *s1 = reinterpret_cast<__libcpp_nmstr *>(&__imp_); - const __libcpp_nmstr *s2 = reinterpret_cast(&le.__imp_); - *s1 = *s2; + __imp_ = le.__imp_; return *this; } @@ -177,15 +84,12 @@ runtime_error::~runtime_error() _NOEXCEPT { - __libcpp_nmstr *s = reinterpret_cast<__libcpp_nmstr *>(&__imp_); - s->~__libcpp_nmstr(); } const char* runtime_error::what() const _NOEXCEPT { - const __libcpp_nmstr *s = reinterpret_cast(&__imp_); - return s->c_str(); + return __imp_.c_str(); } domain_error::~domain_error() _NOEXCEPT {}