authorgravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-10 21:39:29+02:00
committergravatar for kubkon@jakubkonka.comJakub Konka <kubkon@jakubkonka.com> 2020-10-13 08:38:17+02:00
log0b77152faa663c12b5ab3aa20db77c2ae1427ece
treec10a38482592ce42fe6bde30ba41c9f1cd0f91fd
parentea45ee54843b10a433bb223caa9706d8253e3222

Add local and offset free lists


1 files changed, 37 insertions(+), 0 deletions(-)

src/link/MachO.zig+37
...@@ -116,7 +116,9 @@ global_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},...@@ -116,7 +116,9 @@ global_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},
116/// Table of all undefined symbols116/// Table of all undefined symbols
117undef_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},117undef_symbols: std.ArrayListUnmanaged(macho.nlist_64) = .{},
118118
119local_symbol_free_list: std.ArrayListUnmanaged(u32) = .{},
119global_symbol_free_list: std.ArrayListUnmanaged(u32) = .{},120global_symbol_free_list: std.ArrayListUnmanaged(u32) = .{},
121offset_table_free_list: std.ArrayListUnmanaged(u32) = .{},
120122
121dyld_stub_binder_index: ?u16 = null,123dyld_stub_binder_index: ?u16 = null,
122124
...@@ -153,6 +155,12 @@ const LIB_SYSTEM_NAME: [*:0]const u8 = "System";...@@ -153,6 +155,12 @@ const LIB_SYSTEM_NAME: [*:0]const u8 = "System";
153/// TODO we should search for libSystem and fail if it doesn't exist, instead of hardcoding it155/// TODO we should search for libSystem and fail if it doesn't exist, instead of hardcoding it
154const LIB_SYSTEM_PATH: [*:0]const u8 = DEFAULT_LIB_SEARCH_PATH ++ "/libSystem.B.dylib";156const LIB_SYSTEM_PATH: [*:0]const u8 = DEFAULT_LIB_SEARCH_PATH ++ "/libSystem.B.dylib";
155157
158/// In order for a slice of bytes to be considered eligible to keep metadata pointing at
159/// it as a possible place to put new symbols, it must have enough room for this many bytes
160/// (plus extra for reserved capacity).
161const minimum_text_block_size = 64;
162const min_text_capacity = minimum_text_block_size * alloc_num / alloc_den;
163
156pub const TextBlock = struct {164pub const TextBlock = struct {
157 /// Each decl always gets a local symbol with the fully qualified name.165 /// Each decl always gets a local symbol with the fully qualified name.
158 /// The vaddr and size are found here directly.166 /// The vaddr and size are found here directly.
...@@ -179,6 +187,33 @@ pub const TextBlock = struct {...@@ -179,6 +187,33 @@ pub const TextBlock = struct {
179 .prev = null,187 .prev = null,
180 .next = null,188 .next = null,
181 };189 };
190
191 /// Returns how much room there is to grow in virtual address space.
192 /// File offset relocation happens transparently, so it is not included in
193 /// this calculation.
194 fn capacity(self: TextBlock, macho_file: MachO) u64 {
195 const self_sym = macho_file.local_symbols.items[self.local_sym_index];
196 if (self.next) |next| {
197 const next_sym = macho_file.local_symbols.items[next.local_sym_index];
198 return next_sym.n_value - self_sym.n_value;
199 } else {
200 // We are the last block.
201 // The capacity is limited only by virtual address space.
202 return std.math.maxInt(u64) - self_sym.n_value;
203 }
204 }
205
206 fn freeListEligible(self: TextBlock, macho_file: MachO) bool {
207 // No need to keep a free list node for the last block.
208 const next = self.next orelse return false;
209 const self_sym = macho_file.local_symbols.items[self.local_sym_index];
210 const next_sym = macho_file.local_symbols.items[next.local_sym_index];
211 const cap = next_sym.n_value - self_sym.n_value;
212 const ideal_cap = self.size * alloc_num / alloc_den;
213 if (cap <= ideal_cap) return false;
214 const surplus = cap - ideal_cap;
215 return surplus >= min_text_capacity;
216 }
182};217};
183218
184pub const Export = struct {219pub const Export = struct {
...@@ -721,11 +756,13 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 {...@@ -721,11 +756,13 @@ fn darwinArchString(arch: std.Target.Cpu.Arch) []const u8 {
721756
722pub fn deinit(self: *MachO) void {757pub fn deinit(self: *MachO) void {
723 self.offset_table.deinit(self.base.allocator);758 self.offset_table.deinit(self.base.allocator);
759 self.offset_table_free_list.deinit(self.base.allocator);
724 self.string_table.deinit(self.base.allocator);760 self.string_table.deinit(self.base.allocator);
725 self.undef_symbols.deinit(self.base.allocator);761 self.undef_symbols.deinit(self.base.allocator);
726 self.global_symbols.deinit(self.base.allocator);762 self.global_symbols.deinit(self.base.allocator);
727 self.global_symbol_free_list.deinit(self.base.allocator);763 self.global_symbol_free_list.deinit(self.base.allocator);
728 self.local_symbols.deinit(self.base.allocator);764 self.local_symbols.deinit(self.base.allocator);
765 self.local_symbol_free_list.deinit(self.base.allocator);
729 self.sections.deinit(self.base.allocator);766 self.sections.deinit(self.base.allocator);
730 self.load_commands.deinit(self.base.allocator);767 self.load_commands.deinit(self.base.allocator);
731}768}