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

+71 -26
View File
@@ -265,6 +265,15 @@ fn drop(self: *Prog) {
// ---- 构建 ----
fn add_instr(self: *Prog, op: Op, ty: VmKind, imm: usize): usize {
var i = self.insns.len;
if i < self.insns.cap {
var p = (self.insns.data as *VmIns) + i;
p.opcode = op;
p.ty = ty;
p.imm = imm;
self.insns.len = i + 1;
ret i + 1;
}
var ins = VmIns { .opcode = op, .ty = ty, .imm = imm };
if !Vec.push_raw(&self.insns, &ins as *u8) { ret 0; }
ret self.insns.len;
@@ -462,11 +471,8 @@ fn dump(self: *Prog, out: *ByteBuffer): bool {
}
fn ins_at(self: *Prog, i: usize): VmIns {
match Vec.get(&self.insns, i) {
.Ok(ptr) => { ret (ptr as *VmIns).*; },
.Err(error) => { ret VmIns { .opcode = .Error, .ty = .Void, .imm = 0 }; },
}
ret VmIns { .opcode = .Error, .ty = .Void, .imm = 0 };
if i >= self.insns.len { ret VmIns { .opcode = .Error, .ty = .Void, .imm = 0 }; }
ret ((self.insns.data as *VmIns) + i).*;
}
fn func_at(self: *Prog, i: usize): *VmFunc {
@@ -491,41 +497,43 @@ fn align8(n: usize): usize {
ret (n + 7) & (~(7 as usize));
}
// 说明:以下 put_* 直接写入已预留容量的 ByteBuffer 存储(store 已按精确总大小 reserve),
// 跳过 ByteBuffer.append → Vec.append 的校验/拷贝路径。若容量不足会越界,故 store 先校验容量。
fn put_u8(out: *ByteBuffer, b: u8): bool {
match ByteBuffer.append_byte(out, b) { .Ok => { ret true; }, .Err(error) => { ret false; } }
ret false;
out.storage.data[out.storage.len] = b;
out.storage.len = out.storage.len + 1;
ret true;
}
// 直接按小端整型写(x86 小端;VM 的 STORE 用 memcpy,未对齐也安全)。
fn put_u16(out: *ByteBuffer, v: usize): bool {
if !put_u8(out, (v & 255) as u8) { ret false; }
ret put_u8(out, ((v >> 8) & 255) as u8);
var d = out.storage.data + out.storage.len;
(d as *u16).* = v as u16;
out.storage.len = out.storage.len + 2;
ret true;
}
fn put_u64(out: *ByteBuffer, v: usize): bool {
var i: usize = 0;
while i < 8 {
if !put_u8(out, ((v >> (i * 8)) & 255) as u8) { ret false; }
i = i + 1;
}
var d = out.storage.data + out.storage.len;
(d as *u64).* = v as u64;
out.storage.len = out.storage.len + 8;
ret true;
}
fn put_zeros(out: *ByteBuffer, n: usize): bool {
var i: usize = 0;
while i < n {
if !put_u8(out, 0) { ret false; }
i = i + 1;
if n != 0 {
ignore_ptr(Mem.set((out.storage.data + out.storage.len) as *any, 0, n));
out.storage.len = out.storage.len + n;
}
ret true;
}
fn put_view(out: *ByteBuffer, v: ByteView): bool {
if v.len == 0 { ret true; }
match ByteBuffer.append(out, ByteView.as_slice(v)) {
.Ok => { ret true; },
.Err(error) => { ret false; },
}
ret false;
Mem.copy((out.storage.data + out.storage.len) as *any, v.ptr as *any, v.len);
out.storage.len = out.storage.len + v.len;
ret true;
}
// 写入「带结尾 NUL、再按 8 对齐」的名称字段(对应 C 侧 nlen = strlen+1)。
@@ -541,6 +549,41 @@ fn store(self: *Prog, path: ByteView): Status {
var out = ByteBuffer.new();
defer { ByteBuffer.drop(&out); }
// 精确预估输出大小并一次性预留,避免大文件逐字节增长导致的重复拷贝。
var total: usize = 48;
var fi: usize = 0;
while fi < self.funcs.len {
var f = func_at(self, fi);
if f != null {
var nlen = f.name.len + 1;
total = total + 8 + align8(nlen) + 32;
}
fi = fi + 1;
}
total = total + self.insns.len * 12;
fi = 0;
while fi < self.natives.len {
var n = native_at(self, fi);
if n != null {
var nlen = n.name.len + 1;
total = total + 8 + align8(nlen) + 8;
}
fi = fi + 1;
}
fi = 0;
while fi < self.strtab.len {
total = total + 8 + align8(str_at(self, fi).len);
fi = fi + 1;
}
fi = 1;
while fi < self.gdata.len {
var e = gdata_at(self, fi);
if e != null { total = total + 8 + align8(e.storage.len); }
fi = fi + 1;
}
match ByteBuffer.reserve(&out, total) { .Ok => {}, .Err(error) => {} }
if out.storage.cap < total || out.storage.data == null { ret .Err(make(.Io)); }
if !put_view(&out, ByteView.from_slice("SPLBIN")) { ret .Err(make(.Io)); }
if !put_zeros(&out, 2) { ret .Err(make(.Io)); }
@@ -572,9 +615,11 @@ fn store(self: *Prog, path: ByteView): Status {
i = 0;
while i < ninsns {
var ins = ins_at(self, i);
if !put_u16(&out, @enum2int(ins.opcode) as usize) { ret .Err(make(.Io)); }
if !put_u16(&out, @enum2int(ins.ty) as usize) { ret .Err(make(.Io)); }
if !put_u64(&out, ins.imm) { ret .Err(make(.Io)); }
var d = out.storage.data + out.storage.len;
(d as *u16).* = @enum2int(ins.opcode) as u16;
((d + 2) as *u16).* = @enum2int(ins.ty) as u16;
((d + 4) as *u64).* = ins.imm as u64;
out.storage.len = out.storage.len + 12;
i = i + 1;
}