mirror of
https://github.com/jart/cosmopolitan.git
synced 2025-07-07 03:38:31 +00:00
Optimize memory layout
This commit is contained in:
parent
0305194d98
commit
b69f3d2488
41 changed files with 383 additions and 347 deletions
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -18,7 +18,6 @@
|
|||
╚─────────────────────────────────────────────────────────────────────────────*/
|
||||
#include "libc/assert.h"
|
||||
#include "libc/dce.h"
|
||||
#include "libc/nt/enum/version.h"
|
||||
#include "libc/nt/version.h"
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue