stage2 大量优化代码使其自举编译时间大幅缩短

This commit is contained in:
zzy committed 2026-09-20 09:33:20 +08:00
1 parent e02b0c633a
commit 846f441e3a
38 files changed
+2418 -835

No files matched your search

+641
View File
@@ -348,6 +348,10 @@ static spl_vm_val_t vm_timestamp(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
if (!_vm)
return 0;
return (spl_vm_val_t)_vm->steps;
case 5:
if (!_vm)
return 0;
return (spl_vm_val_t)_vm->ncalls;
case 4:
return has_time ? (spl_vm_val_t)((unsigned long long)ts.tv_sec * 1000000000ull +
(unsigned long long)ts.tv_nsec)
@@ -493,6 +497,623 @@ SYSCALL_1(vm_run, spl_vm_t *, spl_vm_run_until(a1, 0))
* prog->natives against known syscall names and hooks up impl_fn.
* ================================================================= */
/* =================================================================
* Native std containers (spike: Vec valid/push_raw/get)
*
* 布局镜像 stage2/utils/vec.spl 的 Vec:
* raw, data, len, cap, elem_size, elem_align (均为机器字)
* 结构体按值传递/复制由 SPL 负责,native 只按指针操作。
* ================================================================= */
typedef struct {
uintptr_t raw;
uintptr_t data;
uintptr_t len;
uintptr_t cap;
uintptr_t elem_size;
uintptr_t elem_align;
} spl_vec_t;
static int spl_vec_is_valid(const spl_vec_t *v) {
if (v->elem_size == 0)
return 0;
uintptr_t a = v->elem_align;
if (a == 0 || (a & (a - 1)) != 0)
return 0;
if (v->len > v->cap)
return 0;
if (v->cap == 0)
return v->raw == 0 && v->data == 0 && v->len == 0;
if (v->raw == 0 || v->data == 0)
return 0;
return (v->data & (a - 1)) == 0;
}
static spl_vm_val_t vm_vec_valid(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_valid", 1);
const spl_vec_t *v = (const spl_vec_t *)(uintptr_t)args[0];
return (spl_vm_val_t)(v ? spl_vec_is_valid(v) : 0);
}
static spl_vm_val_t vm_vec_push_raw(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_push_raw", 2);
spl_vec_t *v = (spl_vec_t *)(uintptr_t)args[0];
const void *elem = (const void *)(uintptr_t)args[1];
if (!v || !elem)
return 0;
if (v->len < v->cap) {
memcpy((void *)(v->data + v->len * v->elem_size), elem, v->elem_size);
v->len++;
return 1;
}
return 0;
}
/* out 接收元素指针;返回 0 成功,1 无效参数,2 越界。 */
static int spl_vec_reserve_raw(spl_vec_t *v, uintptr_t need);
static spl_vm_val_t vm_vec_push(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_push", 2);
spl_vec_t *v = (spl_vec_t *)(uintptr_t)args[0];
const void *elem = (const void *)(uintptr_t)args[1];
if (!v || !elem || !spl_vec_is_valid(v))
return 1;
if (v->len < v->cap) {
memcpy((void *)(v->data + v->len * v->elem_size), elem, v->elem_size);
v->len++;
return 0;
}
int rc = spl_vec_reserve_raw(v, v->len + 1);
if (rc)
return rc;
memmove((void *)(v->data + v->len * v->elem_size), elem, v->elem_size);
v->len++;
return 0;
}
static spl_vm_val_t vm_vec_get(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_get", 3);
const spl_vec_t *v = (const spl_vec_t *)(uintptr_t)args[0];
uintptr_t index = (uintptr_t)args[1];
uintptr_t *out = (uintptr_t *)(uintptr_t)args[2];
if (!v || !out)
return 1;
if (!spl_vec_is_valid(v))
return 1;
if (index >= v->len)
return 2;
*out = v->data + index * v->elem_size;
return 0;
}
/* 错误码统一:0 ok / 1 InvalidArgument / 2 OutOfRange / 3 Overflow / 4 InvalidAlignment */
static int spl_align_ok(uintptr_t a) { return a != 0 && (a & (a - 1)) == 0; }
static int spl_grow_capacity(uintptr_t current, uintptr_t min_cap, uintptr_t need,
uintptr_t *out) {
uintptr_t cap = current < min_cap ? min_cap : current;
uintptr_t limit = ~(uintptr_t)0;
while (cap < need) {
if (cap > limit / 2) {
cap = need;
break;
}
cap = cap * 2;
}
*out = cap;
return 0;
}
static int spl_vec_allocate(spl_vec_t *out, uintptr_t capacity, uintptr_t elem_size,
uintptr_t elem_align) {
if (elem_size == 0)
return 1;
if (!spl_align_ok(elem_align))
return 4;
out->raw = 0;
out->data = 0;
out->len = 0;
out->cap = 0;
out->elem_size = elem_size;
out->elem_align = elem_align;
if (capacity == 0)
return 0;
if (capacity > ~(uintptr_t)0 / elem_size)
return 3;
uintptr_t bytes = capacity * elem_size;
uintptr_t mask = elem_align - 1;
if (bytes > ~(uintptr_t)0 - mask)
return 3;
uintptr_t total = bytes + mask;
void *raw = malloc(total);
if (!raw)
return 3;
uintptr_t addr = (uintptr_t)raw;
if (addr > ~(uintptr_t)0 - mask) {
free(raw);
return 3;
}
out->raw = addr;
out->data = (addr + mask) & ~mask;
out->cap = capacity;
return 0;
}
static spl_vm_val_t vm_vec_allocate(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_allocate", 4);
spl_vec_t *out = (spl_vec_t *)(uintptr_t)args[0];
if (!out)
return 1;
return (spl_vm_val_t)spl_vec_allocate(out, (uintptr_t)args[1], (uintptr_t)args[2],
(uintptr_t)args[3]);
}
static int spl_vec_reserve_raw(spl_vec_t *v, uintptr_t need) {
if (need <= v->cap)
return 0;
uintptr_t new_cap = 0;
spl_grow_capacity(v->cap, 8, need, &new_cap);
spl_vec_t fresh;
int rc = spl_vec_allocate(&fresh, new_cap, v->elem_size, v->elem_align);
if (rc)
return rc;
uintptr_t used = 0;
if (v->len != 0) {
if (v->len > ~(uintptr_t)0 / v->elem_size) {
free((void *)fresh.raw);
return 3;
}
used = v->len * v->elem_size;
}
if (used != 0)
memcpy((void *)fresh.data, (void *)v->data, used);
fresh.len = v->len;
uintptr_t old = v->raw;
*v = fresh;
if (old)
free((void *)old);
return 0;
}
static spl_vm_val_t vm_vec_reserve_raw(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_reserve_raw", 2);
spl_vec_t *v = (spl_vec_t *)(uintptr_t)args[0];
if (!v)
return 1;
return (spl_vm_val_t)spl_vec_reserve_raw(v, (uintptr_t)args[1]);
}
static spl_vm_val_t vm_vec_append(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_append", 3);
spl_vec_t *v = (spl_vec_t *)(uintptr_t)args[0];
const void *elems = (const void *)(uintptr_t)args[1];
uintptr_t count = (uintptr_t)args[2];
if (!v || !spl_vec_is_valid(v))
return 1;
if (count == 0)
return 0;
if (!elems)
return 1;
if (count > ~(uintptr_t)0 / v->elem_size)
return 3;
uintptr_t copy_bytes = count * v->elem_size;
if (v->len > ~(uintptr_t)0 - count)
return 3;
uintptr_t new_len = v->len + count;
uintptr_t used = v->len * v->elem_size;
int source_inside = 0;
uintptr_t source_offset = 0;
if (used != 0) {
uintptr_t base = v->data;
uintptr_t source = (uintptr_t)elems;
if (source >= base && source - base < used) {
source_offset = source - base;
if (copy_bytes > used - source_offset)
return 2;
source_inside = 1;
}
}
int rc = spl_vec_reserve_raw(v, new_len);
if (rc)
return rc;
if (source_inside)
elems = (const void *)(v->data + source_offset);
memmove((void *)(v->data + used), elems, copy_bytes);
v->len = new_len;
return 0;
}
static spl_vm_val_t vm_vec_set(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_set", 3);
spl_vec_t *v = (spl_vec_t *)(uintptr_t)args[0];
uintptr_t index = (uintptr_t)args[1];
const void *elem = (const void *)(uintptr_t)args[2];
if (!v || !elem || !spl_vec_is_valid(v))
return 1;
if (index >= v->len)
return 2;
memmove((void *)(v->data + index * v->elem_size), elem, v->elem_size);
return 0;
}
static spl_vm_val_t vm_vec_pop(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_pop", 2);
spl_vec_t *v = (spl_vec_t *)(uintptr_t)args[0];
void *out = (void *)(uintptr_t)args[1];
if (!v || !out || !spl_vec_is_valid(v))
return 1;
if (v->len == 0)
return 2;
memmove(out, (void *)(v->data + (v->len - 1) * v->elem_size), v->elem_size);
v->len--;
return 0;
}
static spl_vm_val_t vm_vec_clone(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_clone", 2);
spl_vec_t *out = (spl_vec_t *)(uintptr_t)args[0];
const spl_vec_t *src = (const spl_vec_t *)(uintptr_t)args[1];
if (!out || !src || !spl_vec_is_valid(out) || !spl_vec_is_valid(src))
return 1;
if (out->elem_size != src->elem_size || out->elem_align != src->elem_align)
return 1;
spl_vec_t fresh;
fresh.raw = 0;
fresh.data = 0;
fresh.len = 0;
fresh.cap = 0;
fresh.elem_size = src->elem_size;
fresh.elem_align = src->elem_align;
int rc = spl_vec_reserve_raw(&fresh, src->len);
if (rc)
return rc;
uintptr_t bytes = src->len * src->elem_size;
if (bytes != 0)
memcpy((void *)fresh.data, (void *)src->data, bytes);
fresh.len = src->len;
if (out->raw)
free((void *)out->raw);
*out = fresh;
return 0;
}
static spl_vm_val_t vm_vec_drop(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_vec_drop", 1);
spl_vec_t *v = (spl_vec_t *)(uintptr_t)args[0];
if (!v)
return 0;
uintptr_t es = v->elem_size;
uintptr_t ea = v->elem_align;
if (v->raw)
free((void *)v->raw);
v->raw = 0;
v->data = 0;
v->len = 0;
v->cap = 0;
v->elem_size = es;
v->elem_align = ea;
return 0;
}
static spl_vm_val_t vm_memmove(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
CHECK_NARGS("vm_memmove", 3);
void *dst = (void *)(uintptr_t)args[0];
const void *src = (const void *)(uintptr_t)args[1];
size_t size = (size_t)args[2];
if (size == 0)
return (spl_vm_val_t)(uintptr_t)dst;
ADDRCHECK(_vm, dst, size, "vm_memmove(dst)");
ADDRCHECK(_vm, src, size, "vm_memmove(src)");
memmove(dst, src, size);
return (spl_vm_val_t)(uintptr_t)dst;
}
/* =================================================================
* Native Map(开放寻址 + 墓碑),布局镜像 stage2/utils/map.spl 的 Map。
* hash_kind: 0 = usize;1 = ByteView(按内容);2 = 常量(仅测试用)。
* ================================================================= */
typedef struct {
spl_vec_t keys;
spl_vec_t vals;
spl_vec_t states;
uintptr_t size;
uintptr_t key_size;
uintptr_t val_size;
uintptr_t hash_kind;
} spl_map_t;
static void spl_vec_release(spl_vec_t *v) {
uintptr_t es = v->elem_size;
uintptr_t ea = v->elem_align;
if (v->raw)
free((void *)v->raw);
v->raw = 0;
v->data = 0;
v->len = 0;
v->cap = 0;
v->elem_size = es;
v->elem_align = ea;
}
static uintptr_t spl_hash_usize_value(uintptr_t value) {
uintptr_t prime = 1099511628211ull;
uintptr_t h = value;
h = (h ^ (h >> 30)) * prime;
h = h ^ (h >> 27);
h = h * prime;
h = h ^ (h >> 31);
if (h == 0)
return prime;
return h;
}
static uintptr_t spl_hash_bytes(const void *data, uintptr_t len) {
const unsigned char *p = (const unsigned char *)data;
uintptr_t h = 14695981039346656037ull;
uintptr_t prime = 1099511628211ull;
for (uintptr_t i = 0; i < len; i++)
h = (h ^ (uintptr_t)p[i]) * prime;
return h;
}
static uintptr_t spl_map_hash(const spl_map_t *m, const void *key) {
if (m->hash_kind == 0)
return spl_hash_usize_value(*(const uintptr_t *)key);
if (m->hash_kind == 2)
return 3;
const uintptr_t *v = (const uintptr_t *)key; /* ByteView { ptr, len } */
return spl_hash_bytes((const void *)v[0], v[1]);
}
static int spl_map_eq(const spl_map_t *m, const void *a, const void *b) {
if (m->hash_kind == 0 || m->hash_kind == 2)
return *(const uintptr_t *)a == *(const uintptr_t *)b;
const uintptr_t *x = (const uintptr_t *)a;
const uintptr_t *y = (const uintptr_t *)b;
if (x[1] != y[1])
return 0;
if (x[1] == 0)
return 1;
return memcmp((const void *)x[0], (const void *)y[0], x[1]) == 0;
}
static int spl_map_valid(const spl_map_t *m) {
if (m->key_size == 0 || m->val_size == 0)
return 0;
if (m->keys.len != m->states.len || m->vals.len != m->states.len)
return 0;
if (m->size > m->states.len)
return 0;
return 1;
}
static uintptr_t spl_map_find_slot(const spl_map_t *m, const void *key) {
if (m->states.cap == 0)
return ~(uintptr_t)0;
uintptr_t mask = m->states.cap - 1;
uintptr_t i = spl_map_hash(m, key) & mask;
unsigned char *st = (unsigned char *)m->states.data;
uintptr_t probes = 0;
while (probes < m->states.cap && st[i] != 0) {
if (st[i] == 1 && spl_map_eq(m, (const void *)(m->keys.data + i * m->key_size), key))
return i;
i = (i + 1) & mask;
probes++;
}
return ~(uintptr_t)0;
}
static void spl_map_place(spl_map_t *m, const void *key, const void *val) {
uintptr_t mask = m->states.cap - 1;
uintptr_t i = spl_map_hash(m, key) & mask;
unsigned char *st = (unsigned char *)m->states.data;
uintptr_t first_deleted = ~(uintptr_t)0;
uintptr_t probes = 0;
while (probes < m->states.cap && st[i] != 0) {
if (st[i] == 2 && first_deleted == ~(uintptr_t)0)
first_deleted = i;
i = (i + 1) & mask;
probes++;
}
if (first_deleted != ~(uintptr_t)0)
i = first_deleted;
memcpy((void *)(m->keys.data + i * m->key_size), key, m->key_size);
memcpy((void *)(m->vals.data + i * m->val_size), val, m->val_size);
st[i] = 1;
m->size++;
}
static int spl_map_reserve(spl_map_t *m, uintptr_t need) {
if (!spl_map_valid(m))
return 1;
if (need <= m->states.cap)
return 0;
uintptr_t new_cap = 0;
spl_grow_capacity(m->states.cap, 8, need, &new_cap);
spl_map_t fresh = *m;
fresh.keys.raw = 0;
fresh.keys.data = 0;
fresh.keys.len = 0;
fresh.keys.cap = 0;
fresh.vals.raw = 0;
fresh.vals.data = 0;
fresh.vals.len = 0;
fresh.vals.cap = 0;
fresh.states.raw = 0;
fresh.states.data = 0;
fresh.states.len = 0;
fresh.states.cap = 0;
fresh.size = 0;
int rc = spl_vec_reserve_raw(&fresh.keys, new_cap);
if (rc)
goto fail;
rc = spl_vec_reserve_raw(&fresh.vals, new_cap);
if (rc)
goto fail;
rc = spl_vec_reserve_raw(&fresh.states, new_cap);
if (rc)
goto fail;
fresh.keys.len = new_cap;
fresh.vals.len = new_cap;
fresh.states.len = new_cap;
memset((void *)fresh.states.data, 0, new_cap);
for (uintptr_t i = 0; i < m->states.len; i++) {
if (((unsigned char *)m->states.data)[i] == 1)
spl_map_place(&fresh, (const void *)(m->keys.data + i * m->key_size),
(const void *)(m->vals.data + i * m->val_size));
}
spl_vec_release(&m->keys);
spl_vec_release(&m->vals);
spl_vec_release(&m->states);
*m = fresh;
return 0;
fail:
spl_vec_release(&fresh.keys);
spl_vec_release(&fresh.vals);
spl_vec_release(&fresh.states);
return rc;
}
static spl_vm_val_t vm_bytes_eq(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_bytes_eq", 4);
const void *a = (const void *)(uintptr_t)args[0];
uintptr_t alen = (uintptr_t)args[1];
const void *b = (const void *)(uintptr_t)args[2];
uintptr_t blen = (uintptr_t)args[3];
if (alen != blen)
return 0;
if (alen == 0)
return 1;
if (!a || !b)
return 0;
return memcmp(a, b, alen) == 0;
}
static spl_vm_val_t vm_map_valid(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_map_valid", 1);
const spl_map_t *m = (const spl_map_t *)(uintptr_t)args[0];
return (spl_vm_val_t)(m ? spl_map_valid(m) : 0);
}
static spl_vm_val_t vm_map_reserve(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_map_reserve", 2);
spl_map_t *m = (spl_map_t *)(uintptr_t)args[0];
if (!m)
return 1;
return (spl_vm_val_t)spl_map_reserve(m, (uintptr_t)args[1]);
}
static spl_vm_val_t vm_map_put(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_map_put", 3);
spl_map_t *m = (spl_map_t *)(uintptr_t)args[0];
const void *key = (const void *)(uintptr_t)args[1];
const void *val = (const void *)(uintptr_t)args[2];
if (!m || !key || !val || !spl_map_valid(m))
return 1;
uintptr_t existing = spl_map_find_slot(m, key);
if (existing != ~(uintptr_t)0) {
memcpy((void *)(m->vals.data + existing * m->val_size), val, m->val_size);
return 0;
}
if (m->states.cap == 0) {
int rc = spl_map_reserve(m, 8);
if (rc)
return rc;
} else {
if (m->size > ~(uintptr_t)0 - 1)
return 3;
uintptr_t next_size = m->size + 1;
if (next_size > ~(uintptr_t)0 / 128)
return 3;
uintptr_t scaled = next_size * 128;
if (scaled / m->states.cap >= 70) {
if (m->states.cap > ~(uintptr_t)0 / 2)
return 3;
int rc = spl_map_reserve(m, m->states.cap * 2);
if (rc)
return rc;
}
}
spl_map_place(m, key, val);
return 0;
}
static spl_vm_val_t vm_map_get(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_map_get", 3);
spl_map_t *m = (spl_map_t *)(uintptr_t)args[0];
const void *key = (const void *)(uintptr_t)args[1];
void *out = (void *)(uintptr_t)args[2];
if (!m || !key || !out || !spl_map_valid(m))
return 1;
uintptr_t i = spl_map_find_slot(m, key);
if (i == ~(uintptr_t)0)
return 1;
memcpy(out, (void *)(m->vals.data + i * m->val_size), m->val_size);
return 0;
}
static spl_vm_val_t vm_map_del(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_map_del", 2);
spl_map_t *m = (spl_map_t *)(uintptr_t)args[0];
const void *key = (const void *)(uintptr_t)args[1];
if (!m || !key || !spl_map_valid(m))
return 1;
uintptr_t i = spl_map_find_slot(m, key);
if (i == ~(uintptr_t)0)
return 1;
((unsigned char *)m->states.data)[i] = 2;
m->size--;
return 0;
}
static spl_vm_val_t vm_map_clear(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_map_clear", 1);
spl_map_t *m = (spl_map_t *)(uintptr_t)args[0];
if (!m)
return 0;
if (m->states.data && m->states.len)
memset((void *)m->states.data, 0, m->states.len);
m->size = 0;
return 0;
}
static spl_vm_val_t vm_map_drop(spl_vm_t *_vm, int nargs, spl_vm_val_t *args) {
(void)_vm;
CHECK_NARGS("vm_map_drop", 1);
spl_map_t *m = (spl_map_t *)(uintptr_t)args[0];
if (!m)
return 0;
spl_vec_release(&m->keys);
spl_vec_release(&m->vals);
spl_vec_release(&m->states);
m->size = 0;
return 0;
}
void spl_syscall_register(spl_prog_t *prog) {
static spl_vm_native_t table[] = {
/* OS operations */
@@ -516,6 +1137,26 @@ void spl_syscall_register(spl_prog_t *prog) {
{"vm_memcpy", 0, vm_memcpy},
{"vm_memcmp", 0, vm_memcmp},
{"vm_printf", 0, vm_printf},
{"vm_vec_valid", 0, vm_vec_valid},
{"vm_vec_push_raw", 0, vm_vec_push_raw},
{"vm_vec_push", 0, vm_vec_push},
{"vm_vec_get", 0, vm_vec_get},
{"vm_vec_allocate", 0, vm_vec_allocate},
{"vm_vec_reserve_raw", 0, vm_vec_reserve_raw},
{"vm_vec_append", 0, vm_vec_append},
{"vm_vec_set", 0, vm_vec_set},
{"vm_vec_pop", 0, vm_vec_pop},
{"vm_vec_clone", 0, vm_vec_clone},
{"vm_vec_drop", 0, vm_vec_drop},
{"vm_memmove", 0, vm_memmove},
{"vm_bytes_eq", 0, vm_bytes_eq},
{"vm_map_valid", 0, vm_map_valid},
{"vm_map_reserve", 0, vm_map_reserve},
{"vm_map_put", 0, vm_map_put},
{"vm_map_get", 0, vm_map_get},
{"vm_map_del", 0, vm_map_del},
{"vm_map_clear", 0, vm_map_clear},
{"vm_map_drop", 0, vm_map_drop},
{"vm_timestamp", 0, vm_timestamp},
/* VM operations (comptime) */