>> 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)

Reply via email to