authorgravatar for mlugg@mlugg.co.ukMatthew Lugg <mlugg@mlugg.co.uk> 2023-06-02 13:47:38+01:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:59-07:00
log0fd52cdc5eb4b17e8066a06d8af761f934cf8808
tree08adff6a341d9d3eaaeefb21cec0234884e1df1d
parent0f80652efb170aa4158e378dbb493da717c9bd17

InternPool: avoid aggregate null bytes storage

This is a workaround for InternPool currently not handling non-null-terminated strings. It avoids using the `bytes` storage for aggregates if there are any null bytes. In the future this should be changed so that the `bytes` storage can be used regardless of whether there are any null bytes. This is important for use cases such as `@embedFile`. However, this fixes a bug for now, and after this commit, stage2 self-hosts again. mlugg: stage5 passes all enabled behavior tests on my system. Commit message edited by Andrew Kelley <andrew@ziglang.org>

2 files changed, 22 insertions(+), 2 deletions(-)

src/InternPool.zig+21-2
...@@ -3951,6 +3951,15 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3951,6 +3951,15 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3951 else => unreachable,3951 else => unreachable,
3952 },3952 },
3953 }3953 }
3954 // We can't dedup '0' bytes in the pool or it could add garbage to string_bytes. So
3955 // if there are any 0 bytes, we have to skip the bytes case. Note that it's okay for
3956 // our sentinel to be 0 since getOrPutTrailingString would add a 0 sentinel anyway.
3957 for (ip.string_bytes.items[string_bytes_index..]) |x| {
3958 if (x == 0) {
3959 ip.string_bytes.shrinkRetainingCapacity(string_bytes_index);
3960 break :bytes;
3961 }
3962 }
3954 if (sentinel != .none) ip.string_bytes.appendAssumeCapacity(3963 if (sentinel != .none) ip.string_bytes.appendAssumeCapacity(
3955 @intCast(u8, ip.indexToKey(sentinel).int.storage.u64),3964 @intCast(u8, ip.indexToKey(sentinel).int.storage.u64),
3956 );3965 );
...@@ -3975,7 +3984,17 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {...@@ -3975,7 +3984,17 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
3975 .ty = aggregate.ty,3984 .ty = aggregate.ty,
3976 }),3985 }),
3977 });3986 });
3978 ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, aggregate.storage.elems));3987 switch (aggregate.storage) {
3988 .bytes => |bytes| for (bytes) |b| {
3989 const elem = try ip.get(gpa, .{ .int = .{
3990 .ty = .u8_type,
3991 .storage = .{ .u64 = b },
3992 } });
3993 ip.extra.appendAssumeCapacity(@enumToInt(elem));
3994 },
3995 .elems => |elems| ip.extra.appendSliceAssumeCapacity(@ptrCast([]const u32, elems)),
3996 .repeated_elem => |elem| ip.extra.appendNTimesAssumeCapacity(@enumToInt(elem), len),
3997 }
3979 if (sentinel != .none) ip.extra.appendAssumeCapacity(@enumToInt(sentinel));3998 if (sentinel != .none) ip.extra.appendAssumeCapacity(@enumToInt(sentinel));
3980 },3999 },
39814000
...@@ -5203,7 +5222,7 @@ pub fn destroyFunc(ip: *InternPool, gpa: Allocator, index: Module.Fn.Index) void...@@ -5203,7 +5222,7 @@ pub fn destroyFunc(ip: *InternPool, gpa: Allocator, index: Module.Fn.Index) void
5203 ip.funcPtr(index).* = undefined;5222 ip.funcPtr(index).* = undefined;
5204 ip.funcs_free_list.append(gpa, index) catch {5223 ip.funcs_free_list.append(gpa, index) catch {
5205 // In order to keep `destroyFunc` a non-fallible function, we ignore memory5224 // In order to keep `destroyFunc` a non-fallible function, we ignore memory
5206 // allocation failures here, instead leaking the Union until garbage collection.5225 // allocation failures here, instead leaking the Fn until garbage collection.
5207 };5226 };
5208}5227}
52095228
src/Module.zig+1
...@@ -337,6 +337,7 @@ pub const CaptureScope = struct {...@@ -337,6 +337,7 @@ pub const CaptureScope = struct {
337 if (!self.failed()) {337 if (!self.failed()) {
338 self.captures.deinit(gpa);338 self.captures.deinit(gpa);
339 }339 }
340 gpa.destroy(self);
340 }341 }
341};342};
342343