>> I wonder where such big difference is coming from. I'll examine perf
>> when I finally get my hands on SPEC2006.
>
> You don't need SPEC, just run something small like bzip2.
Ok, good to know. Here are my results for bunzipping a vmtouched 100M file:
gcc:
0m6.315s
clang:
0m5.570s
clang -fsanitize=address:
0m10.961s
clang -fsanitize=address -mllvm -asan-instrumentation-with-call-threshold=0:
0m21.988s
clang -fsanitize=address -mllvm -asan-outline-checks (my
implementation, see attach):
0m17.345s
So even though my implementation is slightly faster we're still
getting a 70% perf hit.
> regular asan instrumentation requires 1 load.
> a call, which itself does 1 load, costs two more loads (call and ret),
Well, these memory accesses are always cached so I wouldn't expect
them to hurt that much. May make sense to profile of course.
> besides the call puts more pressure on the reg allocator which causes more
> spills.
This sounds reasonable. I wonder if using custom ABI for these
callbacks would help - amd64 marks a lot registers (nine?)
caller-saved whereas checking callbacks only need 3-4 regs on the fast
path. Sadly GCC does not seem to provide generic infrastructure for
custom ABIs.
-Y
--
You received this message because you are subscribed to the Google Groups
"address-sanitizer" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
For more options, visit https://groups.google.com/d/optout.
#include "asan_internal.h"
#include "asan_mapping.h"
// FIXME: add optimized implementation for ARM.
#define DEFINE_ASAN_CHECK(type, size) \
extern "C" \
void __asan_report_ ## type ## size(uptr addr); \
extern "C" INTERFACE_ATTRIBUTE \
void __asan_ ## type ## size(uptr addr); \
void __asan_ ## type ## size(uptr addr) { \
int shadow_val = *(s8 *)MEM_TO_SHADOW(addr); \
int last = (addr & 7) + size - 1; \
if (UNLIKELY(shadow_val && last >= shadow_val)) \
__asan_report_ ## type ## size(addr); \
}
DEFINE_ASAN_CHECK(load, 1)
DEFINE_ASAN_CHECK(load, 2)
DEFINE_ASAN_CHECK(load, 4)
DEFINE_ASAN_CHECK(load, 8)
DEFINE_ASAN_CHECK(store, 1)
DEFINE_ASAN_CHECK(store, 2)
DEFINE_ASAN_CHECK(store, 4)
DEFINE_ASAN_CHECK(store, 8)
// FIXME: this relies on 3-bit shadow scaling
#define DEFINE_ASAN_CHECK16(type) \
extern "C" \
void __asan_report_ ## type ## 16(uptr addr); \
extern "C" INTERFACE_ATTRIBUTE \
void __asan_ ## type ## 16(uptr addr); \
void __asan_ ## type ## 16(uptr addr) { \
int shadow_val1 = *(s8 *)MEM_TO_SHADOW(addr); \
int shadow_val2 = *(s8 *)MEM_TO_SHADOW(addr + 8); \
int last = (addr & 7) + 16 - 1; \
if (UNLIKELY((shadow_val1 && last >= shadow_val1) || \
(shadow_val2 && last >= shadow_val2))) \
__asan_report_ ## type ## 16(addr); \
}
DEFINE_ASAN_CHECK16(load)
DEFINE_ASAN_CHECK16(store)
#define DEFINE_ASAN_CHECK_N(type) \
extern "C" \
void __asan_report_ ## type ## _n(uptr addr, uptr size); \
extern "C" INTERFACE_ATTRIBUTE \
uptr __asan_ ## type ## _n(uptr addr, uptr size); \
uptr __asan_ ## type ## _n(uptr addr, uptr size) { \
if (UNLIKELY(!size)) \
return addr; \
uptr addr_end = addr + size - 1; \
int shadow_val = *(s8 *)MEM_TO_SHADOW(addr); \
int shadow_val_end = *(s8 *)MEM_TO_SHADOW(addr_end); \
int last = addr & 7; \
int last_end = addr_end & 7; \
if (UNLIKELY((shadow_val && last >= shadow_val) || \
(shadow_val_end && last_end >= shadow_val_end))) \
__asan_report_ ## type ## _n(addr, size); \
return addr; \
}
DEFINE_ASAN_CHECK_N(load)
DEFINE_ASAN_CHECK_N(store)