Add memcpy with bounds checks.
The memcpy implementation is not completely stupid but is almost certainly not as good as a carefully tuned and optimised one. Building snmalloc with FreeBSD's libc memcpy + jemalloc and with this, each 10 times, does not show a statistically significant performance difference at 95% confidence. The snmalloc version has very slightly lower median and worst-case times. This is in no way a sensible benchmark, but it serves as a smoke test for significant performance regressions. The CI self-host job now uses the checked memcpy. This also fixes an off-by-one error in the external bounds. This is triggered by ninja, so we will see breakage in CI if it is reintroduced. In debug builds, we provide a verbose error containing the address of the allocation, the base and bounds of the allocation, and a backtrace. The backtrace was broken by the CI cleanup moving the BACKTRACE_HEADER macro into the SNMALLOC_ namespace. This is also fixed. The test involves hijacking `abort`, which doesn't work everywhere. It also requires `backtrace` to work in configurations where stack traces are enabled. This is disabled in QEMU because `backtrace` appears to crash reliably in QEMU user mode. For now, in the -checks build configurations, we are hitting a slow path in the pagemap on accesses so that the pages that are `PROT_NONE` don't cause crashes. These need to be made read-only, but this requires a PAL change.
This commit is contained in:
committed by
David Chisnall
parent
d524ef5cac
commit
51e75bca89
@@ -231,11 +231,11 @@ namespace snmalloc
|
||||
* expected to point to the base of some (sub)allocation into which cursor
|
||||
* points; would-be negative answers trip an assertion in debug builds.
|
||||
*/
|
||||
inline size_t pointer_diff(void* base, void* cursor)
|
||||
inline size_t pointer_diff(const void* base, const void* cursor)
|
||||
{
|
||||
SNMALLOC_ASSERT(cursor >= base);
|
||||
return static_cast<size_t>(
|
||||
static_cast<char*>(cursor) - static_cast<char*>(base));
|
||||
static_cast<const char*>(cursor) - static_cast<const char*>(base));
|
||||
}
|
||||
|
||||
template<
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
# define SNMALLOC_PURE
|
||||
# define SNMALLOC_COLD
|
||||
# define SNMALLOC_REQUIRE_CONSTINIT
|
||||
# define SNMALLOC_UNUSED_FUNCTION
|
||||
#else
|
||||
# define likely(x) __builtin_expect(!!(x), 1)
|
||||
# define unlikely(x) __builtin_expect(!!(x), 0)
|
||||
@@ -25,6 +26,7 @@
|
||||
# define SNMALLOC_FAST_PATH_LAMBDA SNMALLOC_FAST_PATH
|
||||
# define SNMALLOC_PURE __attribute__((const))
|
||||
# define SNMALLOC_COLD __attribute__((cold))
|
||||
# define SNMALLOC_UNUSED_FUNCTION __attribute((unused))
|
||||
# ifdef __clang__
|
||||
# define SNMALLOC_REQUIRE_CONSTINIT \
|
||||
[[clang::require_constant_initialization]]
|
||||
|
||||
Reference in New Issue
Block a user