From d1e511bebdf49c4aacfb3e00253ecd98b37d9a2e Mon Sep 17 00:00:00 2001 From: dzaima Date: Thu, 13 Jul 2023 15:44:09 +0300 Subject: [PATCH] add padding before allocations & document it --- src/README.md | 2 ++ src/core/mm.c | 11 +++++++++++ src/jit/nvm_x86_64.c | 1 + src/opt/mm_buddyTemplate.c | 10 +++------- 4 files changed, 17 insertions(+), 7 deletions(-) diff --git a/src/README.md b/src/README.md index d6a52b5c..b150e9e0 100644 --- a/src/README.md +++ b/src/README.md @@ -150,6 +150,8 @@ See src/h.h for more basics An object can be allocated with `mm_alloc(sizeInBytes, t_something)`. The returned object starts with the structure of `Value`, so custom data must be after that. `mm_free` can be used to force-free an object regardless of its reference count. +Any such allocation is guaranteed to have at least 1024 bytes readable & writable both before & after the allocation, though of course the read values should not affect any visible behavior, and writes need to write back exactly the data that was there before. + A heap-allocated object from type `B` can be cast to a `Value*` with `v(x)`, to an `Arr*` with `a(x)`, or to a specific pointer type with `c(Type,x)`. The reference count of any `B` object can be incremented/decremented with `inc(x)`/`dec(x)`, and any subtype of `Value*` can use `ptr_inc(x)`/`ptr_dec(x)`. `inc(x)` and `ptr_inc(x)` will return the argument, so you can use it inline. `dec(x)` and `ptr_dec(x)` will free the object if the refcount as a result goes to zero. `incBy` / `incByG` offset the reference count by the specified amount, but will not free the object if it results in a reference count of zero. diff --git a/src/core/mm.c b/src/core/mm.c index be657e48..44294319 100644 --- a/src/core/mm.c +++ b/src/core/mm.c @@ -1,7 +1,17 @@ #define MM_C 1 +#define ALLOC_PADDING 1024 // number of accessible padding bytes always required around an object #include "../core.h" +usz getPageSize(void); +static u64 prepAllocSize(u64 sz) { + u64 psz = getPageSize(); + u64 minTotPad = ALLOC_PADDING*2 + 128; + if (psz < minTotPad) psz = minTotPad; + return sz + psz; +} +#define MMAP(SZ) mmap(NULL, prepAllocSize(SZ), PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) + #if MM==0 #include "../opt/mm_malloc.c" #elif MM==1 @@ -11,3 +21,4 @@ #else #error "bad MM value" #endif +#undef MMAP diff --git a/src/jit/nvm_x86_64.c b/src/jit/nvm_x86_64.c index 1c9b321c..2c956a84 100644 --- a/src/jit/nvm_x86_64.c +++ b/src/jit/nvm_x86_64.c @@ -68,6 +68,7 @@ static void* mmX_allocN(usz sz, u8 type) { assert(sz>=16); return mmX_allocL(64- #undef BN #undef BSZ #undef ALLOC_IMPL_MMX +#undef MMAP // all the instructions to be called by the generated code diff --git a/src/opt/mm_buddyTemplate.c b/src/opt/mm_buddyTemplate.c index 901ba39c..dad67b40 100644 --- a/src/opt/mm_buddyTemplate.c +++ b/src/opt/mm_buddyTemplate.c @@ -5,10 +5,6 @@ #define al BN(al) #define alCap BN(alCap) #define alSize BN(alSize) -#ifndef MMAP - usz getPageSize(void); - #define MMAP(SZ) mmap(NULL, (SZ)+getPageSize(), PROT_READ|PROT_WRITE, MAP_NORESERVE|MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) -#endif #define str0(X) #X #define str1(X) str0(X) @@ -82,8 +78,9 @@ static NOINLINE void* BN(allocateMore)(i64 bucket, u8 type, i64 from, i64 to) { if (mem==MAP_FAILED) thrOOM(); if (ptr2u64(mem)+sz > (1ULL<<48)) fatal("mmap returned address range above 2⋆48"); #if ALLOC_MODE==0 - // ux off = offsetof(TyArr,a); - // if (off&31) mem+= 32-(off&31); // align heap such that arr->a is 32-byte-aligned + mem+= ALLOC_PADDING; + // ux off = offsetof(TyArr,a); + // if (off&31) mem+= 32-(off&31); // align heap such that arr->a is 32-byte-aligned #endif EmptyValue* c = (void*)mem; #endif @@ -207,7 +204,6 @@ void BN(dumpHeap)(FILE* f) { fflush(f); } -#undef MMAP #undef AllocInfo #undef buckets #undef al