[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 18:43:00 PST 2023


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

>From d55a13c8b35394d6e6cdc0f3042d2167bcc81bb1 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/3] [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 fca8b3d6e2c737..36e7e6dc6621fa 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -1011,6 +1011,9 @@ private:
 
   _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
 #ifndef _LIBCPP_HAS_NO_ASAN
+    // 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 c676182fba8bac..8a5e4c5e530ce2 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1912,8 +1912,10 @@ private:
 
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_delete() const _NOEXCEPT {
 #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
-    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);
 #endif
   }
 
diff --git a/libcxx/include/vector b/libcxx/include/vector
index 0098273a195ff8..dea2ea3a13b6d0 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -853,7 +853,9 @@ private:
 
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
 #ifndef _LIBCPP_HAS_NO_ASAN
-    __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());
 #endif
   }
 

>From 418cdd7ac97f492231ff145007df306197ff1b13 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/3] 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 36e7e6dc6621fa..790c45c26d80fa 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -1012,7 +1012,7 @@ private:
   _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
 #ifndef _LIBCPP_HAS_NO_ASAN
     // 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 8a5e4c5e530ce2..5c2a6bea90e6c9 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1913,7 +1913,7 @@ private:
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_delete() const _NOEXCEPT {
 #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
     // 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);
 #endif

>From 629e00786578ff0cbb64b107ce21678862c0fd71 Mon Sep 17 00:00:00 2001
From: Advenam Tacet <advenam.tacet at trailofbits.com>
Date: Thu, 21 Dec 2023 23:01:13 +0100
Subject: [PATCH 3/3] if constexpr since C++17

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

diff --git a/libcxx/include/deque b/libcxx/include/deque
index 790c45c26d80fa..73d9a3b3920882 100644
--- a/libcxx/include/deque
+++ b/libcxx/include/deque
@@ -1012,7 +1012,7 @@ private:
   _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
 #ifndef _LIBCPP_HAS_NO_ASAN
     // The default allocator does not require unpoisoning before returning memory.
-    if _LIBCPP_CONSTEXPR (is_same<allocator_type, allocator<_Tp> >::value)
+    if _LIBCPP_CONSTEXPR_SINCE_CXX17 (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 5c2a6bea90e6c9..3e1d468892d0a3 100644
--- a/libcxx/include/string
+++ b/libcxx/include/string
@@ -1913,7 +1913,7 @@ private:
   _LIBCPP_HIDE_FROM_ABI _LIBCPP_CONSTEXPR_SINCE_CXX20 void __annotate_delete() const _NOEXCEPT {
 #if !defined(_LIBCPP_HAS_NO_ASAN) && defined(_LIBCPP_INSTRUMENTED_WITH_ASAN)
     // 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_SINCE_CXX17 (!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);
 #endif
diff --git a/libcxx/include/vector b/libcxx/include/vector
index dea2ea3a13b6d0..5b248ef9d6aa62 100644
--- a/libcxx/include/vector
+++ b/libcxx/include/vector
@@ -854,7 +854,7 @@ private:
   _LIBCPP_CONSTEXPR_SINCE_CXX20 _LIBCPP_HIDE_FROM_ABI void __annotate_delete() const _NOEXCEPT {
 #ifndef _LIBCPP_HAS_NO_ASAN
     // The default allocator does not require unpoisoning before returning memory.
-    if _LIBCPP_CONSTEXPR (!is_same<allocator_type, __default_allocator_type>::value)
+    if _LIBCPP_CONSTEXPR_SINCE_CXX17 (!is_same<allocator_type, __default_allocator_type>::value)
       __annotate_contiguous_container(data(), data() + capacity(), data() + size(), data() + capacity());
 #endif
   }



More information about the libcxx-commits mailing list