| ... | ... | @@ -39,6 +39,11 @@ magic: u32, |
| 39 | 39 | entry_val: ?u64 = null, |
| 40 | 40 | |
| 41 | 41 | got_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. |
| 44 | got_index_free_list: std.ArrayListUnmanaged(u64) = .{}, |
| 45 | |
| 46 | syms_index_free_list: std.ArrayListUnmanaged(u64) = .{}, |
| 42 | 47 | |
| 43 | 48 | const Bases = struct { |
| 44 | 49 | text: u64, |
| ... | ... | @@ -212,8 +217,12 @@ fn updateFinish(self: *Plan9, decl: *Module.Decl) !void { |
| 212 | 217 | if (decl.link.plan9.sym_index) |s| { |
| 213 | 218 | self.syms.items[s] = sym; |
| 214 | 219 | } else { |
| 215 | | try self.syms.append(self.base.allocator, sym); |
| 216 | | decl.link.plan9.sym_index = self.syms.items.len - 1; |
| 220 | if (self.syms_index_free_list.popOrNull()) |i| { |
| 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 | } |
| 219 | 228 | |
| ... | ... | @@ -244,14 +253,12 @@ pub fn flushModule(self: *Plan9, comp: *Compilation) !void { |
| 244 | 253 | |
| 245 | 254 | const mod = self.base.options.module orelse return error.LinkingWithoutZigSourceUnimplemented; |
| 246 | 255 | |
| 247 | | // TODO I changed this assert from == to >= but this code all needs to be audited; see |
| 248 | | // the comment in `freeDecl`. |
| 249 | | assert(self.got_len >= self.fn_decl_table.count() + self.data_decl_table.count()); |
| 256 | assert(self.got_len == self.fn_decl_table.count() + self.data_decl_table.count() + self.got_index_free_list.items.len); |
| 250 | 257 | const got_size = self.got_len * if (!self.sixtyfour_bit) @as(u32, 4) else 8; |
| 251 | 258 | var got_table = try self.base.allocator.alloc(u8, got_size); |
| 252 | 259 | defer self.base.allocator.free(got_table); |
| 253 | 260 | |
| 254 | | // + 2 for header, got, symbols |
| 261 | // + 3 for header, got, symbols |
| 255 | 262 | var iovecs = try self.base.allocator.alloc(std.os.iovec_const, self.fn_decl_table.count() + self.data_decl_table.count() + 3); |
| 256 | 263 | defer self.base.allocator.free(iovecs); |
| 257 | 264 | |
| ... | ... | @@ -380,18 +387,24 @@ fn addDeclExports( |
| 380 | 387 | } |
| 381 | 388 | |
| 382 | 389 | pub 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 | 390 | // TODO audit the lifetimes of decls table entries. It's possible to get |
| 386 | 391 | // allocateDeclIndexes and then freeDecl without any updateDecl in between. |
| 387 | 392 | // However that is planned to change, see the TODO comment in Module.zig |
| 388 | 393 | // in the deleteUnusedDecl function. |
| 389 | | const is_fn = (decl.ty.zigTypeTag() == .Fn); |
| 394 | const is_fn = (decl.val.tag() == .function); |
| 390 | 395 | if (is_fn) { |
| 391 | 396 | _ = self.fn_decl_table.swapRemove(decl); |
| 392 | 397 | } else { |
| 393 | 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 | } |
| 396 | 409 | |
| 397 | 410 | pub fn updateDeclExports( |
| ... | ... | @@ -418,6 +431,8 @@ pub fn deinit(self: *Plan9) void { |
| 418 | 431 | } |
| 419 | 432 | self.data_decl_table.deinit(self.base.allocator); |
| 420 | 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 | } |
| 422 | 437 | |
| 423 | 438 | pub const Export = ?usize; |
| ... | ... | @@ -481,7 +496,11 @@ pub fn writeSyms(self: *Plan9, buf: *std.ArrayList(u8)) !void { |
| 481 | 496 | |
| 482 | 497 | pub fn allocateDeclIndexes(self: *Plan9, decl: *Module.Decl) !void { |
| 483 | 498 | if (decl.link.plan9.got_index == null) { |
| 484 | | self.got_len += 1; |
| 485 | | decl.link.plan9.got_index = self.got_len - 1; |
| 499 | if (self.got_index_free_list.popOrNull()) |i| { |
| 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 | } |