1*c05d8e5dSAndroid Build Coastguard Worker //===------------------------ __refstring ---------------------------------===// 2*c05d8e5dSAndroid Build Coastguard Worker // 3*c05d8e5dSAndroid Build Coastguard Worker // The LLVM Compiler Infrastructure 4*c05d8e5dSAndroid Build Coastguard Worker // 5*c05d8e5dSAndroid Build Coastguard Worker // This file is dual licensed under the MIT and the University of Illinois Open 6*c05d8e5dSAndroid Build Coastguard Worker // Source Licenses. See LICENSE.TXT for details. 7*c05d8e5dSAndroid Build Coastguard Worker // 8*c05d8e5dSAndroid Build Coastguard Worker //===----------------------------------------------------------------------===// 9*c05d8e5dSAndroid Build Coastguard Worker 10*c05d8e5dSAndroid Build Coastguard Worker // FIXME: This file is copied from libcxx/src/include/refstring.h. Instead of 11*c05d8e5dSAndroid Build Coastguard Worker // duplicating the file in libc++abi we should require that the libc++ sources 12*c05d8e5dSAndroid Build Coastguard Worker // are available when building libc++abi. 13*c05d8e5dSAndroid Build Coastguard Worker 14*c05d8e5dSAndroid Build Coastguard Worker #ifndef _LIBCPPABI_REFSTRING_H 15*c05d8e5dSAndroid Build Coastguard Worker #define _LIBCPPABI_REFSTRING_H 16*c05d8e5dSAndroid Build Coastguard Worker 17*c05d8e5dSAndroid Build Coastguard Worker #include <__config> 18*c05d8e5dSAndroid Build Coastguard Worker #include <stdexcept> 19*c05d8e5dSAndroid Build Coastguard Worker #include <cstddef> 20*c05d8e5dSAndroid Build Coastguard Worker #include <cstring> 21*c05d8e5dSAndroid Build Coastguard Worker #ifdef __APPLE__ 22*c05d8e5dSAndroid Build Coastguard Worker #include <dlfcn.h> 23*c05d8e5dSAndroid Build Coastguard Worker #include <mach-o/dyld.h> 24*c05d8e5dSAndroid Build Coastguard Worker #endif 25*c05d8e5dSAndroid Build Coastguard Worker #include "atomic_support.h" 26*c05d8e5dSAndroid Build Coastguard Worker 27*c05d8e5dSAndroid Build Coastguard Worker _LIBCPP_BEGIN_NAMESPACE_STD 28*c05d8e5dSAndroid Build Coastguard Worker 29*c05d8e5dSAndroid Build Coastguard Worker namespace __refstring_imp { namespace { 30*c05d8e5dSAndroid Build Coastguard Worker typedef int count_t; 31*c05d8e5dSAndroid Build Coastguard Worker 32*c05d8e5dSAndroid Build Coastguard Worker struct _Rep_base { 33*c05d8e5dSAndroid Build Coastguard Worker std::size_t len; 34*c05d8e5dSAndroid Build Coastguard Worker std::size_t cap; 35*c05d8e5dSAndroid Build Coastguard Worker count_t count; 36*c05d8e5dSAndroid Build Coastguard Worker }; 37*c05d8e5dSAndroid Build Coastguard Worker rep_from_data(const char * data_)38*c05d8e5dSAndroid Build Coastguard Workerinline _Rep_base* rep_from_data(const char *data_) noexcept { 39*c05d8e5dSAndroid Build Coastguard Worker char *data = const_cast<char *>(data_); 40*c05d8e5dSAndroid Build Coastguard Worker return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); 41*c05d8e5dSAndroid Build Coastguard Worker } 42*c05d8e5dSAndroid Build Coastguard Worker data_from_rep(_Rep_base * rep)43*c05d8e5dSAndroid Build Coastguard Workerinline char * data_from_rep(_Rep_base *rep) noexcept { 44*c05d8e5dSAndroid Build Coastguard Worker char *data = reinterpret_cast<char *>(rep); 45*c05d8e5dSAndroid Build Coastguard Worker return data + sizeof(*rep); 46*c05d8e5dSAndroid Build Coastguard Worker } 47*c05d8e5dSAndroid Build Coastguard Worker 48*c05d8e5dSAndroid Build Coastguard Worker #if defined(__APPLE__) 49*c05d8e5dSAndroid Build Coastguard Worker inline compute_gcc_empty_string_storage()50*c05d8e5dSAndroid Build Coastguard Workerconst char* compute_gcc_empty_string_storage() _NOEXCEPT 51*c05d8e5dSAndroid Build Coastguard Worker { 52*c05d8e5dSAndroid Build Coastguard Worker void* handle = dlopen("/usr/lib/libstdc++.6.dylib", RTLD_NOLOAD); 53*c05d8e5dSAndroid Build Coastguard Worker if (handle == nullptr) 54*c05d8e5dSAndroid Build Coastguard Worker return nullptr; 55*c05d8e5dSAndroid Build Coastguard Worker void* sym = dlsym(handle, "_ZNSs4_Rep20_S_empty_rep_storageE"); 56*c05d8e5dSAndroid Build Coastguard Worker if (sym == nullptr) 57*c05d8e5dSAndroid Build Coastguard Worker return nullptr; 58*c05d8e5dSAndroid Build Coastguard Worker return data_from_rep(reinterpret_cast<_Rep_base *>(sym)); 59*c05d8e5dSAndroid Build Coastguard Worker } 60*c05d8e5dSAndroid Build Coastguard Worker 61*c05d8e5dSAndroid Build Coastguard Worker inline 62*c05d8e5dSAndroid Build Coastguard Worker const char* get_gcc_empty_string_storage()63*c05d8e5dSAndroid Build Coastguard Workerget_gcc_empty_string_storage() _NOEXCEPT 64*c05d8e5dSAndroid Build Coastguard Worker { 65*c05d8e5dSAndroid Build Coastguard Worker static const char* p = compute_gcc_empty_string_storage(); 66*c05d8e5dSAndroid Build Coastguard Worker return p; 67*c05d8e5dSAndroid Build Coastguard Worker } 68*c05d8e5dSAndroid Build Coastguard Worker #endif 69*c05d8e5dSAndroid Build Coastguard Worker 70*c05d8e5dSAndroid Build Coastguard Worker }} // namespace __refstring_imp 71*c05d8e5dSAndroid Build Coastguard Worker 72*c05d8e5dSAndroid Build Coastguard Worker using namespace __refstring_imp; 73*c05d8e5dSAndroid Build Coastguard Worker 74*c05d8e5dSAndroid Build Coastguard Worker inline __libcpp_refstring(const char * msg)75*c05d8e5dSAndroid Build Coastguard Worker__libcpp_refstring::__libcpp_refstring(const char* msg) { 76*c05d8e5dSAndroid Build Coastguard Worker std::size_t len = strlen(msg); 77*c05d8e5dSAndroid Build Coastguard Worker _Rep_base* rep = static_cast<_Rep_base *>(::operator new(sizeof(*rep) + len + 1)); 78*c05d8e5dSAndroid Build Coastguard Worker rep->len = len; 79*c05d8e5dSAndroid Build Coastguard Worker rep->cap = len; 80*c05d8e5dSAndroid Build Coastguard Worker rep->count = 0; 81*c05d8e5dSAndroid Build Coastguard Worker char *data = data_from_rep(rep); 82*c05d8e5dSAndroid Build Coastguard Worker std::memcpy(data, msg, len + 1); 83*c05d8e5dSAndroid Build Coastguard Worker __imp_ = data; 84*c05d8e5dSAndroid Build Coastguard Worker } 85*c05d8e5dSAndroid Build Coastguard Worker 86*c05d8e5dSAndroid Build Coastguard Worker inline __libcpp_refstring(const __libcpp_refstring & s)87*c05d8e5dSAndroid Build Coastguard Worker__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT 88*c05d8e5dSAndroid Build Coastguard Worker : __imp_(s.__imp_) 89*c05d8e5dSAndroid Build Coastguard Worker { 90*c05d8e5dSAndroid Build Coastguard Worker if (__uses_refcount()) 91*c05d8e5dSAndroid Build Coastguard Worker __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); 92*c05d8e5dSAndroid Build Coastguard Worker } 93*c05d8e5dSAndroid Build Coastguard Worker 94*c05d8e5dSAndroid Build Coastguard Worker inline 95*c05d8e5dSAndroid Build Coastguard Worker __libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { 96*c05d8e5dSAndroid Build Coastguard Worker bool adjust_old_count = __uses_refcount(); 97*c05d8e5dSAndroid Build Coastguard Worker struct _Rep_base *old_rep = rep_from_data(__imp_); 98*c05d8e5dSAndroid Build Coastguard Worker __imp_ = s.__imp_; 99*c05d8e5dSAndroid Build Coastguard Worker if (__uses_refcount()) 100*c05d8e5dSAndroid Build Coastguard Worker __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); 101*c05d8e5dSAndroid Build Coastguard Worker if (adjust_old_count) 102*c05d8e5dSAndroid Build Coastguard Worker { 103*c05d8e5dSAndroid Build Coastguard Worker if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0) 104*c05d8e5dSAndroid Build Coastguard Worker { 105*c05d8e5dSAndroid Build Coastguard Worker ::operator delete(old_rep); 106*c05d8e5dSAndroid Build Coastguard Worker } 107*c05d8e5dSAndroid Build Coastguard Worker } 108*c05d8e5dSAndroid Build Coastguard Worker return *this; 109*c05d8e5dSAndroid Build Coastguard Worker } 110*c05d8e5dSAndroid Build Coastguard Worker 111*c05d8e5dSAndroid Build Coastguard Worker inline ~__libcpp_refstring()112*c05d8e5dSAndroid Build Coastguard Worker__libcpp_refstring::~__libcpp_refstring() { 113*c05d8e5dSAndroid Build Coastguard Worker if (__uses_refcount()) { 114*c05d8e5dSAndroid Build Coastguard Worker _Rep_base* rep = rep_from_data(__imp_); 115*c05d8e5dSAndroid Build Coastguard Worker if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) { 116*c05d8e5dSAndroid Build Coastguard Worker ::operator delete(rep); 117*c05d8e5dSAndroid Build Coastguard Worker } 118*c05d8e5dSAndroid Build Coastguard Worker } 119*c05d8e5dSAndroid Build Coastguard Worker } 120*c05d8e5dSAndroid Build Coastguard Worker 121*c05d8e5dSAndroid Build Coastguard Worker inline __uses_refcount()122*c05d8e5dSAndroid Build Coastguard Workerbool __libcpp_refstring::__uses_refcount() const { 123*c05d8e5dSAndroid Build Coastguard Worker #ifdef __APPLE__ 124*c05d8e5dSAndroid Build Coastguard Worker return __imp_ != get_gcc_empty_string_storage(); 125*c05d8e5dSAndroid Build Coastguard Worker #else 126*c05d8e5dSAndroid Build Coastguard Worker return true; 127*c05d8e5dSAndroid Build Coastguard Worker #endif 128*c05d8e5dSAndroid Build Coastguard Worker } 129*c05d8e5dSAndroid Build Coastguard Worker 130*c05d8e5dSAndroid Build Coastguard Worker _LIBCPP_END_NAMESPACE_STD 131*c05d8e5dSAndroid Build Coastguard Worker 132*c05d8e5dSAndroid Build Coastguard Worker #endif //_LIBCPPABI_REFSTRING_H 133