| author | |
| committer | |
| log | 8ab4a003c8f22a3fd8f84bdb2fc27d8c20d3bf2f |
| tree | 28db2ba140f4017ef0f314d47a52c8dd517301a9 |
| parent | 474ade88b58b6fd7239049ec445129eabafa3cbd |
Two problems solved:
* The Decl name may be allocated with gpa or it may be a reference to
the ZIR string table.
* The main update() function was freeing the ZIR when we still had
Decl objects referencing it.2 files changed, 18 insertions(+), 2 deletions(-)
src/Compilation.zig+6-1| ... | @@ -1646,10 +1646,15 @@ pub fn update(self: *Compilation) !void { | ... | @@ -1646,10 +1646,15 @@ pub fn update(self: *Compilation) !void { |
| 1646 | 1646 | ||
| 1647 | // If there are any errors, we anticipate the source files being loaded | 1647 | // If there are any errors, we anticipate the source files being loaded |
| 1648 | // to report error messages. Otherwise we unload all source files to save memory. | 1648 | // to report error messages. Otherwise we unload all source files to save memory. |
| 1649 | // The ZIR needs to stay loaded in memory because (1) Decl objects contain references | ||
| 1650 | // to it, and (2) generic instantiations, comptime calls, inline calls will need | ||
| 1651 | // to reference the ZIR. | ||
| 1649 | if (self.totalErrorCount() == 0 and !self.keep_source_files_loaded) { | 1652 | if (self.totalErrorCount() == 0 and !self.keep_source_files_loaded) { |
| 1650 | if (self.bin_file.options.module) |module| { | 1653 | if (self.bin_file.options.module) |module| { |
| 1651 | for (module.import_table.items()) |entry| { | 1654 | for (module.import_table.items()) |entry| { |
| 1652 | entry.value.unload(self.gpa); | 1655 | const file = entry.value; |
| 1656 | file.unloadTree(self.gpa); | ||
| 1657 | file.unloadSource(self.gpa); | ||
| 1653 | } | 1658 | } |
| 1654 | } | 1659 | } |
| 1655 | } | 1660 | } |
src/Module.zig+12-1| ... | @@ -263,9 +263,20 @@ pub const Decl = struct { | ... | @@ -263,9 +263,20 @@ pub const Decl = struct { |
| 263 | false, | 263 | false, |
| 264 | ); | 264 | ); |
| 265 | 265 | ||
| 266 | pub fn clearName(decl: *Decl, gpa: *Allocator) void { | ||
| 267 | // name could be allocated in the ZIR or it could be owned by gpa. | ||
| 268 | const file = decl.namespace.file_scope; | ||
| 269 | const string_table_start = @ptrToInt(file.zir.string_bytes.ptr); | ||
| 270 | const string_table_end = string_table_start + file.zir.string_bytes.len; | ||
| 271 | if (@ptrToInt(decl.name) < string_table_start or @ptrToInt(decl.name) >= string_table_end) { | ||
| 272 | gpa.free(mem.spanZ(decl.name)); | ||
| 273 | } | ||
| 274 | decl.name = undefined; | ||
| 275 | } | ||
| 276 | |||
| 266 | pub fn destroy(decl: *Decl, module: *Module) void { | 277 | pub fn destroy(decl: *Decl, module: *Module) void { |
| 267 | const gpa = module.gpa; | 278 | const gpa = module.gpa; |
| 268 | gpa.free(mem.spanZ(decl.name)); | 279 | decl.clearName(gpa); |
| 269 | if (decl.has_tv) { | 280 | if (decl.has_tv) { |
| 270 | if (decl.val.castTag(.function)) |payload| { | 281 | if (decl.val.castTag(.function)) |payload| { |
| 271 | const func = payload.data; | 282 | const func = payload.data; |