From 38bf94280bb9735a005673d3eae132f75795b854 Mon Sep 17 00:00:00 2001 From: Jakub Konka Date: Wed, 16 Dec 2020 11:55:25 +0100 Subject: [PATCH] Update libcxxabi llvm commit b2851aea80e5a8f0cfd6c3c5a56a6b00fb28c6b6 --- lib/libcxxabi/include/__cxxabi_config.h | 17 ++- lib/libcxxabi/include/cxxabi.h | 19 +-- lib/libcxxabi/src/cxa_guard_impl.h | 48 +++---- lib/libcxxabi/src/demangle/ItaniumDemangle.h | 135 ++++++++++++++++++- lib/libcxxabi/src/demangle/Utility.h | 2 +- lib/libcxxabi/src/fallback_malloc.cpp | 39 +++--- lib/libcxxabi/src/include/refstring.h | 131 ------------------ lib/libcxxabi/src/private_typeinfo.cpp | 34 ++++- lib/libcxxabi/src/stdlib_exception.cpp | 1 - lib/libcxxabi/src/stdlib_new_delete.cpp | 36 +++-- lib/libcxxabi/src/stdlib_stdexcept.cpp | 2 +- 11 files changed, 244 insertions(+), 220 deletions(-) delete mode 100644 lib/libcxxabi/src/include/refstring.h diff --git a/lib/libcxxabi/include/__cxxabi_config.h b/lib/libcxxabi/include/__cxxabi_config.h index b5444d67ee..cffedb88df 100644 --- a/lib/libcxxabi/include/__cxxabi_config.h +++ b/lib/libcxxabi/include/__cxxabi_config.h @@ -18,6 +18,19 @@ #define __has_attribute(_attribute_) 0 #endif +#if defined(__clang__) +# define _LIBCXXABI_COMPILER_CLANG +# ifndef __apple_build_version__ +# define _LIBCXXABI_CLANG_VER (__clang_major__ * 100 + __clang_minor__) +# endif +#elif defined(__GNUC__) +# define _LIBCXXABI_COMPILER_GCC +#elif defined(_MSC_VER) +# define _LIBCXXABI_COMPILER_MSVC +#elif defined(__IBMCPP__) +# define _LIBCXXABI_COMPILER_IBM +#endif + #if defined(_WIN32) #if defined(_LIBCXXABI_DISABLE_VISIBILITY_ANNOTATIONS) #define _LIBCXXABI_HIDDEN @@ -53,7 +66,7 @@ #endif #endif -#if defined(_WIN32) +#if defined(_LIBCXXABI_COMPILER_MSVC) #define _LIBCXXABI_WEAK #else #define _LIBCXXABI_WEAK __attribute__((__weak__)) @@ -72,7 +85,7 @@ #endif // wasm32 follows the arm32 ABI convention of using 32-bit guard. -#if defined(__arm__) || defined(__wasm32__) +#if defined(__arm__) || defined(__wasm32__) || defined(__ARM64_ARCH_8_32__) # define _LIBCXXABI_GUARD_ABI_ARM #endif diff --git a/lib/libcxxabi/include/cxxabi.h b/lib/libcxxabi/include/cxxabi.h index d21d3e1e23..43ce6f5f74 100644 --- a/lib/libcxxabi/include/cxxabi.h +++ b/lib/libcxxabi/include/cxxabi.h @@ -21,6 +21,7 @@ #define _LIBCPPABI_VERSION 1002 #define _LIBCXXABI_NORETURN __attribute__((noreturn)) +#define _LIBCXXABI_ALWAYS_COLD __attribute__((cold)) #ifdef __cplusplus @@ -78,13 +79,13 @@ extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_NORETURN void __cxa_deleted_virtual(void); // 3.3.2 One-time Construction API #if defined(_LIBCXXABI_GUARD_ABI_ARM) -extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint32_t *); -extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint32_t *); -extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint32_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint32_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint32_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint32_t *); #else -extern _LIBCXXABI_FUNC_VIS int __cxa_guard_acquire(uint64_t *); -extern _LIBCXXABI_FUNC_VIS void __cxa_guard_release(uint64_t *); -extern _LIBCXXABI_FUNC_VIS void __cxa_guard_abort(uint64_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD int __cxa_guard_acquire(uint64_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_release(uint64_t *); +extern _LIBCXXABI_FUNC_VIS _LIBCXXABI_ALWAYS_COLD void __cxa_guard_abort(uint64_t *); #endif // 3.3.3 Array Construction and Destruction API @@ -136,9 +137,9 @@ __cxa_vec_cctor(void *dest_array, void *src_array, size_t element_count, void (*destructor)(void *)); // 3.3.5.3 Runtime API -extern _LIBCXXABI_FUNC_VIS int __cxa_atexit(void (*f)(void *), void *p, - void *d); -extern _LIBCXXABI_FUNC_VIS int __cxa_finalize(void *); +// These functions are part of the C++ ABI, but they are not defined in libc++abi: +// int __cxa_atexit(void (*)(void *), void *, void *); +// void __cxa_finalize(void *); // 3.4 Demangler API extern _LIBCXXABI_FUNC_VIS char *__cxa_demangle(const char *mangled_name, diff --git a/lib/libcxxabi/src/cxa_guard_impl.h b/lib/libcxxabi/src/cxa_guard_impl.h index f6a698e23a..6f873f241f 100644 --- a/lib/libcxxabi/src/cxa_guard_impl.h +++ b/lib/libcxxabi/src/cxa_guard_impl.h @@ -54,6 +54,14 @@ #endif #endif +#if defined(__clang__) +# pragma clang diagnostic push +# pragma clang diagnostic ignored "-Wtautological-pointer-compare" +#elif defined(__GNUC__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Waddress" +#endif + // To make testing possible, this header is included from both cxa_guard.cpp // and a number of tests. // @@ -112,25 +120,25 @@ class AtomicInt { public: using MemoryOrder = std::__libcpp_atomic_order; - explicit AtomicInt(IntType *b) : b(b) {} + explicit AtomicInt(IntType *b) : b_(b) {} AtomicInt(AtomicInt const&) = delete; AtomicInt& operator=(AtomicInt const&) = delete; IntType load(MemoryOrder ord) { - return std::__libcpp_atomic_load(b, ord); + return std::__libcpp_atomic_load(b_, ord); } void store(IntType val, MemoryOrder ord) { - std::__libcpp_atomic_store(b, val, ord); + std::__libcpp_atomic_store(b_, val, ord); } IntType exchange(IntType new_val, MemoryOrder ord) { - return std::__libcpp_atomic_exchange(b, new_val, ord); + return std::__libcpp_atomic_exchange(b_, new_val, ord); } bool compare_exchange(IntType *expected, IntType desired, MemoryOrder ord_success, MemoryOrder ord_failure) { - return std::__libcpp_atomic_compare_exchange(b, expected, desired, ord_success, ord_failure); + return std::__libcpp_atomic_compare_exchange(b_, expected, desired, ord_success, ord_failure); } private: - IntType *b; + IntType *b_; }; //===----------------------------------------------------------------------===// @@ -154,14 +162,7 @@ constexpr uint32_t (*PlatformThreadID)() = nullptr; constexpr bool PlatformSupportsThreadID() { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#endif return +PlatformThreadID != nullptr; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif } //===----------------------------------------------------------------------===// @@ -375,18 +376,18 @@ private: LockGuard& operator=(LockGuard const&) = delete; explicit LockGuard(const char* calling_func) - : calling_func(calling_func) { + : calling_func_(calling_func) { if (global_mutex.lock()) - ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func); + ABORT_WITH_MESSAGE("%s failed to acquire mutex", calling_func_); } ~LockGuard() { if (global_mutex.unlock()) - ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func); + ABORT_WITH_MESSAGE("%s failed to release mutex", calling_func_); } private: - const char* const calling_func; + const char* const calling_func_; }; }; @@ -411,14 +412,7 @@ constexpr void (*PlatformFutexWake)(int*) = nullptr; #endif constexpr bool PlatformSupportsFutex() { -#ifdef __clang__ -#pragma clang diagnostic push -#pragma clang diagnostic ignored "-Wtautological-pointer-compare" -#endif return +PlatformFutexWait != nullptr; -#ifdef __clang__ -#pragma clang diagnostic pop -#endif } /// InitByteFutex - Manages initialization using atomics and the futex syscall @@ -589,4 +583,10 @@ using SelectedImplementation = } // end namespace } // end namespace __cxxabiv1 +#if defined(__clang__) +# pragma clang diagnostic pop +#elif defined(__GNUC__) +# pragma GCC diagnostic pop +#endif + #endif // LIBCXXABI_SRC_INCLUDE_CXA_GUARD_IMPL_H diff --git a/lib/libcxxabi/src/demangle/ItaniumDemangle.h b/lib/libcxxabi/src/demangle/ItaniumDemangle.h index 6ab8732183..6bfc02d153 100644 --- a/lib/libcxxabi/src/demangle/ItaniumDemangle.h +++ b/lib/libcxxabi/src/demangle/ItaniumDemangle.h @@ -82,6 +82,7 @@ X(PostfixExpr) \ X(ConditionalExpr) \ X(MemberExpr) \ + X(SubobjectExpr) \ X(EnclosingExpr) \ X(CastExpr) \ X(SizeofParamPackExpr) \ @@ -91,6 +92,7 @@ X(PrefixExpr) \ X(FunctionParam) \ X(ConversionExpr) \ + X(PointerToMemberConversionExpr) \ X(InitListExpr) \ X(FoldExpr) \ X(ThrowExpr) \ @@ -1656,6 +1658,40 @@ public: } }; +class SubobjectExpr : public Node { + const Node *Type; + const Node *SubExpr; + StringView Offset; + NodeArray UnionSelectors; + bool OnePastTheEnd; + +public: + SubobjectExpr(const Node *Type_, const Node *SubExpr_, StringView Offset_, + NodeArray UnionSelectors_, bool OnePastTheEnd_) + : Node(KSubobjectExpr), Type(Type_), SubExpr(SubExpr_), Offset(Offset_), + UnionSelectors(UnionSelectors_), OnePastTheEnd(OnePastTheEnd_) {} + + template void match(Fn F) const { + F(Type, SubExpr, Offset, UnionSelectors, OnePastTheEnd); + } + + void printLeft(OutputStream &S) const override { + SubExpr->print(S); + S += ".<"; + Type->print(S); + S += " at offset "; + if (Offset.empty()) { + S += "0"; + } else if (Offset[0] == 'n') { + S += "-"; + S += Offset.dropFront(); + } else { + S += Offset; + } + S += ">"; + } +}; + class EnclosingExpr : public Node { const StringView Prefix; const Node *Infix; @@ -1843,6 +1879,28 @@ public: } }; +class PointerToMemberConversionExpr : public Node { + const Node *Type; + const Node *SubExpr; + StringView Offset; + +public: + PointerToMemberConversionExpr(const Node *Type_, const Node *SubExpr_, + StringView Offset_) + : Node(KPointerToMemberConversionExpr), Type(Type_), SubExpr(SubExpr_), + Offset(Offset_) {} + + template void match(Fn F) const { F(Type, SubExpr, Offset); } + + void printLeft(OutputStream &S) const override { + S += "("; + Type->print(S); + S += ")("; + SubExpr->print(S); + S += ")"; + } +}; + class InitListExpr : public Node { const Node *Ty; NodeArray Inits; @@ -2313,9 +2371,9 @@ template struct AbstractManglingParser { TemplateParamList Params; public: - ScopedTemplateParamList(AbstractManglingParser *Parser) - : Parser(Parser), - OldNumTemplateParamLists(Parser->TemplateParams.size()) { + ScopedTemplateParamList(AbstractManglingParser *TheParser) + : Parser(TheParser), + OldNumTemplateParamLists(TheParser->TemplateParams.size()) { Parser->TemplateParams.push_back(&Params); } ~ScopedTemplateParamList() { @@ -2437,6 +2495,8 @@ template struct AbstractManglingParser { Node *parseConversionExpr(); Node *parseBracedExpr(); Node *parseFoldExpr(); + Node *parsePointerToMemberConversionExpr(); + Node *parseSubobjectExpr(); /// Parse the production. Node *parseType(); @@ -4404,6 +4464,50 @@ Node *AbstractManglingParser::parseFoldExpr() { return make(IsLeftFold, OperatorName, Pack, Init); } +// ::= mc [] E +// +// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47 +template +Node *AbstractManglingParser::parsePointerToMemberConversionExpr() { + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + Node *Expr = getDerived().parseExpr(); + if (!Expr) + return nullptr; + StringView Offset = getDerived().parseNumber(true); + if (!consumeIf('E')) + return nullptr; + return make(Ty, Expr, Offset); +} + +// ::= so [] * [p] E +// ::= _ [] +// +// Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/47 +template +Node *AbstractManglingParser::parseSubobjectExpr() { + Node *Ty = getDerived().parseType(); + if (!Ty) + return nullptr; + Node *Expr = getDerived().parseExpr(); + if (!Expr) + return nullptr; + StringView Offset = getDerived().parseNumber(true); + size_t SelectorsBegin = Names.size(); + while (consumeIf('_')) { + Node *Selector = make(parseNumber()); + if (!Selector) + return nullptr; + Names.push_back(Selector); + } + bool OnePastTheEnd = consumeIf('p'); + if (!consumeIf('E')) + return nullptr; + return make( + Ty, Expr, Offset, popTrailingNodeArray(SelectorsBegin), OnePastTheEnd); +} + // ::= // ::= // ::= @@ -4661,6 +4765,9 @@ Node *AbstractManglingParser::parseExpr() { return nullptr; case 'm': switch (First[1]) { + case 'c': + First += 2; + return parsePointerToMemberConversionExpr(); case 'i': First += 2; return getDerived().parseBinaryExpr("-"); @@ -4808,6 +4915,9 @@ Node *AbstractManglingParser::parseExpr() { return Ex; return make("static_cast", T, Ex); } + case 'o': + First += 2; + return parseSubobjectExpr(); case 'p': { First += 2; Node *Child = getDerived().parseExpr(); @@ -4975,6 +5085,16 @@ Node *AbstractManglingParser::parseSpecialName() { switch (look()) { case 'T': switch (look(1)) { + // TA # template parameter object + // + // Not yet in the spec: https://github.com/itanium-cxx-abi/cxx-abi/issues/63 + case 'A': { + First += 2; + Node *Arg = getDerived().parseTemplateArg(); + if (Arg == nullptr) + return nullptr; + return make("template parameter object for ", Arg); + } // TV # virtual table case 'V': { First += 2; @@ -5103,7 +5223,7 @@ Node *AbstractManglingParser::parseEncoding() { decltype(TemplateParams) OldParams; public: - SaveTemplateParams(AbstractManglingParser *Parser) : Parser(Parser) { + SaveTemplateParams(AbstractManglingParser *TheParser) : Parser(TheParser) { OldParams = std::move(Parser->TemplateParams); Parser->TemplateParams.clear(); } @@ -5203,7 +5323,12 @@ struct FloatData #else static const size_t mangled_size = 20; // May need to be adjusted to 16 or 24 on other platforms #endif - static const size_t max_demangled_size = 40; + // `-0x1.ffffffffffffffffffffffffffffp+16383` + 'L' + '\0' == 42 bytes. + // 28 'f's * 4 bits == 112 bits, which is the number of mantissa bits. + // Negatives are one character longer than positives. + // `0x1.` and `p` are constant, and exponents `+16383` and `-16382` are the + // same length. 1 sign bit, 112 mantissa bits, and 15 exponent bits == 128. + static const size_t max_demangled_size = 42; static constexpr const char *spec = "%LaL"; }; diff --git a/lib/libcxxabi/src/demangle/Utility.h b/lib/libcxxabi/src/demangle/Utility.h index 04e1936ebb..846a5f0818 100644 --- a/lib/libcxxabi/src/demangle/Utility.h +++ b/lib/libcxxabi/src/demangle/Utility.h @@ -52,7 +52,7 @@ class OutputStream { char *TempPtr = std::end(Temp); while (N) { - *--TempPtr = '0' + char(N % 10); + *--TempPtr = char('0' + N % 10); N /= 10; } diff --git a/lib/libcxxabi/src/fallback_malloc.cpp b/lib/libcxxabi/src/fallback_malloc.cpp index fdae40764a..f3d7937793 100644 --- a/lib/libcxxabi/src/fallback_malloc.cpp +++ b/lib/libcxxabi/src/fallback_malloc.cpp @@ -6,9 +6,6 @@ // //===----------------------------------------------------------------------===// -// Define _LIBCPP_BUILDING_LIBRARY to ensure _LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION -// is only defined when libc aligned allocation is not available. -#define _LIBCPP_BUILDING_LIBRARY #include "fallback_malloc.h" #include <__threading_support> @@ -20,6 +17,7 @@ #include // for malloc, calloc, free #include // for memset +#include // for std::__libcpp_aligned_{alloc,free} // A small, simple heap manager based (loosely) on // the startup heap manager from FreeBSD, optimized for space. @@ -144,29 +142,26 @@ void fallback_free(void* ptr) { mutexor mtx(&heap_mutex); #ifdef DEBUG_FALLBACK_MALLOC - std::cout << "Freeing item at " << offset_from_node(cp) << " of size " - << cp->len << std::endl; + std::printf("Freeing item at %d of size %d\n", offset_from_node(cp), cp->len); #endif for (p = freelist, prev = 0; p && p != list_end; prev = p, p = node_from_offset(p->next_node)) { #ifdef DEBUG_FALLBACK_MALLOC - std::cout << " p, cp, after (p), after(cp) " << offset_from_node(p) << ' ' - << offset_from_node(cp) << ' ' << offset_from_node(after(p)) - << ' ' << offset_from_node(after(cp)) << std::endl; + std::printf(" p=%d, cp=%d, after(p)=%d, after(cp)=%d\n", + offset_from_node(p), offset_from_node(cp), + offset_from_node(after(p)), offset_from_node(after(cp))); #endif if (after(p) == cp) { #ifdef DEBUG_FALLBACK_MALLOC - std::cout << " Appending onto chunk at " << offset_from_node(p) - << std::endl; + std::printf(" Appending onto chunk at %d\n", offset_from_node(p)); #endif p->len = static_cast( p->len + cp->len); // make the free heap_node larger return; } else if (after(cp) == p) { // there's a free heap_node right after #ifdef DEBUG_FALLBACK_MALLOC - std::cout << " Appending free chunk at " << offset_from_node(p) - << std::endl; + std::printf(" Appending free chunk at %d\n", offset_from_node(p)); #endif cp->len = static_cast(cp->len + p->len); if (prev == 0) { @@ -179,8 +174,7 @@ void fallback_free(void* ptr) { } // Nothing to merge with, add it to the start of the free list #ifdef DEBUG_FALLBACK_MALLOC - std::cout << " Making new free list entry " << offset_from_node(cp) - << std::endl; + std::printf(" Making new free list entry %d\n", offset_from_node(cp)); #endif cp->next_node = offset_from_node(freelist); freelist = cp; @@ -195,11 +189,11 @@ size_t print_free_list() { for (p = freelist, prev = 0; p && p != list_end; prev = p, p = node_from_offset(p->next_node)) { - std::cout << (prev == 0 ? "" : " ") << "Offset: " << offset_from_node(p) - << "\tsize: " << p->len << " Next: " << p->next_node << std::endl; + std::printf("%sOffset: %d\tsize: %d Next: %d\n", + (prev == 0 ? "" : " "), offset_from_node(p), p->len, p->next_node); total_free += p->len; } - std::cout << "Total Free space: " << total_free << std::endl; + std::printf("Total Free space: %d\n", total_free); return total_free; } #endif @@ -211,7 +205,7 @@ struct __attribute__((aligned)) __aligned_type {}; void* __aligned_malloc_with_fallback(size_t size) { #if defined(_WIN32) - if (void* dest = _aligned_malloc(size, alignof(__aligned_type))) + if (void* dest = std::__libcpp_aligned_alloc(alignof(__aligned_type), size)) return dest; #elif defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) if (void* dest = ::malloc(size)) @@ -219,8 +213,7 @@ void* __aligned_malloc_with_fallback(size_t size) { #else if (size == 0) size = 1; - void* dest; - if (::posix_memalign(&dest, __alignof(__aligned_type), size) == 0) + if (void* dest = std::__libcpp_aligned_alloc(__alignof(__aligned_type), size)) return dest; #endif return fallback_malloc(size); @@ -241,10 +234,10 @@ void __aligned_free_with_fallback(void* ptr) { if (is_fallback_ptr(ptr)) fallback_free(ptr); else { -#if defined(_WIN32) - ::_aligned_free(ptr); -#else +#if defined(_LIBCPP_HAS_NO_LIBRARY_ALIGNED_ALLOCATION) ::free(ptr); +#else + std::__libcpp_aligned_free(ptr); #endif } } diff --git a/lib/libcxxabi/src/include/refstring.h b/lib/libcxxabi/src/include/refstring.h deleted file mode 100644 index 5905b5c932..0000000000 --- a/lib/libcxxabi/src/include/refstring.h +++ /dev/null @@ -1,131 +0,0 @@ -//===------------------------ __refstring ---------------------------------===// -// -// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions. -// See https://llvm.org/LICENSE.txt for license information. -// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception -// -//===----------------------------------------------------------------------===// - -// FIXME: This file is copied from libcxx/src/include/refstring.h. Instead of -// duplicating the file in libc++abi we should require that the libc++ sources -// are available when building libc++abi. - -#ifndef _LIBCPPABI_REFSTRING_H -#define _LIBCPPABI_REFSTRING_H - -#include <__config> -#include -#include -#include -#ifdef __APPLE__ -#include -#include -#endif -#include "atomic_support.h" - -_LIBCPP_BEGIN_NAMESPACE_STD - -namespace __refstring_imp { namespace { -typedef int count_t; - -struct _Rep_base { - std::size_t len; - std::size_t cap; - count_t count; -}; - -inline _Rep_base* rep_from_data(const char *data_) noexcept { - char *data = const_cast(data_); - return reinterpret_cast<_Rep_base *>(data - sizeof(_Rep_base)); -} - -inline char * data_from_rep(_Rep_base *rep) noexcept { - char *data = reinterpret_cast(rep); - return data + sizeof(*rep); -} - -#if defined(__APPLE__) -inline -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)); -} - -inline -const char* -get_gcc_empty_string_storage() _NOEXCEPT -{ - static const char* p = compute_gcc_empty_string_storage(); - return p; -} -#endif - -}} // namespace __refstring_imp - -using namespace __refstring_imp; - -inline -__libcpp_refstring::__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); - __imp_ = data; -} - -inline -__libcpp_refstring::__libcpp_refstring(const __libcpp_refstring &s) _NOEXCEPT - : __imp_(s.__imp_) -{ - if (__uses_refcount()) - __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); -} - -inline -__libcpp_refstring& __libcpp_refstring::operator=(__libcpp_refstring const& s) _NOEXCEPT { - bool adjust_old_count = __uses_refcount(); - struct _Rep_base *old_rep = rep_from_data(__imp_); - __imp_ = s.__imp_; - if (__uses_refcount()) - __libcpp_atomic_add(&rep_from_data(__imp_)->count, 1); - if (adjust_old_count) - { - if (__libcpp_atomic_add(&old_rep->count, count_t(-1)) < 0) - { - ::operator delete(old_rep); - } - } - return *this; -} - -inline -__libcpp_refstring::~__libcpp_refstring() { - if (__uses_refcount()) { - _Rep_base* rep = rep_from_data(__imp_); - if (__libcpp_atomic_add(&rep->count, count_t(-1)) < 0) { - ::operator delete(rep); - } - } -} - -inline -bool __libcpp_refstring::__uses_refcount() const { -#ifdef __APPLE__ - return __imp_ != get_gcc_empty_string_storage(); -#else - return true; -#endif -} - -_LIBCPP_END_NAMESPACE_STD - -#endif //_LIBCPPABI_REFSTRING_H diff --git a/lib/libcxxabi/src/private_typeinfo.cpp b/lib/libcxxabi/src/private_typeinfo.cpp index 55a90b3ae1..c77ad669c4 100644 --- a/lib/libcxxabi/src/private_typeinfo.cpp +++ b/lib/libcxxabi/src/private_typeinfo.cpp @@ -61,6 +61,16 @@ is_equal(const std::type_info* x, const std::type_info* y, bool use_strcmp) return x == y || strcmp(x->name(), y->name()) == 0; } +static inline ptrdiff_t update_offset_to_base(const char* vtable, + ptrdiff_t offset_to_base) { +#if __has_feature(cxx_abi_relative_vtable) + // VTable components are 32 bits in the relative vtables ABI. + return *reinterpret_cast(vtable + offset_to_base); +#else + return *reinterpret_cast(vtable + offset_to_base); +#endif +} + namespace __cxxabiv1 { @@ -297,7 +307,7 @@ __base_class_type_info::has_unambiguous_public_base(__dynamic_cast_info* info, if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(adjustedPtr); - offset_to_base = *reinterpret_cast(vtable + offset_to_base); + offset_to_base = update_offset_to_base(vtable, offset_to_base); } } __base_type->has_unambiguous_public_base( @@ -615,10 +625,26 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, // Possible future optimization: Take advantage of src2dst_offset // Get (dynamic_ptr, dynamic_type) from static_ptr +#if __has_feature(cxx_abi_relative_vtable) + // The vtable address will point to the first virtual function, which is 8 + // bytes after the start of the vtable (4 for the offset from top + 4 for the typeinfo component). + const int32_t* vtable = + *reinterpret_cast(static_ptr); + int32_t offset_to_derived = vtable[-2]; + const void* dynamic_ptr = static_cast(static_ptr) + offset_to_derived; + + // The typeinfo component is now a relative offset to a proxy. + int32_t offset_to_ti_proxy = vtable[-1]; + const uint8_t* ptr_to_ti_proxy = + reinterpret_cast(vtable) + offset_to_ti_proxy; + const __class_type_info* dynamic_type = + *(reinterpret_cast(ptr_to_ti_proxy)); +#else void **vtable = *static_cast(static_ptr); ptrdiff_t offset_to_derived = reinterpret_cast(vtable[-2]); const void* dynamic_ptr = static_cast(static_ptr) + offset_to_derived; const __class_type_info* dynamic_type = static_cast(vtable[-1]); +#endif // Initialize answer to nullptr. This will be changed from the search // results if a non-null answer is found. Regardless, this is what will @@ -641,6 +667,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, { // We get here only if there is some kind of visibility problem // in client code. + static_assert(std::atomic::is_always_lock_free, ""); static std::atomic error_count(0); size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); if ((error_count_snapshot & (error_count_snapshot-1)) == 0) @@ -667,6 +694,7 @@ __dynamic_cast(const void *static_ptr, const __class_type_info *static_type, if (info.path_dst_ptr_to_static_ptr == unknown && info.path_dynamic_ptr_to_static_ptr == unknown) { + static_assert(std::atomic::is_always_lock_free, ""); static std::atomic error_count(0); size_t error_count_snapshot = error_count.fetch_add(1, std::memory_order_relaxed); if ((error_count_snapshot & (error_count_snapshot-1)) == 0) @@ -1265,7 +1293,7 @@ __base_class_type_info::search_above_dst(__dynamic_cast_info* info, if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(current_ptr); - offset_to_base = *reinterpret_cast(vtable + offset_to_base); + offset_to_base = update_offset_to_base(vtable, offset_to_base); } __base_type->search_above_dst(info, dst_ptr, static_cast(current_ptr) + offset_to_base, @@ -1285,7 +1313,7 @@ __base_class_type_info::search_below_dst(__dynamic_cast_info* info, if (__offset_flags & __virtual_mask) { const char* vtable = *static_cast(current_ptr); - offset_to_base = *reinterpret_cast(vtable + offset_to_base); + offset_to_base = update_offset_to_base(vtable, offset_to_base); } __base_type->search_below_dst(info, static_cast(current_ptr) + offset_to_base, diff --git a/lib/libcxxabi/src/stdlib_exception.cpp b/lib/libcxxabi/src/stdlib_exception.cpp index 88d911d96c..b0cc431f24 100644 --- a/lib/libcxxabi/src/stdlib_exception.cpp +++ b/lib/libcxxabi/src/stdlib_exception.cpp @@ -6,7 +6,6 @@ // //===----------------------------------------------------------------------===// -#define _LIBCPP_BUILDING_LIBRARY #include #include diff --git a/lib/libcxxabi/src/stdlib_new_delete.cpp b/lib/libcxxabi/src/stdlib_new_delete.cpp index 698c5f7c29..9df84548ea 100644 --- a/lib/libcxxabi/src/stdlib_new_delete.cpp +++ b/lib/libcxxabi/src/stdlib_new_delete.cpp @@ -8,7 +8,6 @@ // This file implements the new and delete operators. //===----------------------------------------------------------------------===// -#define _LIBCPP_BUILDING_LIBRARY #include "__cxxabi_config.h" #include #include @@ -28,7 +27,7 @@ operator new(std::size_t size) _THROW_BAD_ALLOC if (size == 0) size = 1; void* p; - while ((p = ::malloc(size)) == 0) + while ((p = ::malloc(size)) == nullptr) { // If malloc fails and there is a new_handler, // call it to try free up memory. @@ -49,7 +48,7 @@ _LIBCXXABI_WEAK void* operator new(size_t size, const std::nothrow_t&) _NOEXCEPT { - void* p = 0; + void* p = nullptr; #ifndef _LIBCXXABI_NO_EXCEPTIONS try { @@ -75,7 +74,7 @@ _LIBCXXABI_WEAK void* operator new[](size_t size, const std::nothrow_t&) _NOEXCEPT { - void* p = 0; + void* p = nullptr; #ifndef _LIBCXXABI_NO_EXCEPTIONS try { @@ -143,15 +142,16 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC size = 1; if (static_cast(alignment) < sizeof(void*)) alignment = std::align_val_t(sizeof(void*)); + + // Try allocating memory. If allocation fails and there is a new_handler, + // call it to try free up memory, and try again until it succeeds, or until + // the new_handler decides to terminate. + // + // If allocation fails and there is no new_handler, we throw bad_alloc + // (or return nullptr if exceptions are disabled). void* p; -#if defined(_LIBCPP_WIN32API) - while ((p = _aligned_malloc(size, static_cast(alignment))) == nullptr) -#else - while (::posix_memalign(&p, static_cast(alignment), size) != 0) -#endif + while ((p = std::__libcpp_aligned_alloc(static_cast(alignment), size)) == nullptr) { - // If posix_memalign fails and there is a new_handler, - // call it to try free up memory. std::new_handler nh = std::get_new_handler(); if (nh) nh(); @@ -159,7 +159,6 @@ operator new(std::size_t size, std::align_val_t alignment) _THROW_BAD_ALLOC #ifndef _LIBCXXABI_NO_EXCEPTIONS throw std::bad_alloc(); #else - p = nullptr; // posix_memalign doesn't initialize 'p' on failure break; #endif } @@ -171,7 +170,7 @@ _LIBCXXABI_WEAK void* operator new(size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT { - void* p = 0; + void* p = nullptr; #ifndef _LIBCXXABI_NO_EXCEPTIONS try { @@ -197,7 +196,7 @@ _LIBCXXABI_WEAK void* operator new[](size_t size, std::align_val_t alignment, const std::nothrow_t&) _NOEXCEPT { - void* p = 0; + void* p = nullptr; #ifndef _LIBCXXABI_NO_EXCEPTIONS try { @@ -216,12 +215,9 @@ _LIBCXXABI_WEAK void operator delete(void* ptr, std::align_val_t) _NOEXCEPT { - if (ptr) -#if defined(_LIBCPP_WIN32API) - ::_aligned_free(ptr); -#else - ::free(ptr); -#endif + if (ptr) { + std::__libcpp_aligned_free(ptr); + } } _LIBCXXABI_WEAK diff --git a/lib/libcxxabi/src/stdlib_stdexcept.cpp b/lib/libcxxabi/src/stdlib_stdexcept.cpp index 2cff8ee2f0..4a464e4889 100644 --- a/lib/libcxxabi/src/stdlib_stdexcept.cpp +++ b/lib/libcxxabi/src/stdlib_stdexcept.cpp @@ -6,7 +6,7 @@ // //===----------------------------------------------------------------------===// -#include "include/refstring.h" +#include "../../libcxx/src/include/refstring.h" #include "stdexcept" #include "new" #include