[asan] speedup by more than 2x handling of the small memset/memcpy/etc calls
authorKostya Serebryany <kcc@google.com>
Thu, 21 Feb 2013 07:07:39 +0000 (07:07 +0000)
committerKostya Serebryany <kcc@google.com>
Thu, 21 Feb 2013 07:07:39 +0000 (07:07 +0000)
llvm-svn: 175728

compiler-rt/lib/asan/asan_interceptors.cc
compiler-rt/lib/asan/asan_mapping.h
compiler-rt/lib/asan/tests/asan_noinst_test.cc

index d4fe21c..af4d5a3 100644 (file)
 
 namespace __asan {
 
+// Return true if we can quickly decide that the region is unpoisoned.
+static inline bool QuickCheckForUnpoisonedRegion(uptr beg, uptr size) {
+  if (size == 0) return true;
+  if (size <= 32)
+    return !AddressIsPoisoned(beg) &&
+           !AddressIsPoisoned(beg + size - 1) &&
+           !AddressIsPoisoned(beg + size / 2);
+  return false;
+}
+
 // We implement ACCESS_MEMORY_RANGE, ASAN_READ_RANGE,
 // and ASAN_WRITE_RANGE as macro instead of function so
 // that no extra frames are created, and stack trace contains
@@ -34,7 +44,8 @@ namespace __asan {
 #define ACCESS_MEMORY_RANGE(offset, size, isWrite) do {                 \
     uptr __offset = (uptr)(offset);                                     \
     uptr __size = (uptr)(size);                                         \
-    if (__asan_region_is_poisoned(__offset, __size)) {                  \
+    if (!QuickCheckForUnpoisonedRegion(__offset, __size) &&             \
+        __asan_region_is_poisoned(__offset, __size)) {                  \
       GET_CURRENT_PC_BP_SP;                                             \
       __asan_report_error(pc, bp, sp, __offset, isWrite, __size);       \
     }                                                                   \
index 12035e3..feaf353 100644 (file)
@@ -206,7 +206,7 @@ static inline bool AddrIsAlignedByGranularity(uptr a) {
 static inline bool AddressIsPoisoned(uptr a) {
   PROFILE_ASAN_MAPPING();
   const uptr kAccessSize = 1;
-  u8 *shadow_address = (u8*)MemToShadow(a);
+  u8 *shadow_address = (u8*)MEM_TO_SHADOW(a);
   s8 shadow_value = *shadow_address;
   if (shadow_value) {
     u8 last_accessed_byte = (a & (SHADOW_GRANULARITY - 1))
index 7c45167..0b8063e 100644 (file)
@@ -764,7 +764,7 @@ TEST(AddressSanitizerInterface, PoisonedRegion) {
 //     10.50%   [.] __sanitizer::mem_is_zero
 // I.e. mem_is_zero should consume ~ SHADOW_GRANULARITY less CPU cycles
 // than memset itself.
-TEST(AddressSanitizerInterface, DISABLED_Stress_memset) {
+TEST(AddressSanitizerInterface, DISABLED_StressLargeMemset) {
   size_t size = 1 << 20;
   char *x = new char[size];
   for (int i = 0; i < 100000; i++)
@@ -772,6 +772,15 @@ TEST(AddressSanitizerInterface, DISABLED_Stress_memset) {
   delete [] x;
 }
 
+// Same here, but we run memset with small sizes.
+TEST(AddressSanitizerInterface, DISABLED_StressSmallMemset) {
+  size_t size = 32;
+  char *x = new char[size];
+  for (int i = 0; i < 100000000; i++)
+    Ident(memset)(x, 0, size);
+  delete [] x;
+}
+
 static const char *kInvalidPoisonMessage = "invalid-poison-memory-range";
 static const char *kInvalidUnpoisonMessage = "invalid-unpoison-memory-range";