Skip to content

Commit cc736aa

Browse files
committed
[libc++] Simplify the __libcpp_refstring implementation
1 parent bb4ed55 commit cc736aa

File tree

2 files changed

+21
-91
lines changed

2 files changed

+21
-91
lines changed

libcxx/include/stdexcept

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -57,17 +57,16 @@ _LIBCPP_BEGIN_NAMESPACE_STD
5757

5858
# ifndef _LIBCPP_ABI_VCRUNTIME
5959
class _LIBCPP_HIDDEN __libcpp_refstring {
60-
const char* __imp_;
61-
62-
bool __uses_refcount() const;
60+
struct __rep;
61+
__rep* __imp_;
6362

6463
public:
6564
explicit __libcpp_refstring(const char* __msg);
6665
__libcpp_refstring(const __libcpp_refstring& __s) _NOEXCEPT;
6766
__libcpp_refstring& operator=(const __libcpp_refstring& __s) _NOEXCEPT;
6867
~__libcpp_refstring();
6968

70-
_LIBCPP_HIDE_FROM_ABI const char* c_str() const _NOEXCEPT { return __imp_; }
69+
_LIBCPP_HIDE_FROM_ABI const char* c_str() const _NOEXCEPT;
7170
};
7271
# endif // !_LIBCPP_ABI_VCRUNTIME
7372

libcxx/src/include/refstring.h

Lines changed: 18 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -15,112 +15,43 @@
1515
#include <cstring>
1616
#include <stdexcept>
1717

18-
// MacOS and iOS used to ship with libstdc++, and still support old applications
19-
// linking against libstdc++. The libc++ and libstdc++ exceptions are supposed
20-
// to be ABI compatible, such that they can be thrown from one library and caught
21-
// in the other.
22-
//
23-
// For that reason, we must look for libstdc++ in the same process and if found,
24-
// check the string stored in the exception object to see if it is the GCC empty
25-
// string singleton before manipulating the reference count. This is done so that
26-
// if an exception is created with a zero-length string in libstdc++, libc++abi
27-
// won't try to delete the memory.
28-
#if defined(__ENVIRONMENT_MAC_OS_X_VERSION_MIN_REQUIRED__) || defined(__ENVIRONMENT_IPHONE_OS_VERSION_MIN_REQUIRED__)
29-
# define _LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE
30-
# include <dlfcn.h>
31-
# include <mach-o/dyld.h>
32-
#endif
33-
3418
_LIBCPP_BEGIN_NAMESPACE_STD
3519

36-
namespace __refstring_imp {
37-
namespace {
38-
typedef int count_t;
20+
_LIBCPP_CLANG_DIAGNOSTIC_IGNORED("-Wc99-extensions")
3921

40-
struct _Rep_base {
41-
std::size_t len;
42-
std::size_t cap;
43-
count_t count;
22+
struct __libcpp_refstring::__rep {
23+
ptrdiff_t refcount;
24+
char data[];
4425
};
4526

46-
inline _Rep_base* rep_from_data(const char* data_) noexcept {
47-
char* data = const_cast<char*>(data_);
48-
return reinterpret_cast<_Rep_base*>(data - sizeof(_Rep_base));
49-
}
50-
51-
inline char* data_from_rep(_Rep_base* rep) noexcept {
52-
char* data = reinterpret_cast<char*>(rep);
53-
return data + sizeof(*rep);
54-
}
55-
56-
#if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE)
57-
inline const char* compute_gcc_empty_string_storage() noexcept {
58-
void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD);
59-
if (handle == nullptr)
60-
return nullptr;
61-
void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE");
62-
if (sym == nullptr)
63-
return nullptr;
64-
return data_from_rep(reinterpret_cast<_Rep_base*>(sym));
65-
}
66-
67-
inline const char* get_gcc_empty_string_storage() noexcept {
68-
static const char* p = compute_gcc_empty_string_storage();
69-
return p;
70-
}
71-
#endif
72-
73-
} // namespace
74-
} // namespace __refstring_imp
75-
76-
using namespace __refstring_imp;
77-
7827
inline __libcpp_refstring::__libcpp_refstring(const char* msg) {
7928
std::size_t len = strlen(msg);
80-
_Rep_base* rep = static_cast<_Rep_base*>(::operator new(sizeof(*rep) + len + 1));
81-
rep->len = len;
82-
rep->cap = len;
83-
rep->count = 0;
84-
char* data = data_from_rep(rep);
85-
std::memcpy(data, msg, len + 1);
86-
__imp_ = data;
29+
auto* rep = static_cast<__rep*>(::operator new(sizeof(__rep) + len + 1));
30+
rep->refcount = 0;
31+
std::memcpy(rep->data, msg, len + 1);
32+
__imp_ = rep;
8733
}
8834

8935
inline __libcpp_refstring::__libcpp_refstring(const __libcpp_refstring& s) noexcept : __imp_(s.__imp_) {
90-
if (__uses_refcount())
91-
__libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
36+
__libcpp_atomic_add(&__imp_->refcount, 1);
9237
}
9338

9439
inline __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) noexcept {
95-
bool adjust_old_count = __uses_refcount();
96-
struct _Rep_base* old_rep = rep_from_data(__imp_);
97-
__imp_ = s.__imp_;
98-
if (__uses_refcount())
99-
__libcpp_atomic_add(&rep_from_data(__imp_)->count, 1);
100-
if (adjust_old_count) {
101-
if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0) {
102-
::operator delete(old_rep);
103-
}
104-
}
40+
__rep* old_rep = __imp_;
41+
__imp_ = s.__imp_;
42+
__libcpp_atomic_add(&__imp_->refcount, 1);
43+
44+
if (__libcpp_atomic_add(&old_rep->refcount, ptrdiff_t(-1)) < 0)
45+
::operator delete(old_rep);
10546
return *this;
10647
}
10748

10849
inline __libcpp_refstring::~__libcpp_refstring() {
109-
if (__uses_refcount()) {
110-
_Rep_base* rep = rep_from_data(__imp_);
111-
if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) {
112-
::operator delete(rep);
113-
}
114-
}
50+
if (__libcpp_atomic_add(&__imp_->refcount, ptrdiff_t(-1)) < 0)
51+
::operator delete(__imp_);
11552
}
11653

117-
inline bool __libcpp_refstring::__uses_refcount() const {
118-
#if defined(_LIBCPP_CHECK_FOR_GCC_EMPTY_STRING_STORAGE)
119-
return __imp_ != get_gcc_empty_string_storage();
120-
#else
121-
return true;
122-
#endif
123-
}
54+
inline const char* __libcpp_refstring::c_str() const noexcept { return __imp_->data; }
12455

12556
_LIBCPP_END_NAMESPACE_STD
12657

0 commit comments

Comments
 (0)