[libcxx] r207695 - Exceptions store the message as reference counted string for
Joerg Sonnenberger
joerg at bec.de
Wed Apr 30 12:54:12 PDT 2014
Author: joerg
Date: Wed Apr 30 14:54:11 2014
New Revision: 207695
URL: http://llvm.org/viewvc/llvm-project?rev=207695&view=rev
Log:
Exceptions store the message as reference counted string for
compatibility to libstdc++. Move the implementation into a header for
easier sharing with libc++abi. Merge a number of improvements from that
version. Provide a POD definition for <stdexcept>'s public use to avoid
cast dances. Discussed with Marshall Clow.
Added:
libcxx/trunk/include/__refstring
Modified:
libcxx/trunk/include/stdexcept
libcxx/trunk/src/stdexcept.cpp
Added: libcxx/trunk/include/__refstring
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/__refstring?rev=207695&view=auto
==============================================================================
--- libcxx/trunk/include/__refstring (added)
+++ libcxx/trunk/include/__refstring Wed Apr 30 14:54:11 2014
@@ -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 <cstddef>
+#include <cstring>
+#if __APPLE__
+#include <dlfcn.h>
+#include <mach-o/dyld.h>
+#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<char *>(data_);
+ return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base));
+ }
+ static
+ char *
+ data_from_rep(_Rep_base *rep) _NOEXCEPT
+ {
+ char *data = reinterpret_cast<char *>(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
Modified: libcxx/trunk/include/stdexcept
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/include/stdexcept?rev=207695&r1=207694&r2=207695&view=diff
==============================================================================
--- libcxx/trunk/include/stdexcept (original)
+++ libcxx/trunk/include/stdexcept Wed Apr 30 14:54:11 2014
@@ -50,6 +50,14 @@ public:
#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 @@ class _LIBCPP_EXCEPTION_ABI logic_error
: public exception
{
private:
- void* __imp_;
+ _VSTD::__libcpp_refstring __imp_;
public:
explicit logic_error(const string&);
explicit logic_error(const char*);
@@ -74,7 +82,7 @@ class _LIBCPP_EXCEPTION_ABI runtime_erro
: public exception
{
private:
- void* __imp_;
+ _VSTD::__libcpp_refstring __imp_;
public:
explicit runtime_error(const string&);
explicit runtime_error(const char*);
Modified: libcxx/trunk/src/stdexcept.cpp
URL: http://llvm.org/viewvc/llvm-project/libcxx/trunk/src/stdexcept.cpp?rev=207695&r1=207694&r2=207695&view=diff
==============================================================================
--- libcxx/trunk/src/stdexcept.cpp (original)
+++ libcxx/trunk/src/stdexcept.cpp Wed Apr 30 14:54:11 2014
@@ -7,124 +7,42 @@
//
//===----------------------------------------------------------------------===//
+#include "__refstring"
#include "stdexcept"
#include "new"
#include "string"
-#include <cstdlib>
-#include <cstring>
-#include <cstdint>
-#include <cstddef>
#include "system_error"
#ifndef __has_include
#define __has_include(inc) 0
#endif
-#ifdef __APPLE__
+/* For _LIBCPPABI_VERSION */
+#if __has_include(<cxxabi.h>) || defined(__APPLE_) || defined(LIBCXXRT)
#include <cxxabi.h>
-#elif defined(LIBCXXRT) || __has_include(<cxxabi.h>)
-#include <cxxabi.h>
-#endif
-
-// Note: optimize for size
-
-#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<std::ptrdiff_t>(2*sizeof(unused_t) +
- sizeof(count_t));
-
- count_t& count() const _NOEXCEPT {return *const_cast<count_t *>(reinterpret_cast<const count_t *>(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<unused_t*>(const_cast<char *>(str_));
- c[0] = c[1] = len;
- str_ += offset;
- count() = 0;
- std::memcpy(const_cast<char*>(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<count_t*>(const_cast<char*>(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
+static_assert(sizeof(std::__libcpp_refstring) == sizeof(const char *), "");
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<const __libcpp_nmstr *>(&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<const __libcpp_nmstr *>(&le.__imp_);
- *s1 = *s2;
+ __imp_ = le.__imp_;
return *this;
}
@@ -132,44 +50,33 @@ logic_error::operator=(const logic_error
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<const __libcpp_nmstr *>(&__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<const __libcpp_nmstr *>(&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<const __libcpp_nmstr *>(&le.__imp_);
- *s1 = *s2;
+ __imp_ = le.__imp_;
return *this;
}
@@ -177,15 +84,12 @@ runtime_error::operator=(const runtime_e
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<const __libcpp_nmstr *>(&__imp_);
- return s->c_str();
+ return __imp_.c_str();
}
domain_error::~domain_error() _NOEXCEPT {}
More information about the cfe-commits
mailing list