aboutsummaryrefslogtreecommitdiff
path: root/src/InternPool.zig
diff options
context:
space:
mode:
authorAndrew Kelley <andrew@ziglang.org>2023-05-29 22:33:40 -0700
committerAndrew Kelley <andrew@ziglang.org>2023-06-10 20:47:57 -0700
commit66f83f27a2904180bae7797a7c87c6eddc7eebff (patch)
treebd3ef82451b2f04d720d84a9ed44c32d54c78455 /src/InternPool.zig
parent27f1ad8afde86c8f734deeb05f5c8cad910275e4 (diff)
downloadzig-66f83f27a2904180bae7797a7c87c6eddc7eebff.tar.gz
zig-66f83f27a2904180bae7797a7c87c6eddc7eebff.zip
InternPool: avoid indexToKey recursion for type_enum_auto
Recursion makes this hot function more difficult to profile and optimize. This commit adds the integer tag type to the type_enum_auto encoding even though the integer tag type can be inferred based on the number of fields of the enum. This avoids a call to getAssumeExists of the integer tag type inside indexToKey.
Diffstat (limited to 'src/InternPool.zig')
-rw-r--r--src/InternPool.zig33
1 files changed, 15 insertions, 18 deletions
diff --git a/src/InternPool.zig b/src/InternPool.zig
index 1cb2704054..3fafca0a74 100644
--- a/src/InternPool.zig
+++ b/src/InternPool.zig
@@ -2169,6 +2169,9 @@ pub const EnumAuto = struct {
decl: Module.Decl.Index,
/// This may be `none` if there are no declarations.
namespace: Module.Namespace.OptionalIndex,
+ /// An integer type which is used for the numerical value of the enum, which
+ /// was inferred by Zig based on the number of tags.
+ int_tag_type: Index,
fields_len: u32,
/// Maps field names to declaration index.
names_map: MapIndex,
@@ -2553,7 +2556,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
return .{ .enum_type = .{
.decl = enum_auto.data.decl,
.namespace = enum_auto.data.namespace,
- .tag_ty = ip.getEnumIntTagType(enum_auto.data.fields_len),
+ .tag_ty = enum_auto.data.int_tag_type,
.names = names,
.values = &.{},
.tag_mode = .auto,
@@ -2928,14 +2931,6 @@ fn indexToKeyFuncType(ip: InternPool, data: u32) Key.FuncType {
};
}
-/// Asserts the integer tag type is already present in the InternPool.
-fn getEnumIntTagType(ip: InternPool, fields_len: u32) Index {
- return ip.getAssumeExists(.{ .int_type = .{
- .bits = if (fields_len == 0) 0 else std.math.log2_int_ceil(u32, fields_len),
- .signedness = .unsigned,
- } });
-}
-
fn indexToKeyEnum(ip: InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {
const enum_explicit = ip.extraDataTrail(EnumExplicit, data);
const names = @ptrCast(
@@ -3222,6 +3217,7 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
.data = ip.addExtraAssumeCapacity(EnumAuto{
.decl = enum_type.decl,
.namespace = enum_type.namespace,
+ .int_tag_type = enum_type.tag_ty,
.names_map = names_map,
.fields_len = fields_len,
}),
@@ -4000,18 +3996,18 @@ pub fn getIncompleteEnum(
}
}
-pub fn getIncompleteEnumAuto(
+fn getIncompleteEnumAuto(
ip: *InternPool,
gpa: Allocator,
enum_type: Key.IncompleteEnumType,
) Allocator.Error!IncompleteEnumType {
- // Although the integer tag type will not be stored in the `EnumAuto` struct,
- // `InternPool` logic depends on it being present so that `typeOf` can be infallible.
- // Ensure it is present here:
- _ = try ip.get(gpa, .{ .int_type = .{
- .bits = if (enum_type.fields_len == 0) 0 else std.math.log2_int_ceil(u32, enum_type.fields_len),
- .signedness = .unsigned,
- } });
+ const int_tag_type = if (enum_type.tag_ty != .none)
+ enum_type.tag_ty
+ else
+ try ip.get(gpa, .{ .int_type = .{
+ .bits = if (enum_type.fields_len == 0) 0 else std.math.log2_int_ceil(u32, enum_type.fields_len),
+ .signedness = .unsigned,
+ } });
// We must keep the map in sync with `items`. The hash and equality functions
// for enum types only look at the decl field, which is present even in
@@ -4029,6 +4025,7 @@ pub fn getIncompleteEnumAuto(
const extra_index = ip.addExtraAssumeCapacity(EnumAuto{
.decl = enum_type.decl,
.namespace = enum_type.namespace,
+ .int_tag_type = int_tag_type,
.names_map = names_map,
.fields_len = enum_type.fields_len,
});
@@ -4040,7 +4037,7 @@ pub fn getIncompleteEnumAuto(
ip.extra.appendNTimesAssumeCapacity(@enumToInt(Index.none), enum_type.fields_len);
return .{
.index = @intToEnum(Index, ip.items.len - 1),
- .tag_ty_index = undefined,
+ .tag_ty_index = extra_index + std.meta.fieldIndex(EnumAuto, "int_tag_type").?,
.names_map = names_map,
.names_start = extra_index + extra_fields_len,
.values_map = .none,