authorgravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-05-29 17:18:23-07:00
committergravatar for andrew@ziglang.orgAndrew Kelley <andrew@ziglang.org> 2023-06-10 20:47:56-07:00
logf7177fb8215714f9f22e3f9da0d3c7d3ad58d390
tree21b113788cf614164b11a3f3968543e352080be0
parentf2778f7ca07cdfd599c65185dbcc6a648740fd5d

InternPool: avoid indexToKey recursion for opt_payload

This is a hot function, and recursion makes it more difficult to profile, as well as likely making it more difficult to optimize. Previously, indexToKey for opt_payload would call getAssumeExists() on the optional type. This made it possible to omit the optional type in the encoding of opt_payload. However, getAssumeExists() *must* call indexToKey because of hashing/equality. So, this commit adds the optional type to the opt_payload encoding, which increases its "extra" size from 0 to 8 bytes. As a result, the opt_payload encoding went from not showing up on the top 25 largest tags to...still not showing up in the top 25 largest tags. This also helps make InternPool.typeOf() no longer need to call indexToKey which is another hot function and another source of recursion.

1 files changed, 11 insertions(+), 14 deletions(-)

src/InternPool.zig+11-14
......@@ -1383,7 +1383,7 @@ pub const Index = enum(u32) {
13831383 ptr_elem: struct { data: *PtrBaseIndex },
13841384 ptr_field: struct { data: *PtrBaseIndex },
13851385 ptr_slice: struct { data: *PtrSlice },
1386 opt_payload: DataIsIndex,
1386 opt_payload: struct { data: *TypeValue },
13871387 opt_null: DataIsIndex,
13881388 int_u8: struct { data: u8 },
13891389 int_u16: struct { data: u16 },
......@@ -1807,9 +1807,8 @@ pub const Tag = enum(u8) {
18071807 /// already contains the slice type corresponding to this payload.
18081808 ptr_slice,
18091809 /// An optional value that is non-null.
1810 /// data is Index of the payload value.
1811 /// In order to use this encoding, one must ensure that the `InternPool`
1812 /// already contains the optional type corresponding to this payload.
1810 /// data is extra index of `TypeValue`.
1811 /// The type is the optional type (not the payload type).
18131812 opt_payload,
18141813 /// An optional value that is null.
18151814 /// data is Index of the optional type.
......@@ -2577,15 +2576,10 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
25772576 .val = .none,
25782577 } },
25792578 .opt_payload => {
2580 const payload_val = @intToEnum(Index, data);
2581 // The existence of `opt_payload` guarantees that the optional type will be
2582 // stored in the `InternPool`.
2583 const opt_ty = ip.getAssumeExists(.{
2584 .opt_type = ip.typeOf(payload_val),
2585 });
2579 const extra = ip.extraData(TypeValue, data);
25862580 return .{ .opt = .{
2587 .ty = opt_ty,
2588 .val = payload_val,
2581 .ty = extra.ty,
2582 .val = extra.val,
25892583 } };
25902584 },
25912585 .ptr_decl => {
......@@ -3375,7 +3369,10 @@ pub fn get(ip: *InternPool, gpa: Allocator, key: Key) Allocator.Error!Index {
33753369 .data = @enumToInt(opt.ty),
33763370 } else .{
33773371 .tag = .opt_payload,
3378 .data = @enumToInt(opt.val),
3372 .data = try ip.addExtra(gpa, TypeValue{
3373 .ty = opt.ty,
3374 .val = opt.val,
3375 }),
33793376 });
33803377 },
33813378
......@@ -4800,7 +4797,7 @@ fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
48004797 .ptr_field => @sizeOf(PtrBaseIndex),
48014798 .ptr_slice => @sizeOf(PtrSlice),
48024799 .opt_null => 0,
4803 .opt_payload => 0,
4800 .opt_payload => @sizeOf(TypeValue),
48044801 .int_u8 => 0,
48054802 .int_u16 => 0,
48064803 .int_u32 => 0,