[libcxx-commits] [libcxx] [ASan][libc++] Optimize `__annotate_delete` for the default allocator (PR #76176)

via libcxx-commits libcxx-commits at lists.llvm.org
Thu Dec 21 13:23:39 PST 2023


https://github.com/AdvenamTacet updated https://github.com/llvm/llvm-project/pull/76176

>From 67477f556e8997a2019813f1464038252c8df6d0 Mon Sep 17 00:00:00 2001
From: Advenam Tacet <advenam.tacet at trailofbits.com>
Date: Thu, 21 Dec 2023 19:44:34 +0100
Subject: [PATCH 1/2] [ASan][libc++] Optimize `__annotate_delete` for the
 default allocator

This commit optimizes the ASan helper functions `__annotate_delete()`, in `std::basic_string`, `std::vector` and `std::deque`, by adding `if` statements to prevent unpoisoning of memory for the default allocator. Unpoisoning is not required by the default allocator, and since it is widely used, this optimization should yield a meaningful performance improvement.

The optimization was suggested by @EricWF.
---
 libcxx/include/deque  | 3 +++
 libcxx/include/string | 6 ++++--
 libcxx/include/vector | 4 +++-
 3 files changed, 10 insertions(+), 3 deletions(-)

diff --git a/libcxx/include/deque b/libcxx/include/deque
index d0520b635bcc8f..91e2b73d83e2f5 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -1007,6 +1007,9 @@ private:
   }
 
   _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
+    // The default allocator does not require unpoisoning before returning memory.
+    if _LIBCPP_CONSTEXPR (is_same<allocator_type, allocator<_Tp>>::value)
+      return;
     if (empty()) {
       for (size_t __i = 0; __i < __map_.size(); ++__i) {
         __annotate_whole_block(__i, __asan_unposion);
diff --git a/libcxx/include/string b/libcxx/include/string
index fdffca5aed18be..08180ffb130d8a 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1908,8 +1908,10 @@ private:
   }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_delete() const _NOEXCEPT {
-    if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
-      __annotate_contiguous_container(data() + size() + 1, data() + capacity() + 1);
+    // The default allocator does not require unpoisoning before returning memory.
+    if _LIBCPP_CONSTEXPR (!is_same<allocator_type, allocator<__default_allocator_type>>::value)
+      if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
+        __annotate_contiguous_container(data() + size() + 1, data() + capacity() + 1);
   }
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_increase(size_type __n) const _NOEXCEPT {
diff --git a/libcxx/include/vector b/libcxx/include/vector
index 3abc917f5c0e18..1b95e1e5c88b75 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -849,7 +849,9 @@ private:
   }
 
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
-    __annotate_contiguous_container(data(), data() + capacity(), data() + size(), data() + capacity());
+    // The default allocator does not require unpoisoning before returning memory.
+    if _LIBCPP_CONSTEXPR (!is_same<allocator_type, __default_allocator_type>::value)
+      __annotate_contiguous_container(data(), data() + capacity(), data() + size(), data() + capacity());
   }
 
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_increase(size_type __n) const _NOEXCEPT {

>From 50840fab203668f1850d54d77213facccc6fca11 Mon Sep 17 00:00:00 2001
From: Advenam Tacet <advenam.tacet at trailofbits.com>
Date: Thu, 21 Dec 2023 22:21:31 +0100
Subject: [PATCH 2/2] C++03 fix

---
 libcxx/include/deque  | 2 +-
 libcxx/include/string | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/libcxx/include/deque b/libcxx/include/deque
index 91e2b73d83e2f5..1158ed804592ee 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -1008,7 +1008,7 @@ private:
 
   _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
     // The default allocator does not require unpoisoning before returning memory.
-    if _LIBCPP_CONSTEXPR (is_same<allocator_type, allocator<_Tp>>::value)
+    if _LIBCPP_CONSTEXPR (is_same<allocator_type, allocator<_Tp> >::value)
       return;
     if (empty()) {
       for (size_t __i = 0; __i < __map_.size(); ++__i) {
diff --git a/libcxx/include/string b/libcxx/include/string
index 08180ffb130d8a..a708fc79a56c08 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1909,7 +1909,7 @@ private:
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_delete() const _NOEXCEPT {
     // The default allocator does not require unpoisoning before returning memory.
-    if _LIBCPP_CONSTEXPR (!is_same<allocator_type, allocator<__default_allocator_type>>::value)
+    if _LIBCPP_CONSTEXPR (!is_same<allocator_type, allocator<__default_allocator_type> >::value)
       if (!__libcpp_is_constant_evaluated() && (__asan_short_string_is_annotated() || __is_long()))
         __annotate_contiguous_container(data() + size() + 1, data() + capacity() + 1);
   }



More information about the libcxx-commits mailing list