aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2021-04-29 20:34:33 -0700
committerAndrew Kelley <andrew@ziglang.org>2021-04-29 20:34:33 -0700
commit8ab4a003c8f22a3fd8f84bdb2fc27d8c20d3bf2f (patch)
tree28db2ba140f4017ef0f314d47a52c8dd517301a9
parent474ade88b58b6fd7239049ec445129eabafa3cbd (diff)
downloadzig-8ab4a003c8f22a3fd8f84bdb2fc27d8c20d3bf2f.tar.gz
zig-8ab4a003c8f22a3fd8f84bdb2fc27d8c20d3bf2f.zip
stage2: properly free Decl name
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.
-rw-r--r--src/Compilation.zig7
-rw-r--r--src/Module.zig13
2 files changed, 18 insertions, 2 deletions
diff --git a/src/Compilation.zig b/src/Compilation.zig
index e4de593fd0..82ede40a9d 100644
--- a/src/Compilation.zig
+++ b/src/Compilation.zig
@@ -1646,10 +1646,15 @@ pub fn update(self: *Compilation) !void {
// If there are any errors, we anticipate the source files being loaded
// to report error messages. Otherwise we unload all source files to save memory.
+ // The ZIR needs to stay loaded in memory because (1) Decl objects contain references
+ // to it, and (2) generic instantiations, comptime calls, inline calls will need
+ // to reference the ZIR.
if (self.totalErrorCount() == 0 and !self.keep_source_files_loaded) {
if (self.bin_file.options.module) |module| {
for (module.import_table.items()) |entry| {
- entry.value.unload(self.gpa);
+ const file = entry.value;
+ file.unloadTree(self.gpa);
+ file.unloadSource(self.gpa);
}
}
}
diff --git a/src/Module.zig b/src/Module.zig
index a212fb44e4..76a740bdc0 100644
--- a/src/Module.zig
+++ b/src/Module.zig
@@ -263,9 +263,20 @@ pub const Decl = struct {
false,
);
+ pub fn clearName(decl: *Decl, gpa: *Allocator) void {
+ // name could be allocated in the ZIR or it could be owned by gpa.
+ const file = decl.namespace.file_scope;
+ const string_table_start = @ptrToInt(file.zir.string_bytes.ptr);
+ const string_table_end = string_table_start + file.zir.string_bytes.len;
+ if (@ptrToInt(decl.name) < string_table_start or @ptrToInt(decl.name) >= string_table_end) {
+ gpa.free(mem.spanZ(decl.name));
+ }
+ decl.name = undefined;
+ }
+
pub fn destroy(decl: *Decl, module: *Module) void {
const gpa = module.gpa;
- gpa.free(mem.spanZ(decl.name));
+ decl.clearName(gpa);
if (decl.has_tv) {
if (decl.val.castTag(.function)) |payload| {
const func = payload.data;