| ... | @@ -1731,11 +1731,8 @@ pub const File = struct { | ... | @@ -1731,11 +1731,8 @@ pub const File = struct { |
| 1731 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { | 1731 | pub fn allocateDeclIndexes(self: *Elf, decl: *Module.Decl) !void { |
| 1732 | if (decl.link.local_sym_index != 0) return; | 1732 | if (decl.link.local_sym_index != 0) return; |
| 1733 | | 1733 | |
| 1734 | // Here we also ensure capacity for the free lists so that they can be appended to without fail. | | |
| 1735 | try self.local_symbols.ensureCapacity(self.allocator, self.local_symbols.items.len + 1); | 1734 | try self.local_symbols.ensureCapacity(self.allocator, self.local_symbols.items.len + 1); |
| 1736 | try self.local_symbol_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len); | | |
| 1737 | try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1); | 1735 | try self.offset_table.ensureCapacity(self.allocator, self.offset_table.items.len + 1); |
| 1738 | try self.offset_table_free_list.ensureCapacity(self.allocator, self.local_symbols.items.len); | | |
| 1739 | | 1736 | |
| 1740 | if (self.local_symbol_free_list.popOrNull()) |i| { | 1737 | if (self.local_symbol_free_list.popOrNull()) |i| { |
| 1741 | log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name }); | 1738 | log.debug(.link, "reusing symbol index {} for {}\n", .{ i, decl.name }); |
| ... | @@ -1768,15 +1765,37 @@ pub const File = struct { | ... | @@ -1768,15 +1765,37 @@ pub const File = struct { |
| 1768 | } | 1765 | } |
| 1769 | | 1766 | |
| 1770 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { | 1767 | pub fn freeDecl(self: *Elf, decl: *Module.Decl) void { |
| | 1768 | // Appending to free lists is allowed to fail because the free lists are heuristics based anyway. |
| 1771 | self.freeTextBlock(&decl.link); | 1769 | self.freeTextBlock(&decl.link); |
| 1772 | if (decl.link.local_sym_index != 0) { | 1770 | if (decl.link.local_sym_index != 0) { |
| 1773 | self.local_symbol_free_list.appendAssumeCapacity(decl.link.local_sym_index); | 1771 | self.local_symbol_free_list.append(self.allocator, decl.link.local_sym_index) catch {}; |
| 1774 | self.offset_table_free_list.appendAssumeCapacity(decl.link.offset_table_index); | 1772 | self.offset_table_free_list.append(self.allocator, decl.link.offset_table_index) catch {}; |
| 1775 | | 1773 | |
| 1776 | self.local_symbols.items[decl.link.local_sym_index].st_info = 0; | 1774 | self.local_symbols.items[decl.link.local_sym_index].st_info = 0; |
| 1777 | | 1775 | |
| 1778 | decl.link.local_sym_index = 0; | 1776 | decl.link.local_sym_index = 0; |
| 1779 | } | 1777 | } |
| | 1778 | // TODO make this logic match freeTextBlock. Maybe abstract the logic out since the same thing |
| | 1779 | // is desired for both. |
| | 1780 | _ = self.dbg_line_fn_free_list.remove(&decl.fn_link); |
| | 1781 | if (decl.fn_link.prev) |prev| { |
| | 1782 | _ = self.dbg_line_fn_free_list.put(self.allocator, prev, {}) catch {}; |
| | 1783 | prev.next = decl.fn_link.next; |
| | 1784 | if (decl.fn_link.next) |next| { |
| | 1785 | next.prev = prev; |
| | 1786 | } else { |
| | 1787 | self.dbg_line_fn_last = prev; |
| | 1788 | } |
| | 1789 | } else if (decl.fn_link.next) |next| { |
| | 1790 | self.dbg_line_fn_first = next; |
| | 1791 | next.prev = null; |
| | 1792 | } |
| | 1793 | if (self.dbg_line_fn_first == &decl.fn_link) { |
| | 1794 | self.dbg_line_fn_first = null; |
| | 1795 | } |
| | 1796 | if (self.dbg_line_fn_last == &decl.fn_link) { |
| | 1797 | self.dbg_line_fn_last = null; |
| | 1798 | } |
| 1780 | } | 1799 | } |
| 1781 | | 1800 | |
| 1782 | pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { | 1801 | pub fn updateDecl(self: *Elf, module: *Module, decl: *Module.Decl) !void { |
| ... | @@ -1923,18 +1942,35 @@ pub const File = struct { | ... | @@ -1923,18 +1942,35 @@ pub const File = struct { |
| 1923 | | 1942 | |
| 1924 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; | 1943 | const debug_line_sect = &self.sections.items[self.debug_line_section_index.?]; |
| 1925 | const src_fn = &decl.fn_link; | 1944 | const src_fn = &decl.fn_link; |
| | 1945 | src_fn.len = @intCast(u32, dbg_line_buffer.items.len); |
| 1926 | if (self.dbg_line_fn_last) |last| { | 1946 | if (self.dbg_line_fn_last) |last| { |
| 1927 | if (src_fn.prev == null and src_fn.next == null) { | 1947 | if (src_fn.next) |next| { |
| | 1948 | // Update existing function - non-last item. |
| | 1949 | if (src_fn.off + src_fn.len + min_nop_size > next.off) { |
| | 1950 | // It grew too big, so we move it to a new location. |
| | 1951 | if (src_fn.prev) |prev| { |
| | 1952 | _ = self.dbg_line_fn_free_list.put(self.allocator, prev, {}) catch {}; |
| | 1953 | prev.next = src_fn.next; |
| | 1954 | } |
| | 1955 | next.prev = src_fn.prev; |
| | 1956 | // Populate where it used to be with NOPs. |
| | 1957 | const file_pos = debug_line_sect.sh_offset + src_fn.off; |
| | 1958 | try self.pwriteWithNops(0, &[0]u8{}, src_fn.len, file_pos); |
| | 1959 | // TODO Look at the free list before appending at the end. |
| | 1960 | src_fn.prev = last; |
| | 1961 | last.next = src_fn; |
| | 1962 | self.dbg_line_fn_last = src_fn; |
| | 1963 | |
| | 1964 | src_fn.off = last.off + (last.len * alloc_num / alloc_den); |
| | 1965 | } |
| | 1966 | } else if (src_fn.prev == null) { |
| 1928 | // Append new function. | 1967 | // Append new function. |
| | 1968 | // TODO Look at the free list before appending at the end. |
| 1929 | src_fn.prev = last; | 1969 | src_fn.prev = last; |
| 1930 | last.next = src_fn; | 1970 | last.next = src_fn; |
| 1931 | self.dbg_line_fn_last = src_fn; | 1971 | self.dbg_line_fn_last = src_fn; |
| 1932 | | 1972 | |
| 1933 | src_fn.off = last.off + (last.len * alloc_num / alloc_den); | 1973 | src_fn.off = last.off + (last.len * alloc_num / alloc_den); |
| 1934 | src_fn.len = @intCast(u32, dbg_line_buffer.items.len); | | |
| 1935 | } else { | | |
| 1936 | // Update existing function. | | |
| 1937 | @panic("TODO updateDecl for .debug_line: add new SrcFn: update"); | | |
| 1938 | } | 1974 | } |
| 1939 | } else { | 1975 | } else { |
| 1940 | // This is the first function of the Line Number Program. | 1976 | // This is the first function of the Line Number Program. |
| ... | @@ -1942,7 +1978,6 @@ pub const File = struct { | ... | @@ -1942,7 +1978,6 @@ pub const File = struct { |
| 1942 | self.dbg_line_fn_last = src_fn; | 1978 | self.dbg_line_fn_last = src_fn; |
| 1943 | | 1979 | |
| 1944 | src_fn.off = self.dbgLineNeededHeaderBytes() * alloc_num / alloc_den; | 1980 | src_fn.off = self.dbgLineNeededHeaderBytes() * alloc_num / alloc_den; |
| 1945 | src_fn.len = @intCast(u32, dbg_line_buffer.items.len); | | |
| 1946 | } | 1981 | } |
| 1947 | | 1982 | |
| 1948 | const needed_size = src_fn.off + src_fn.len; | 1983 | const needed_size = src_fn.off + src_fn.len; |
| ... | @@ -1982,10 +2017,7 @@ pub const File = struct { | ... | @@ -1982,10 +2017,7 @@ pub const File = struct { |
| 1982 | const tracy = trace(@src()); | 2017 | const tracy = trace(@src()); |
| 1983 | defer tracy.end(); | 2018 | defer tracy.end(); |
| 1984 | | 2019 | |
| 1985 | // In addition to ensuring capacity for global_symbols, we also ensure capacity for freeing all of | | |
| 1986 | // them, so that deleting exports is guaranteed to succeed. | | |
| 1987 | try self.global_symbols.ensureCapacity(self.allocator, self.global_symbols.items.len + exports.len); | 2020 | try self.global_symbols.ensureCapacity(self.allocator, self.global_symbols.items.len + exports.len); |
| 1988 | try self.global_symbol_free_list.ensureCapacity(self.allocator, self.global_symbols.items.len); | | |
| 1989 | const typed_value = decl.typed_value.most_recent.typed_value; | 2021 | const typed_value = decl.typed_value.most_recent.typed_value; |
| 1990 | if (decl.link.local_sym_index == 0) return; | 2022 | if (decl.link.local_sym_index == 0) return; |
| 1991 | const decl_sym = self.local_symbols.items[decl.link.local_sym_index]; | 2023 | const decl_sym = self.local_symbols.items[decl.link.local_sym_index]; |
| ... | @@ -2052,7 +2084,7 @@ pub const File = struct { | ... | @@ -2052,7 +2084,7 @@ pub const File = struct { |
| 2052 | | 2084 | |
| 2053 | pub fn deleteExport(self: *Elf, exp: Export) void { | 2085 | pub fn deleteExport(self: *Elf, exp: Export) void { |
| 2054 | const sym_index = exp.sym_index orelse return; | 2086 | const sym_index = exp.sym_index orelse return; |
| 2055 | self.global_symbol_free_list.appendAssumeCapacity(sym_index); | 2087 | self.global_symbol_free_list.append(self.allocator, sym_index) catch {}; |
| 2056 | self.global_symbols.items[sym_index].st_info = 0; | 2088 | self.global_symbols.items[sym_index].st_info = 0; |
| 2057 | } | 2089 | } |
| 2058 | | 2090 | |
| ... | @@ -2284,7 +2316,7 @@ pub const File = struct { | ... | @@ -2284,7 +2316,7 @@ pub const File = struct { |
| 2284 | } | 2316 | } |
| 2285 | | 2317 | |
| 2286 | /// Writes to the file a buffer, prefixed and suffixed by the specified number of | 2318 | /// Writes to the file a buffer, prefixed and suffixed by the specified number of |
| 2287 | /// bytes of NOPs. Asserts each padding size is at least two bytes and total padding bytes | 2319 | /// bytes of NOPs. Asserts each padding size is at least `min_nop_size` and total padding bytes |
| 2288 | /// are less than 126,976 bytes (if this limit is ever reached, this function can be | 2320 | /// are less than 126,976 bytes (if this limit is ever reached, this function can be |
| 2289 | /// improved to make more than one pwritev call, or the limit can be raised by a fixed | 2321 | /// improved to make more than one pwritev call, or the limit can be raised by a fixed |
| 2290 | /// amount by increasing the length of `vecs`). | 2322 | /// amount by increasing the length of `vecs`). |
| ... | @@ -2361,6 +2393,8 @@ pub const File = struct { | ... | @@ -2361,6 +2393,8 @@ pub const File = struct { |
| 2361 | try self.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size); | 2393 | try self.file.?.pwritevAll(vecs[0..vec_index], offset - prev_padding_size); |
| 2362 | } | 2394 | } |
| 2363 | | 2395 | |
| | 2396 | const min_nop_size = 2; |
| | 2397 | |
| 2364 | }; | 2398 | }; |
| 2365 | }; | 2399 | }; |
| 2366 | | 2400 | |