Optimize memory layout

This commit is contained in:
Justine Tunney 2022-09-12 04:19:32 -07:00
parent 0305194d98
commit b69f3d2488
No known key found for this signature in database
GPG key ID: BE714B4575D6E328
41 changed files with 383 additions and 347 deletions

View file

@ -16,32 +16,62 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/dce.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
#include "libc/macros.internal.h"
#include "libc/runtime/memtrack.internal.h"
#include "libc/runtime/runtime.h"
#include "libc/runtime/winargs.internal.h"
#define ADDR(x) ((int64_t)((uint64_t)(x) << 32) >> 16)
#define UNSHADOW(x) ((int64_t)(MAX(0, (x)-0x7fff8000)) << 3)
#define FRAME(x) ((int)((x) >> 16))
const char *(DescribeFrame)(char buf[32], int x) {
/* asan runtime depends on this function */
char *p;
if (IsShadowFrame(x)) {
ksnprintf(buf, 32, " shadow=%.8x", FRAME(UNSHADOW(ADDR(x))));
return buf;
return " shadow ";
static const char *GetFrameName(int x) {
if (!x) {
return "null";
} else if (IsShadowFrame(x)) {
return "shadow";
} else if (IsAutoFrame(x)) {
return " automap";
return "automap";
} else if (IsFixedFrame(x)) {
return " fixed ";
return "fixed";
} else if (IsArenaFrame(x)) {
return " arena ";
return "arena";
} else if (IsStaticStackFrame(x)) {
return " stack ";
return "stack";
} else if (IsGfdsFrame(x)) {
return "g_fds";
} else if (IsZiposFrame(x)) {
return "zipos";
} else if (IsNsyncFrame(x)) {
return "nsync";
} else if (IsMemtrackFrame(x)) {
return "memtrack";
} else if (IsOldStackFrame(x)) {
return "oldstack";
} else if (IsWindows() &&
(((GetStaticStackAddr(0) + GetStackSize()) >> 16) <= x &&
x <= ((GetStaticStackAddr(0) + GetStackSize() +
sizeof(struct WinArgs) - 1) >>
16))) {
return "winargs";
} else if ((int)((intptr_t)_base >> 16) <= x &&
x <= (int)(((intptr_t)_end - 1) >> 16)) {
return "image";
} else {
return "";
return "unknown";
}
}
const char *(DescribeFrame)(char buf[32], int x) {
char *p;
if (IsShadowFrame(x)) {
ksnprintf(buf, 64, "%s %s %.8x", GetFrameName(x),
GetFrameName(FRAME(UNSHADOW(ADDR(x)))), FRAME(UNSHADOW(ADDR(x))));
return buf;
} else {
return GetFrameName(x);
}
}

View file

@ -49,7 +49,7 @@ const char *(DescribeMapping)(char p[8], int prot, int flags) {
DescribeProt(p, prot);
p[3] = DescribeMapType(flags);
p[4] = (flags & MAP_ANONYMOUS) ? 'a' : '-';
p[6] = (flags & MAP_FIXED) ? 'F' : '-';
p[7] = 0;
p[5] = (flags & MAP_FIXED) ? 'F' : '-';
p[6] = 0;
return p;
}

View file

@ -46,8 +46,9 @@ struct DirectMap sys_mmap(void *addr, size_t size, int prot, int flags, int fd,
} else {
d = sys_mmap_nt(addr, size, prot, flags, fd, off);
}
KERNTRACE("sys_mmap(%.12p%s, %'zu, %s, %s, %d, %'ld) → {%.12p, %p}% m", addr,
DescribeFrame((intptr_t)addr >> 16), size, DescribeProtFlags(prot),
DescribeMapFlags(flags), fd, off, d.addr, d.maphandle);
KERNTRACE("sys_mmap(%.12p /* %s */, %'zu, %s, %s, %d, %'ld) → {%.12p, %p}% m",
addr, DescribeFrame((intptr_t)addr >> 16), size,
DescribeProtFlags(prot), DescribeMapFlags(flags), fd, off, d.addr,
d.maphandle);
return d;
}

View file

@ -18,7 +18,6 @@
*/
#include "libc/assert.h"
#include "libc/dce.h"
#include "libc/nt/enum/version.h"
#include "libc/nt/version.h"
/**

View file

@ -37,11 +37,20 @@
#include "libc/sysv/consts/prot.h"
#include "libc/sysv/errfuns.h"
#if IsModeDbg()
#define ASSERT_MEMTRACK() \
if (!AreMemoryIntervalsOk(mm)) { \
PrintMemoryIntervals(2, mm); \
notpossible; \
}
#else
#define ASSERT_MEMTRACK()
#endif
static void *MoveMemoryIntervals(struct MemoryInterval *d,
const struct MemoryInterval *s, int n) {
// asan runtime depends on this function
int i;
assert(n >= 0);
if (n < 0) unreachable;
if (d > s) {
for (i = n; i--;) {
d[i] = s[i];
@ -55,9 +64,8 @@ static void *MoveMemoryIntervals(struct MemoryInterval *d,
}
static void RemoveMemoryIntervals(struct MemoryIntervals *mm, int i, int n) {
// asan runtime depends on this function
assert(i >= 0);
assert(i + n <= mm->i);
if (i < 0) unreachable;
if (i + n > mm->i) unreachable;
MoveMemoryIntervals(mm->p + i, mm->p + i + n, mm->i - (i + n));
mm->i -= n;
}
@ -96,19 +104,14 @@ static bool ExtendMemoryIntervals(struct MemoryIntervals *mm) {
if (!dm.addr) return false;
mm->n = (size + gran) / sizeof(*mm->p);
}
#if IsModeDbg()
assert(AreMemoryIntervalsOk(mm));
#endif
ASSERT_MEMTRACK();
return true;
}
int CreateMemoryInterval(struct MemoryIntervals *mm, int i) {
// asan runtime depends on this function
int rc;
rc = 0;
assert(i >= 0);
assert(i <= mm->i);
assert(mm->n >= 0);
if (i < 0) unreachable;
if (i > mm->i) unreachable;
if (mm->n < 0) unreachable;
if (UNLIKELY(mm->i == mm->n) && !ExtendMemoryIntervals(mm)) return enomem();
MoveMemoryIntervals(mm->p + i + 1, mm->p + i, mm->i++ - i);
return 0;
@ -126,12 +129,9 @@ static int PunchHole(struct MemoryIntervals *mm, int x, int y, int i) {
int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
void wf(struct MemoryIntervals *, int, int)) {
unsigned l, r;
#if IsModeDbg()
assert(y >= x);
assert(AreMemoryIntervalsOk(mm));
#endif
ASSERT_MEMTRACK();
if (y < x) unreachable;
if (!mm->i) return 0;
// binary search for the lefthand side
l = FindMemoryInterval(mm, x);
if (l == mm->i) return 0;
@ -140,8 +140,8 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
// binary search for the righthand side
r = FindMemoryInterval(mm, y);
if (r == mm->i || (r > l && y < mm->p[r].x)) --r;
assert(r >= l);
assert(x <= mm->p[r].y);
if (r < l) unreachable;
if (x > mm->p[r].y) unreachable;
// remove the middle of an existing map
//
@ -162,11 +162,11 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
// ----|mmmm|----------------- after
//
if (x > mm->p[l].x && x <= mm->p[l].y) {
assert(y >= mm->p[l].y);
if (y < mm->p[l].y) unreachable;
if (IsWindows()) return einval();
mm->p[l].size -= (size_t)(mm->p[l].y - (x - 1)) * FRAMESIZE;
mm->p[l].y = x - 1;
assert(mm->p[l].x <= mm->p[l].y);
if (mm->p[l].x > mm->p[l].y) unreachable;
++l;
}
@ -177,11 +177,11 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
// ---------------|mm|-------- after
//
if (y >= mm->p[r].x && y < mm->p[r].y) {
assert(x <= mm->p[r].x);
if (x > mm->p[r].x) unreachable;
if (IsWindows()) return einval();
mm->p[r].size -= (size_t)((y + 1) - mm->p[r].x) * FRAMESIZE;
mm->p[r].x = y + 1;
assert(mm->p[r].x <= mm->p[r].y);
if (mm->p[r].x > mm->p[r].y) unreachable;
--r;
}
@ -197,16 +197,9 @@ int ReleaseMemoryIntervals(struct MemoryIntervals *mm, int x, int y,
int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
int prot, int flags, bool readonlyfile, bool iscow,
long offset, long size) {
// asan runtime depends on this function
unsigned i;
#if IsModeDbg()
assert(y >= x);
if (!AreMemoryIntervalsOk(mm)) {
PrintMemoryIntervals(2, mm);
}
assert(AreMemoryIntervalsOk(mm));
#endif
ASSERT_MEMTRACK();
if (y < x) unreachable;
i = FindMemoryInterval(mm, x);
// try to extend the righthand side of the lefthand entry
@ -249,5 +242,6 @@ int TrackMemoryInterval(struct MemoryIntervals *mm, int x, int y, long h,
mm->p[i].iscow = iscow;
mm->p[i].readonlyfile = readonlyfile;
}
return 0;
}

View file

@ -16,6 +16,7 @@
TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
PERFORMANCE OF THIS SOFTWARE.
*/
#include "libc/fmt/conv.h"
#include "libc/fmt/itoa.h"
#include "libc/intrin/describeflags.internal.h"
#include "libc/intrin/kprintf.h"
@ -34,28 +35,26 @@ static bool IsNoteworthyHole(unsigned i, const struct MemoryIntervals *mm) {
}
void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) {
char *p, mappingbuf[8], framebuf[32];
long i, w, frames, maptally = 0, gaptally = 0;
char *p, mappingbuf[8], framebuf[64], sb[16];
long i, w, frames, maptally = 0;
for (w = i = 0; i < mm->i; ++i) {
w = MAX(w, LengthInt64Thousands(mm->p[i].y + 1 - mm->p[i].x));
}
for (i = 0; i < mm->i; ++i) {
frames = mm->p[i].y + 1 - mm->p[i].x;
maptally += frames;
kprintf("%08x-%08x %s %'*ldx%s", mm->p[i].x, mm->p[i].y,
kprintf("%08x-%08x %s %'*ldx %s", mm->p[i].x, mm->p[i].y,
(DescribeMapping)(mappingbuf, mm->p[i].prot, mm->p[i].flags), w,
frames, (DescribeFrame)(framebuf, mm->p[i].x));
if (mm->p[i].iscow) kprintf(" cow");
if (mm->p[i].readonlyfile) kprintf(" readonlyfile");
if (mm->p[i].size !=
(size_t)(mm->p[i].y - mm->p[i].x) * FRAMESIZE + FRAMESIZE) {
kprintf(" size=%'zu", mm->p[i].size);
}
sizefmt(sb, mm->p[i].size, 1024);
kprintf(" %sB", sb);
if (i + 1 < mm->i) {
frames = mm->p[i + 1].x - mm->p[i].y - 1;
if (frames && IsNoteworthyHole(i, mm)) {
gaptally += frames;
kprintf(" w/ %'ld frame hole", frames);
sizefmt(sb, frames * FRAMESIZE, 1024);
kprintf(" w/ %sB hole", sb);
}
}
if (mm->p[i].h != -1) {
@ -63,5 +62,6 @@ void PrintMemoryIntervals(int fd, const struct MemoryIntervals *mm) {
}
kprintf("\n");
}
kprintf("# %ld frames mapped w/ %'ld frames gapped\n", maptally, gaptally);
sizefmt(sb, maptally * FRAMESIZE, 1024);
kprintf("# %sB total mapped memory\n", sb);
}