stage2 大量优化代码使其自举编译时间大幅缩短
This commit is contained in:
1 parent
e02b0c633a
commit
846f441e3a
38 files changed
+2418
-835
No files matched your search
+71
-26
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user