From ab5be26af5828e8b83a6d6258f5e5a17f8d47cea Mon Sep 17 00:00:00 2001 From: Kostya Serebryany Date: Thu, 21 Feb 2013 07:07:39 +0000 Subject: [PATCH] [asan] speedup by more than 2x handling of the small memset/memcpy/etc calls llvm-svn: 175728 --- compiler-rt/lib/asan/asan_interceptors.cc | 13 ++++++++++++- compiler-rt/lib/asan/asan_mapping.h | 2 +- compiler-rt/lib/asan/tests/asan_noinst_test.cc | 11 ++++++++++- 3 files changed, 23 insertions(+), 3 deletions(-) diff --git a/compiler-rt/lib/asan/asan_interceptors.cc b/compiler-rt/lib/asan/asan_interceptors.cc index d4fe21c..af4d5a3 100644 --- a/compiler-rt/lib/asan/asan_interceptors.cc +++ b/compiler-rt/lib/asan/asan_interceptors.cc @@ -26,6 +26,16 @@ 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); \ } \ diff --git a/compiler-rt/lib/asan/asan_mapping.h b/compiler-rt/lib/asan/asan_mapping.h index 12035e3..feaf353 100644 --- a/compiler-rt/lib/asan/asan_mapping.h +++ b/compiler-rt/lib/asan/asan_mapping.h @@ -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)) diff --git a/compiler-rt/lib/asan/tests/asan_noinst_test.cc b/compiler-rt/lib/asan/tests/asan_noinst_test.cc index 7c45167..0b8063e 100644 --- a/compiler-rt/lib/asan/tests/asan_noinst_test.cc +++ b/compiler-rt/lib/asan/tests/asan_noinst_test.cc @@ -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"; -- 2.7.4