diff --git a/README.md b/README.md index 5b49691..423671e 100644 --- a/README.md +++ b/README.md @@ -16,6 +16,15 @@ translation is most of each function; what an above-libc implementation has to get right is the places where the C library's vocabulary and openkal's do **not** correspond, and those are the places the sources comment individually. +## What 0.14.3 corrects + +The descriptor-rights tables (4,096 entries and 64 roots) had members whose +defaults were -1, so the whole tables were initialised data: about 80 KiB in +every Web build's binary, though no entry is used until a descriptor is +opened. Every member's default is now zero; a slot taken gives its sentinels. +Measured with emsdk 6.0.9 at -O2: `g_entries` and `g_roots` move from `.data` +to `.bss`. No behaviour changes. + ## What 0.14.2 corrects The manifest declares `openkal = "^0.25.0"`. An implementation written against a @@ -248,7 +257,7 @@ implementation in its source: openkal = "0.25.0" [target.'cfg(os = "emscripten")'.dependencies] -openkal-emscripten = "0.14.2" +openkal-emscripten = "0.14.3" ``` ## Licence diff --git a/mcpp.toml b/mcpp.toml index 9968e14..7f6334f 100644 --- a/mcpp.toml +++ b/mcpp.toml @@ -1,7 +1,7 @@ [package] namespace = "mcpplibs" name = "openkal-emscripten" -version = "0.14.2" +version = "0.14.3" description = "An implementation of openkal for Emscripten, written ABOVE a C library rather than beneath one, because on this platform there is no kernel to issue calls to." license = "Apache-2.0" diff --git a/src/rights.cpp b/src/rights.cpp index 3914924..0e8e389 100644 --- a/src/rights.cpp +++ b/src/rights.cpp @@ -77,12 +77,14 @@ struct keyset { constexpr int kRoots = 64; constexpr uptr kBatch = 64 * 1024; +// Every member's default is zero, so the table is zero-filled memory and not +// bytes of the program (64 roots); `new_root' gives a live one its -1s. struct root { bool live = false; int refs = 0; unsigned flags = 0; - int base = -1; // a descriptor of the root, to list beneath - int record = -1; // opened to append + int base = 0; // a descriptor of the root, to list beneath (-1 when live and none) + int record = 0; // opened to append (-1 when live and none) char* rprefix = nullptr; uptr rplen = 0; keyset seen; @@ -94,9 +96,13 @@ struct root { }; root g_roots[kRoots]; +// As the roots: zero by default, so 4096 entries cost the program no bytes +// (with fd = -1 and root = -1 they were ~80 KiB of its data, every page of a +// Web build carried them); `new_entry' gives a used one its root of -1. struct entry { - int fd = -1; - int root = -1; + bool used = false; + int fd = 0; + int root = 0; unsigned flags = 0; char* prefix = nullptr; uptr plen = 0; @@ -113,19 +119,27 @@ entry* entry_of(int fd) { entry* new_entry(int fd) { if (fd < 0 || fd >= kMaxDescriptor) return nullptr; for (int i = 0; i < kEntries; ++i) - if (g_entries[i].fd < 0) { g_entries[i].fd = fd; g_slot[fd] = static_cast(i + 1); return &g_entries[i]; } + if (!g_entries[i].used) { + g_entries[i] = entry{.used = true, .fd = fd, .root = -1}; + g_slot[fd] = static_cast(i + 1); + return &g_entries[i]; + } return nullptr; } void drop_entry(entry* e) { if (!e) return; - if (e->fd >= 0 && e->fd < kMaxDescriptor) g_slot[e->fd] = 0; + if (e->used && e->fd >= 0 && e->fd < kMaxDescriptor) g_slot[e->fd] = 0; ::free(e->prefix); *e = entry{}; } int new_root() { - for (int i = 0; i < kRoots; ++i) if (!g_roots[i].live) { g_roots[i] = root{}; g_roots[i].live = true; return i; } + for (int i = 0; i < kRoots; ++i) if (!g_roots[i].live) { + g_roots[i] = root{}; + g_roots[i].live = true, g_roots[i].base = -1, g_roots[i].record = -1; + return i; + } return -1; }