summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKostya Serebryany <kcc@google.com>2013-02-21 07:07:39 +0000
committerKostya Serebryany <kcc@google.com>2013-02-21 07:07:39 +0000
commita84805f1ccb2b7d4b6c0ba384bd3541fa4eaf808 (patch)
treeb901bd491adc1d509c5df729b9d2e61366831aea
parent20aed578bf010a91222aed0096d87e0d887a28e9 (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
-rw-r--r--lib/asan/asan_interceptors.cc13
-rw-r--r--lib/asan/asan_mapping.h2
-rw-r--r--lib/asan/tests/asan_noinst_test.cc11
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";