authorgravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-04-09 09:24:52+02:00
committergravatar for luuk@degram.devLuuk de Gram <luuk@degram.dev> 2021-04-09 09:24:52+02:00
logeaaf75c1579e0202efb1b8b71155ea147d52c56a
treef94dff606589b1d8685543048ace9866e2bca8aa
parentff5774d93d9d952a74fab3666d4480f534c770db
signaturelock-open Commit is signed but in an unrecognized format.

Fix memory cleanup and update unplugging to avoid infinite loop


1 files changed, 23 insertions(+), 28 deletions(-)

src/link/Wasm.zig+23-28
...@@ -47,9 +47,6 @@ offset_table_free_list: std.ArrayListUnmanaged(u32) = .{},...@@ -47,9 +47,6 @@ offset_table_free_list: std.ArrayListUnmanaged(u32) = .{},
47/// This is ment for bookkeeping so we can safely cleanup all codegen memory47/// This is ment for bookkeeping so we can safely cleanup all codegen memory
48/// when calling `deinit`48/// when calling `deinit`
49symbols: std.ArrayListUnmanaged(*Module.Decl) = .{},49symbols: std.ArrayListUnmanaged(*Module.Decl) = .{},
50/// Contains indexes into `symbols` that are no longer used and can be populated instead,
51/// removing the need to search for a symbol and remove it when it's dereferenced.
52symbols_free_list: std.ArrayListUnmanaged(u32) = .{},
5350
54pub const FnData = struct {51pub const FnData = struct {
55 /// Generated code for the type of the function52 /// Generated code for the type of the function
...@@ -95,6 +92,19 @@ pub const DeclBlock = struct {...@@ -95,6 +92,19 @@ pub const DeclBlock = struct {
95 .next = null,92 .next = null,
96 .data = undefined,93 .data = undefined,
97 };94 };
95
96 /// Unplugs the `DeclBlock` from the chain
97 fn unplug(self: *DeclBlock) void {
98 if (self.prev) |prev| {
99 prev.next = self.next;
100 }
101
102 if (self.next) |next| {
103 next.prev = self.prev;
104 }
105 self.next = null;
106 self.prev = null;
107 }
98};108};
99109
100pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Wasm {110pub fn openPath(allocator: *Allocator, sub_path: []const u8, options: link.Options) !*Wasm {
...@@ -131,10 +141,6 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Wasm {...@@ -131,10 +141,6 @@ pub fn createEmpty(gpa: *Allocator, options: link.Options) !*Wasm {
131}141}
132142
133pub fn deinit(self: *Wasm) void {143pub fn deinit(self: *Wasm) void {
134 while (self.symbols_free_list.popOrNull()) |idx| {
135 //dead decl's so remove them from symbol list before trying to clean them up
136 _ = self.symbols.swapRemove(idx);
137 }
138 for (self.symbols.items) |decl| {144 for (self.symbols.items) |decl| {
139 decl.fn_link.wasm.functype.deinit(self.base.allocator);145 decl.fn_link.wasm.functype.deinit(self.base.allocator);
140 decl.fn_link.wasm.code.deinit(self.base.allocator);146 decl.fn_link.wasm.code.deinit(self.base.allocator);
...@@ -146,7 +152,6 @@ pub fn deinit(self: *Wasm) void {...@@ -146,7 +152,6 @@ pub fn deinit(self: *Wasm) void {
146 self.offset_table.deinit(self.base.allocator);152 self.offset_table.deinit(self.base.allocator);
147 self.offset_table_free_list.deinit(self.base.allocator);153 self.offset_table_free_list.deinit(self.base.allocator);
148 self.symbols.deinit(self.base.allocator);154 self.symbols.deinit(self.base.allocator);
149 self.symbols_free_list.deinit(self.base.allocator);
150}155}
151156
152pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {157pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
...@@ -158,12 +163,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {...@@ -158,12 +163,8 @@ pub fn allocateDeclIndexes(self: *Wasm, decl: *Module.Decl) !void {
158 const block = &decl.link.wasm;163 const block = &decl.link.wasm;
159 block.init = true;164 block.init = true;
160165
161 if (self.symbols_free_list.popOrNull()) |index| {166 block.symbol_index = @intCast(u32, self.symbols.items.len);
162 block.symbol_index = index;167 self.symbols.appendAssumeCapacity(decl);
163 } else {
164 block.symbol_index = @intCast(u32, self.symbols.items.len);
165 _ = self.symbols.addOneAssumeCapacity();
166 }
167168
168 if (self.offset_table_free_list.popOrNull()) |index| {169 if (self.offset_table_free_list.popOrNull()) |index| {
169 block.offset_index = index;170 block.offset_index = index;
...@@ -241,12 +242,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {...@@ -241,12 +242,7 @@ pub fn updateDecl(self: *Wasm, module: *Module, decl: *Module.Decl) !void {
241242
242 // If we're updating an existing decl, unplug it first243 // If we're updating an existing decl, unplug it first
243 // to avoid infinite loops due to earlier links244 // to avoid infinite loops due to earlier links
244 if (block.prev) |prev| {245 block.unplug();
245 prev.next = block.next;
246 }
247 if (block.next) |next| {
248 next.prev = block.prev;
249 }
250246
251 if (self.last_block) |last| {247 if (self.last_block) |last| {
252 if (last != block) {248 if (last != block) {
...@@ -278,16 +274,15 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {...@@ -278,16 +274,15 @@ pub fn freeDecl(self: *Wasm, decl: *Module.Decl) void {
278 self.last_block = block.prev;274 self.last_block = block.prev;
279 }275 }
280276
281 if (block.prev) |prev| {277 block.unplug();
282 prev.next = block.next;
283 }
284
285 if (block.next) |next| {
286 next.prev = block.prev;
287 }
288278
289 self.offset_table_free_list.append(self.base.allocator, decl.link.wasm.offset_index) catch {};279 self.offset_table_free_list.append(self.base.allocator, decl.link.wasm.offset_index) catch {};
290 self.symbols_free_list.append(self.base.allocator, decl.link.wasm.symbol_index) catch {};280 _ = self.symbols.swapRemove(block.symbol_index);
281
282 // update symbol_index as we swap removed the last symbol into the removed's position
283 if (block.symbol_index < self.symbols.items.len)
284 self.symbols.items[block.symbol_index].link.wasm.symbol_index = block.symbol_index;
285
291 block.init = false;286 block.init = false;
292287
293 decl.fn_link.wasm.functype.deinit(self.base.allocator);288 decl.fn_link.wasm.functype.deinit(self.base.allocator);