aboutsummaryrefslogtreecommitdiff
path: root/src/InternPool.zig
diff options
context:
space:
mode:
authorJacob Young <jacobly0@users.noreply.github.com>2023-06-12 01:44:12 -0400
committerAndrew Kelley <andrew@ziglang.org>2023-06-11 23:45:09 -0700
commitd37ebfcf231c68a0430840c4fbe649dd0076ae1e (patch)
treed9f67acedf38600487a2d2ed08e1e202dfad5667 /src/InternPool.zig
parent54460e39ace2140e6bfcb0bf4ae1709d128f9e8d (diff)
downloadzig-d37ebfcf231c68a0430840c4fbe649dd0076ae1e.tar.gz
zig-d37ebfcf231c68a0430840c4fbe649dd0076ae1e.zip
InternPool: avoid as many slices pointing to `string_bytes` as possible
These are frequently invalidated whenever a string is interned, so avoid creating pointers to `string_bytes` wherever possible. This is an attempt to fix random CI failures.
Diffstat (limited to 'src/InternPool.zig')
-rw-r--r--src/InternPool.zig46
1 files changed, 38 insertions, 8 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig
index 0f0b40ba4d..d5cf2d3fbf 100644
--- a/src/InternPool.zig
+++ b/src/InternPool.zig
@@ -156,6 +156,35 @@ pub const NullTerminatedString = enum(u32) {
_ = ctx;
return @enumToInt(a) < @enumToInt(b);
}
+
+ pub fn toUnsigned(self: NullTerminatedString, ip: *const InternPool) ?u32 {
+ const s = ip.stringToSlice(self);
+ if (s.len > 1 and s[0] == '0') return null;
+ if (std.mem.indexOfScalar(u8, s, '_')) |_| return null;
+ return std.fmt.parseUnsigned(u32, s, 10) catch null;
+ }
+
+ const FormatData = struct {
+ string: NullTerminatedString,
+ ip: *const InternPool,
+ };
+ fn format(
+ data: FormatData,
+ comptime specifier: []const u8,
+ _: std.fmt.FormatOptions,
+ writer: anytype,
+ ) @TypeOf(writer).Error!void {
+ const s = data.ip.stringToSlice(data.string);
+ if (comptime std.mem.eql(u8, specifier, "")) {
+ try writer.writeAll(s);
+ } else if (comptime std.mem.eql(u8, specifier, "i")) {
+ try writer.print("{}", .{std.zig.fmtId(s)});
+ } else @compileError("invalid format string '" ++ specifier ++ "' for '" ++ @typeName(NullTerminatedString) ++ "'");
+ }
+
+ pub fn fmt(self: NullTerminatedString, ip: *const InternPool) std.fmt.Formatter(format) {
+ return .{ .data = .{ .string = self, .ip = ip } };
+ }
};
/// An index into `string_bytes` which might be `none`.
@@ -5252,10 +5281,9 @@ pub fn getOrPutString(
gpa: Allocator,
s: []const u8,
) Allocator.Error!NullTerminatedString {
- const string_bytes = &ip.string_bytes;
- try string_bytes.ensureUnusedCapacity(gpa, s.len + 1);
- string_bytes.appendSliceAssumeCapacity(s);
- string_bytes.appendAssumeCapacity(0);
+ try ip.string_bytes.ensureUnusedCapacity(gpa, s.len + 1);
+ ip.string_bytes.appendSliceAssumeCapacity(s);
+ ip.string_bytes.appendAssumeCapacity(0);
return ip.getOrPutTrailingString(gpa, s.len + 1);
}
@@ -5265,10 +5293,12 @@ pub fn getOrPutStringFmt(
comptime format: []const u8,
args: anytype,
) Allocator.Error!NullTerminatedString {
- const start = ip.string_bytes.items.len;
- try ip.string_bytes.writer(gpa).print(format, args);
- try ip.string_bytes.append(gpa, 0);
- return ip.getOrPutTrailingString(gpa, ip.string_bytes.items.len - start);
+ // ensure that references to string_bytes in args do not get invalidated
+ const len = std.fmt.count(format, args) + 1;
+ try ip.string_bytes.ensureUnusedCapacity(gpa, len);
+ ip.string_bytes.writer(undefined).print(format, args) catch unreachable;
+ ip.string_bytes.appendAssumeCapacity(0);
+ return ip.getOrPutTrailingString(gpa, len);
}
pub fn getOrPutStringOpt(