authorgravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2021-08-29 16:35:52-04:00
committergravatar for jacoblevgw@gmail.comJacob G-W <jacoblevgw@gmail.com> 2021-09-18 19:44:40-04:00
log4cb2d6bc3e3ab7c27cabdc7318abaea1afc34654
treeb2ea6cb79fa7dd76089160079a4e41b45585f2d2
parentf388b575533b8e36999bc5ee406421feb7e80baa

plan9 linker: add free lists for got_index and sym_index

This allows the same global offset and symbol table index to be re-used if a decl is freed.

1 files changed, 30 insertions(+), 11 deletions(-)

src/link/Plan9.zig+30-11
...@@ -39,6 +39,11 @@ magic: u32,...@@ -39,6 +39,11 @@ magic: u32,
39entry_val: ?u64 = null,39entry_val: ?u64 = null,
4040
41got_len: usize = 0,41got_len: usize = 0,
42// A list of all the free got indexes, so when making a new decl
43// don't make a new one, just use one from here.
44got_index_free_list: std.ArrayListUnmanaged(u64) = .{},
45
46syms_index_free_list: std.ArrayListUnmanaged(u64) = .{},
4247
43const Bases = struct {48const Bases = struct {
44 text: u64,49 text: u64,
...@@ -212,8 +217,12 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void {...@@ -212,8 +217,12 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void {
212 if (decl.link.plan9.sym_index) |s| {217 if (decl.link.plan9.sym_index) |s| {
213 self.syms.items[s] = sym;218 self.syms.items[s] = sym;
214 } else {219 } else {
215 try self.syms.append(self.base.allocator, sym);220 if (self.syms_index_free_list.popOrNull()) |i| {
216 decl.link.plan9.sym_index = self.syms.items.len - 1;221 decl.link.plan9.sym_index = i;
222 } else {
223 try self.syms.append(self.base.allocator, sym);
224 decl.link.plan9.sym_index = self.syms.items.len - 1;
225 }
217 }226 }
218}227}
219228
...@@ -244,14 +253,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {...@@ -244,14 +253,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void {
244253
245 const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;254 const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented;
246255
247 // TODO I changed this assert from == to >= but this code all needs to be audited; see256 assert(self.got_len == self.fn_decl_table.count() + self.data_decl_table.count() + self.got_index_free_list.items.len);
248 // the comment in `freeDecl`.
249 assert(self.got_len >= self.fn_decl_table.count() + self.data_decl_table.count());
250 const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8;257 const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8;
251 var got_table = try self.base.allocator.alloc(u8, got_size);258 var got_table = try self.base.allocator.alloc(u8, got_size);
252 defer self.base.allocator.free(got_table);259 defer self.base.allocator.free(got_table);
253260
254 // + 2 for header, got, symbols261 // + 3 for header, got, symbols
255 var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.fn_decl_table.count() + self.data_decl_table.count() + 3);262 var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.fn_decl_table.count() + self.data_decl_table.count() + 3);
256 defer self.base.allocator.free(iovecs);263 defer self.base.allocator.free(iovecs);
257264
...@@ -380,18 +387,24 @@ fn addDeclExports(...@@ -380,18 +387,24 @@ fn addDeclExports(
380}387}
381388
382pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void {389pub fn freeDecl(self: *Plan9, decl: *Module.Decl) void {
383 // TODO this is not the correct check for being function body,
384 // it could just be a function pointer.
385 // TODO audit the lifetimes of decls table entries. It's possible to get390 // TODO audit the lifetimes of decls table entries. It's possible to get
386 // allocateDeclIndexes and then freeDecl without any updateDecl in between.391 // allocateDeclIndexes and then freeDecl without any updateDecl in between.
387 // However that is planned to change, see the TODO comment in Module.zig392 // However that is planned to change, see the TODO comment in Module.zig
388 // in the deleteUnusedDecl function.393 // in the deleteUnusedDecl function.
389 const is_fn = (decl.ty.zigTypeTag() == .Fn);394 const is_fn = (decl.val.tag() == .function);
390 if (is_fn) {395 if (is_fn) {
391 _ = self.fn_decl_table.swapRemove(decl);396 _ = self.fn_decl_table.swapRemove(decl);
392 } else {397 } else {
393 _ = self.data_decl_table.swapRemove(decl);398 _ = self.data_decl_table.swapRemove(decl);
394 }399 }
400 if (decl.link.plan9.got_index) |i| {
401 // TODO: if this catch {} is triggered, an assertion in flushModule will be triggered, because got_index_free_list will have the wrong length
402 self.got_index_free_list.append(self.base.allocator, i) catch {};
403 }
404 if (decl.link.plan9.sym_index) |i| {
405 self.syms_index_free_list.append(self.base.allocator, i) catch {};
406 self.syms.items[i] = undefined;
407 }
395}408}
396409
397pub fn updateDeclExports(410pub fn updateDeclExports(
...@@ -418,6 +431,8 @@ pub fn deinit(self: *Plan9) void {...@@ -418,6 +431,8 @@ pub fn deinit(self: *Plan9) void {
418 }431 }
419 self.data_decl_table.deinit(self.base.allocator);432 self.data_decl_table.deinit(self.base.allocator);
420 self.syms.deinit(self.base.allocator);433 self.syms.deinit(self.base.allocator);
434 self.got_index_free_list.deinit(self.base.allocator);
435 self.syms_index_free_list.deinit(self.base.allocator);
421}436}
422437
423pub const Export = ?usize;438pub const Export = ?usize;
...@@ -481,7 +496,11 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {...@@ -481,7 +496,11 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void {
481496
482pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void {497pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void {
483 if (decl.link.plan9.got_index == null) {498 if (decl.link.plan9.got_index == null) {
484 self.got_len += 1;499 if (self.got_index_free_list.popOrNull()) |i| {
485 decl.link.plan9.got_index = self.got_len - 1;500 decl.link.plan9.got_index = i;
501 } else {
502 self.got_len += 1;
503 decl.link.plan9.got_index = self.got_len - 1;
504 }
486 }505 }
487}506}