aboutsummaryrefslogtreecommitdiff
path: root/src/InternPool.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-05-14 20:37:22 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-06-10 20:47:53 -0700
commit6a9a918fbe4adc23dd7d7573c6f1e499f4be074e (patch)
treef94c3d80a82b04a905d725689740af1d8c90dc97 /src/InternPool.zig
parentd18881de1be811c1dff52590223b92c916c4b773 (diff)
downloadzig-6a9a918fbe4adc23dd7d7573c6f1e499f4be074e.tar.gz
zig-6a9a918fbe4adc23dd7d7573c6f1e499f4be074e.zip
stage2: encode one-possible-value tuple specially
Anonymous structs and anonymous tuples can be stored via a only_possible_value tag because their type encodings, by definition, will have every value specified, which can be used to populate the fields slice in `Key.Aggregate`. Also fix `isTupleOrAnonStruct`.
Diffstat (limited to 'src/InternPool.zig')
-rw-r--r--src/InternPool.zig44
1 files changed, 33 insertions, 11 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig
index 74cc452176..2435e0ad31 100644
--- a/src/InternPool.zig
+++ b/src/InternPool.zig
@@ -1166,10 +1166,10 @@ pub const Tag = enum(u8) {
/// Module.Struct object allocated for it.
/// data is Module.Namespace.Index.
type_struct_ns,
- /// An AnonStructType which stores types, names, and values for each field.
+ /// An AnonStructType which stores types, names, and values for fields.
/// data is extra index of `TypeStructAnon`.
type_struct_anon,
- /// An AnonStructType which has only types and values for each field.
+ /// An AnonStructType which has only types and values for fields.
/// data is extra index of `TypeStructAnon`.
type_tuple_anon,
/// A tagged union type.
@@ -1272,7 +1272,8 @@ pub const Tag = enum(u8) {
/// only one possible value. Not all only-possible-values are encoded this way;
/// for example structs which have all comptime fields are not encoded this way.
/// The set of values that are encoded this way is:
- /// * A struct which has 0 fields.
+ /// * An array or vector which has length 0.
+ /// * A struct which has all fields comptime-known.
/// data is Index of the type, which is known to be zero bits at runtime.
only_possible_value,
/// data is extra index to Key.Union.
@@ -1863,10 +1864,21 @@ pub fn indexToKey(ip: InternPool, index: Index) Key {
.only_possible_value => {
const ty = @intToEnum(Index, data);
return switch (ip.indexToKey(ty)) {
+ // TODO: migrate structs to properly use the InternPool rather
+ // than using the SegmentedList trick, then the struct type will
+ // have a slice of comptime values that can be used here for when
+ // the struct has one possible value due to all fields comptime (same
+ // as the tuple case below).
.struct_type => .{ .aggregate = .{
.ty = ty,
.fields = &.{},
} },
+ // There is only one possible value precisely due to the
+ // fact that this values slice is fully populated!
+ .anon_struct_type => |anon_struct_type| .{ .aggregate = .{
+ .ty = ty,
+ .fields = anon_struct_type.values,
+ } },
else => unreachable,
};
},
@@ -2392,12 +2404,6 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
.aggregate => |aggregate| {
assert(aggregate.ty != .none);
for (aggregate.fields) |elem| assert(elem != .none);
- if (aggregate.fields.len != ip.aggregateTypeLen(aggregate.ty)) {
- std.debug.print("aggregate fields len = {d}, type len = {d}\n", .{
- aggregate.fields.len,
- ip.aggregateTypeLen(aggregate.ty),
- });
- }
assert(aggregate.fields.len == ip.aggregateTypeLen(aggregate.ty));
if (aggregate.fields.len == 0) {
@@ -2408,6 +2414,22 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
return @intToEnum(Index, ip.items.len - 1);
}
+ switch (ip.indexToKey(aggregate.ty)) {
+ .anon_struct_type => |anon_struct_type| {
+ if (std.mem.eql(Index, anon_struct_type.values, aggregate.fields)) {
+ // This encoding works thanks to the fact that, as we just verified,
+ // the type itself contains a slice of values that can be provided
+ // in the aggregate fields.
+ ip.items.appendAssumeCapacity(.{
+ .tag = .only_possible_value,
+ .data = @enumToInt(aggregate.ty),
+ });
+ return @intToEnum(Index, ip.items.len - 1);
+ }
+ },
+ else => {},
+ }
+
try ip.extra.ensureUnusedCapacity(
gpa,
@typeInfo(Aggregate).Struct.fields.len + aggregate.fields.len,
@@ -3121,8 +3143,8 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
}
};
counts.sort(SortContext{ .map = &counts });
- const len = @min(50, counts.count());
- std.debug.print(" top 50 tags:\n", .{});
+ const len = @min(25, counts.count());
+ std.debug.print(" top 25 tags:\n", .{});
for (counts.keys()[0..len], counts.values()[0..len]) |tag, stats| {
std.debug.print(" {s}: {d} occurrences, {d} total bytes\n", .{
@tagName(tag), stats.count, stats.bytes,