[asan] Faster version of QuickCheckForUnpoisonedRegion
authorVitaly Buka <vitalybuka@google.com>
Tue, 9 Aug 2022 04:38:55 +0000 (21:38 -0700)
committerVitaly Buka <vitalybuka@google.com>
Tue, 9 Aug 2022 05:07:35 +0000 (22:07 -0700)
Slightly helps with performance regression after D128146.

compiler-rt/lib/asan/asan_interceptors_memintrinsics.h

index 391e72b..bbc5390 100644 (file)
@@ -26,17 +26,21 @@ namespace __asan {
 // Return true if we can quickly decide that the region is unpoisoned.
 // We assume that a redzone is at least 16 bytes.
 static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
-  if (UNLIKELY(size == 0))
+  if (UNLIKELY(size == 0 || size > sizeof(uptr) * ASAN_SHADOW_GRANULARITY))
+    return !size;
+
+  uptr last = beg + size - 1;
+  uptr shadow_first = MEM_TO_SHADOW(beg);
+  uptr shadow_last = MEM_TO_SHADOW(last);
+  uptr uptr_first = RoundDownTo(shadow_first, sizeof(uptr));
+  uptr uptr_last = RoundDownTo(shadow_last, sizeof(uptr));
+  if (LIKELY(((*reinterpret_cast<const uptr *>(uptr_first) |
+               *reinterpret_cast<const uptr *>(uptr_last)) == 0)))
     return true;
-  if (size <= 32)
-    return !AddressIsPoisoned(beg) && !AddressIsPoisoned(beg + size - 1) &&
-           !AddressIsPoisoned(beg + size / 2);
-  if (size <= 64)
-    return !AddressIsPoisoned(beg) && !AddressIsPoisoned(beg + size / 4) &&
-           !AddressIsPoisoned(beg + size - 1) &&
-           !AddressIsPoisoned(beg + 3 * size / 4) &&
-           !AddressIsPoisoned(beg + size / 2);
-  return false;
+  u8 shadow = AddressIsPoisoned(last);
+  for (; shadow_first < shadow_last; ++shadow_first)
+    shadow |= *((u8 *)shadow_first);
+  return !shadow;
 }
 
 struct AsanInterceptorContext {