diff options
author | Kostya Serebryany <kcc@google.com> | 2013-02-21 07:07:39 +0000 |
---|---|---|
committer | Kostya Serebryany <kcc@google.com> | 2013-02-21 07:07:39 +0000 |
commit | a84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808 (patch) | |
tree | b901bd491adc1d509c5df729b9d2e61366831aea /lib | |
parent | 20aed578bf010a91222aed0096d87e0d887a28e9 (diff) |
[asan] speedup by more than 2x handling of the small memset/memcpy/etc calls
git-svn-id: https://llvm.org/svn/llvm-project/compiler-rt/trunk@175728 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib')
-rw-r--r-- | lib/asan/asan_interceptors.cc | 13 | ||||
-rw-r--r-- | lib/asan/asan_mapping.h | 2 | ||||
-rw-r--r-- | lib/asan/tests/asan_noinst_test.cc | 11 |
3 files changed, 23 insertions, 3 deletions
diff --git a/lib/asan/asan_interceptors.cc b/lib/asan/asan_interceptors.cc index d4fe21c55..af4d5a313 100644 --- a/lib/asan/asan_interceptors.cc +++ b/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/lib/asan/asan_mapping.h b/lib/asan/asan_mapping.h index 12035e3d3..feaf35338 100644 --- a/lib/asan/asan_mapping.h +++ b/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/lib/asan/tests/asan_noinst_test.cc b/lib/asan/tests/asan_noinst_test.cc index 7c45167c2..0b8063eb3 100644 --- a/lib/asan/tests/asan_noinst_test.cc +++ b/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"; |