Skip to content

Commit 8f38f23

Browse files
andrewrkjacobly0
authored andcommitted
InternPool: pass by const pointer
The Zig language allows the compiler to make this optimization automatically. We should definitely make the compiler do that, and revert this commit. However, that will not happen in this branch, and I want to continue to explore achieving performance parity with merge-base. So, this commit changes all InternPool parameters to be passed by const pointer rather than by value. I measured a 1.03x ± 0.03 speedup vs the previous commit compiling the (set of passing) behavior tests. Against merge-base, this commit is 1.17x ± 0.04 slower, which is an improvement from the previous measurement of 1.22x ± 0.02. Related issue: ziglang#13510 Related issue: ziglang#14129 Related issue: ziglang#15688
1 parent e1c3ab5 commit 8f38f23

File tree

17 files changed

+94
-94
lines changed

17 files changed

+94
-94
lines changed

src/Air.zig

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1182,15 +1182,15 @@ pub fn getMainBody(air: Air) []const Air.Inst.Index {
11821182
return air.extra[extra.end..][0..extra.data.body_len];
11831183
}
11841184

1185-
pub fn typeOf(air: Air, inst: Air.Inst.Ref, ip: InternPool) Type {
1185+
pub fn typeOf(air: Air, inst: Air.Inst.Ref, ip: *const InternPool) Type {
11861186
const ref_int = @enumToInt(inst);
11871187
if (ref_int < InternPool.static_keys.len) {
11881188
return InternPool.static_keys[ref_int].typeOf().toType();
11891189
}
11901190
return air.typeOfIndex(ref_int - ref_start_index, ip);
11911191
}
11921192

1193-
pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: InternPool) Type {
1193+
pub fn typeOfIndex(air: Air, inst: Air.Inst.Index, ip: *const InternPool) Type {
11941194
const datas = air.instructions.items(.data);
11951195
switch (air.instructions.items(.tag)[inst]) {
11961196
.add,
@@ -1520,7 +1520,7 @@ pub fn value(air: Air, inst: Inst.Ref, mod: *Module) !?Value {
15201520
const air_datas = air.instructions.items(.data);
15211521
switch (air.instructions.items(.tag)[inst_index]) {
15221522
.interned => return air_datas[inst_index].interned.toValue(),
1523-
else => return air.typeOfIndex(inst_index, mod.intern_pool).onePossibleValue(mod),
1523+
else => return air.typeOfIndex(inst_index, &mod.intern_pool).onePossibleValue(mod),
15241524
}
15251525
}
15261526

@@ -1537,7 +1537,7 @@ pub fn nullTerminatedString(air: Air, index: usize) [:0]const u8 {
15371537
/// because it can cause side effects. If an instruction does not need to be
15381538
/// lowered, and Liveness determines its result is unused, backends should
15391539
/// avoid lowering it.
1540-
pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: InternPool) bool {
1540+
pub fn mustLower(air: Air, inst: Air.Inst.Index, ip: *const InternPool) bool {
15411541
const data = air.instructions.items(.data)[inst];
15421542
return switch (air.instructions.items(.tag)[inst]) {
15431543
.arg,

src/InternPool.zig

Lines changed: 42 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -2992,7 +2992,7 @@ pub fn indexToKey(ip: *const InternPool, index: Index) Key {
29922992
};
29932993
}
29942994

2995-
fn indexToKeyFuncType(ip: InternPool, data: u32) Key.FuncType {
2995+
fn indexToKeyFuncType(ip: *const InternPool, data: u32) Key.FuncType {
29962996
const type_function = ip.extraDataTrail(TypeFunction, data);
29972997
const param_types = @ptrCast(
29982998
[]Index,
@@ -3015,7 +3015,7 @@ fn indexToKeyFuncType(ip: InternPool, data: u32) Key.FuncType {
30153015
};
30163016
}
30173017

3018-
fn indexToKeyEnum(ip: InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {
3018+
fn indexToKeyEnum(ip: *const InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key {
30193019
const enum_explicit = ip.extraDataTrail(EnumExplicit, data);
30203020
const names = @ptrCast(
30213021
[]const NullTerminatedString,
@@ -3038,7 +3038,7 @@ fn indexToKeyEnum(ip: InternPool, data: u32, tag_mode: Key.EnumType.TagMode) Key
30383038
} };
30393039
}
30403040

3041-
fn indexToKeyBigInt(ip: InternPool, limb_index: u32, positive: bool) Key {
3041+
fn indexToKeyBigInt(ip: *const InternPool, limb_index: u32, positive: bool) Key {
30423042
const int_info = ip.limbData(Int, limb_index);
30433043
return .{ .int = .{
30443044
.ty = int_info.ty,
@@ -4351,7 +4351,7 @@ fn addLimbsAssumeCapacity(ip: *InternPool, limbs: []const Limb) void {
43514351
}
43524352
}
43534353

4354-
fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data: T, end: usize } {
4354+
fn extraDataTrail(ip: *const InternPool, comptime T: type, index: usize) struct { data: T, end: usize } {
43554355
var result: T = undefined;
43564356
const fields = @typeInfo(T).Struct.fields;
43574357
inline for (fields, 0..) |field, i| {
@@ -4384,12 +4384,12 @@ fn extraDataTrail(ip: InternPool, comptime T: type, index: usize) struct { data:
43844384
};
43854385
}
43864386

4387-
fn extraData(ip: InternPool, comptime T: type, index: usize) T {
4387+
fn extraData(ip: *const InternPool, comptime T: type, index: usize) T {
43884388
return extraDataTrail(ip, T, index).data;
43894389
}
43904390

43914391
/// Asserts the struct has 32-bit fields and the number of fields is evenly divisible by 2.
4392-
fn limbData(ip: InternPool, comptime T: type, index: usize) T {
4392+
fn limbData(ip: *const InternPool, comptime T: type, index: usize) T {
43934393
switch (@sizeOf(Limb)) {
43944394
@sizeOf(u32) => return extraData(ip, T, index),
43954395
@sizeOf(u64) => {},
@@ -4413,7 +4413,7 @@ fn limbData(ip: InternPool, comptime T: type, index: usize) T {
44134413
}
44144414

44154415
/// This function returns the Limb slice that is trailing data after a payload.
4416-
fn limbSlice(ip: InternPool, comptime S: type, limb_index: u32, len: u32) []const Limb {
4416+
fn limbSlice(ip: *const InternPool, comptime S: type, limb_index: u32, len: u32) []const Limb {
44174417
const field_count = @typeInfo(S).Struct.fields.len;
44184418
switch (@sizeOf(Limb)) {
44194419
@sizeOf(u32) => {
@@ -4433,7 +4433,7 @@ const LimbsAsIndexes = struct {
44334433
len: u32,
44344434
};
44354435

4436-
fn limbsSliceToIndex(ip: InternPool, limbs: []const Limb) LimbsAsIndexes {
4436+
fn limbsSliceToIndex(ip: *const InternPool, limbs: []const Limb) LimbsAsIndexes {
44374437
const host_slice = switch (@sizeOf(Limb)) {
44384438
@sizeOf(u32) => ip.extra.items,
44394439
@sizeOf(u64) => ip.limbs.items,
@@ -4447,7 +4447,7 @@ fn limbsSliceToIndex(ip: InternPool, limbs: []const Limb) LimbsAsIndexes {
44474447
}
44484448

44494449
/// This function converts Limb array indexes to a primitive slice type.
4450-
fn limbsIndexToSlice(ip: InternPool, limbs: LimbsAsIndexes) []const Limb {
4450+
fn limbsIndexToSlice(ip: *const InternPool, limbs: LimbsAsIndexes) []const Limb {
44514451
return switch (@sizeOf(Limb)) {
44524452
@sizeOf(u32) => ip.extra.items[limbs.start..][0..limbs.len],
44534453
@sizeOf(u64) => ip.limbs.items[limbs.start..][0..limbs.len],
@@ -4485,7 +4485,7 @@ test "basic usage" {
44854485
try std.testing.expect(another_array_i32 == array_i32);
44864486
}
44874487

4488-
pub fn childType(ip: InternPool, i: Index) Index {
4488+
pub fn childType(ip: *const InternPool, i: Index) Index {
44894489
return switch (ip.indexToKey(i)) {
44904490
.ptr_type => |ptr_type| ptr_type.elem_type,
44914491
.vector_type => |vector_type| vector_type.child,
@@ -4496,7 +4496,7 @@ pub fn childType(ip: InternPool, i: Index) Index {
44964496
}
44974497

44984498
/// Given a slice type, returns the type of the ptr field.
4499-
pub fn slicePtrType(ip: InternPool, i: Index) Index {
4499+
pub fn slicePtrType(ip: *const InternPool, i: Index) Index {
45004500
switch (i) {
45014501
.slice_const_u8_type => return .manyptr_const_u8_type,
45024502
.slice_const_u8_sentinel_0_type => return .manyptr_const_u8_sentinel_0_type,
@@ -4510,7 +4510,7 @@ pub fn slicePtrType(ip: InternPool, i: Index) Index {
45104510
}
45114511

45124512
/// Given a slice value, returns the value of the ptr field.
4513-
pub fn slicePtr(ip: InternPool, i: Index) Index {
4513+
pub fn slicePtr(ip: *const InternPool, i: Index) Index {
45144514
const item = ip.items.get(@enumToInt(i));
45154515
switch (item.tag) {
45164516
.ptr_slice => return ip.extraData(PtrSlice, item.data).ptr,
@@ -4519,7 +4519,7 @@ pub fn slicePtr(ip: InternPool, i: Index) Index {
45194519
}
45204520

45214521
/// Given a slice value, returns the value of the len field.
4522-
pub fn sliceLen(ip: InternPool, i: Index) Index {
4522+
pub fn sliceLen(ip: *const InternPool, i: Index) Index {
45234523
const item = ip.items.get(@enumToInt(i));
45244524
switch (item.tag) {
45254525
.ptr_slice => return ip.extraData(PtrSlice, item.data).len,
@@ -4702,15 +4702,15 @@ pub fn getCoercedInts(ip: *InternPool, gpa: Allocator, int: Key.Int, new_ty: Ind
47024702
} });
47034703
}
47044704

4705-
pub fn indexToStructType(ip: InternPool, val: Index) Module.Struct.OptionalIndex {
4705+
pub fn indexToStructType(ip: *const InternPool, val: Index) Module.Struct.OptionalIndex {
47064706
assert(val != .none);
47074707
const tags = ip.items.items(.tag);
47084708
if (tags[@enumToInt(val)] != .type_struct) return .none;
47094709
const datas = ip.items.items(.data);
47104710
return @intToEnum(Module.Struct.Index, datas[@enumToInt(val)]).toOptional();
47114711
}
47124712

4713-
pub fn indexToUnionType(ip: InternPool, val: Index) Module.Union.OptionalIndex {
4713+
pub fn indexToUnionType(ip: *const InternPool, val: Index) Module.Union.OptionalIndex {
47144714
assert(val != .none);
47154715
const tags = ip.items.items(.tag);
47164716
switch (tags[@enumToInt(val)]) {
@@ -4721,7 +4721,7 @@ pub fn indexToUnionType(ip: InternPool, val: Index) Module.Union.OptionalIndex {
47214721
return @intToEnum(Module.Union.Index, datas[@enumToInt(val)]).toOptional();
47224722
}
47234723

4724-
pub fn indexToFuncType(ip: InternPool, val: Index) ?Key.FuncType {
4724+
pub fn indexToFuncType(ip: *const InternPool, val: Index) ?Key.FuncType {
47254725
assert(val != .none);
47264726
const tags = ip.items.items(.tag);
47274727
const datas = ip.items.items(.data);
@@ -4731,15 +4731,15 @@ pub fn indexToFuncType(ip: InternPool, val: Index) ?Key.FuncType {
47314731
}
47324732
}
47334733

4734-
pub fn indexToFunc(ip: InternPool, val: Index) Module.Fn.OptionalIndex {
4734+
pub fn indexToFunc(ip: *const InternPool, val: Index) Module.Fn.OptionalIndex {
47354735
assert(val != .none);
47364736
const tags = ip.items.items(.tag);
47374737
if (tags[@enumToInt(val)] != .func) return .none;
47384738
const datas = ip.items.items(.data);
47394739
return ip.extraData(Key.Func, datas[@enumToInt(val)]).index.toOptional();
47404740
}
47414741

4742-
pub fn indexToInferredErrorSetType(ip: InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex {
4742+
pub fn indexToInferredErrorSetType(ip: *const InternPool, val: Index) Module.Fn.InferredErrorSet.OptionalIndex {
47434743
assert(val != .none);
47444744
const tags = ip.items.items(.tag);
47454745
if (tags[@enumToInt(val)] != .type_inferred_error_set) return .none;
@@ -4748,7 +4748,7 @@ pub fn indexToInferredErrorSetType(ip: InternPool, val: Index) Module.Fn.Inferre
47484748
}
47494749

47504750
/// includes .comptime_int_type
4751-
pub fn isIntegerType(ip: InternPool, ty: Index) bool {
4751+
pub fn isIntegerType(ip: *const InternPool, ty: Index) bool {
47524752
return switch (ty) {
47534753
.usize_type,
47544754
.isize_type,
@@ -4769,7 +4769,7 @@ pub fn isIntegerType(ip: InternPool, ty: Index) bool {
47694769
}
47704770

47714771
/// does not include .enum_literal_type
4772-
pub fn isEnumType(ip: InternPool, ty: Index) bool {
4772+
pub fn isEnumType(ip: *const InternPool, ty: Index) bool {
47734773
return switch (ty) {
47744774
.atomic_order_type,
47754775
.atomic_rmw_op_type,
@@ -4783,35 +4783,35 @@ pub fn isEnumType(ip: InternPool, ty: Index) bool {
47834783
};
47844784
}
47854785

4786-
pub fn isFunctionType(ip: InternPool, ty: Index) bool {
4786+
pub fn isFunctionType(ip: *const InternPool, ty: Index) bool {
47874787
return ip.indexToKey(ty) == .func_type;
47884788
}
47894789

4790-
pub fn isPointerType(ip: InternPool, ty: Index) bool {
4790+
pub fn isPointerType(ip: *const InternPool, ty: Index) bool {
47914791
return ip.indexToKey(ty) == .ptr_type;
47924792
}
47934793

4794-
pub fn isOptionalType(ip: InternPool, ty: Index) bool {
4794+
pub fn isOptionalType(ip: *const InternPool, ty: Index) bool {
47954795
return ip.indexToKey(ty) == .opt_type;
47964796
}
47974797

47984798
/// includes .inferred_error_set_type
4799-
pub fn isErrorSetType(ip: InternPool, ty: Index) bool {
4799+
pub fn isErrorSetType(ip: *const InternPool, ty: Index) bool {
48004800
return ty == .anyerror_type or switch (ip.indexToKey(ty)) {
48014801
.error_set_type, .inferred_error_set_type => true,
48024802
else => false,
48034803
};
48044804
}
48054805

4806-
pub fn isInferredErrorSetType(ip: InternPool, ty: Index) bool {
4806+
pub fn isInferredErrorSetType(ip: *const InternPool, ty: Index) bool {
48074807
return ip.indexToKey(ty) == .inferred_error_set_type;
48084808
}
48094809

4810-
pub fn isErrorUnionType(ip: InternPool, ty: Index) bool {
4810+
pub fn isErrorUnionType(ip: *const InternPool, ty: Index) bool {
48114811
return ip.indexToKey(ty) == .error_union_type;
48124812
}
48134813

4814-
pub fn isAggregateType(ip: InternPool, ty: Index) bool {
4814+
pub fn isAggregateType(ip: *const InternPool, ty: Index) bool {
48154815
return switch (ip.indexToKey(ty)) {
48164816
.array_type, .vector_type, .anon_struct_type, .struct_type => true,
48174817
else => false,
@@ -4827,11 +4827,11 @@ pub fn mutateVarInit(ip: *InternPool, index: Index, init_index: Index) void {
48274827
ip.extra.items[ip.items.items(.data)[@enumToInt(index)] + field_index] = @enumToInt(init_index);
48284828
}
48294829

4830-
pub fn dump(ip: InternPool) void {
4830+
pub fn dump(ip: *const InternPool) void {
48314831
dumpFallible(ip, std.heap.page_allocator) catch return;
48324832
}
48334833

4834-
fn dumpFallible(ip: InternPool, arena: Allocator) anyerror!void {
4834+
fn dumpFallible(ip: *const InternPool, arena: Allocator) anyerror!void {
48354835
const items_size = (1 + 4) * ip.items.len;
48364836
const extra_size = 4 * ip.extra.items.len;
48374837
const limbs_size = 8 * ip.limbs.items.len;
@@ -5023,35 +5023,35 @@ pub fn structPtr(ip: *InternPool, index: Module.Struct.Index) *Module.Struct {
50235023
return ip.allocated_structs.at(@enumToInt(index));
50245024
}
50255025

5026-
pub fn structPtrConst(ip: InternPool, index: Module.Struct.Index) *const Module.Struct {
5026+
pub fn structPtrConst(ip: *const InternPool, index: Module.Struct.Index) *const Module.Struct {
50275027
return ip.allocated_structs.at(@enumToInt(index));
50285028
}
50295029

5030-
pub fn structPtrUnwrapConst(ip: InternPool, index: Module.Struct.OptionalIndex) ?*const Module.Struct {
5030+
pub fn structPtrUnwrapConst(ip: *const InternPool, index: Module.Struct.OptionalIndex) ?*const Module.Struct {
50315031
return structPtrConst(ip, index.unwrap() orelse return null);
50325032
}
50335033

50345034
pub fn unionPtr(ip: *InternPool, index: Module.Union.Index) *Module.Union {
50355035
return ip.allocated_unions.at(@enumToInt(index));
50365036
}
50375037

5038-
pub fn unionPtrConst(ip: InternPool, index: Module.Union.Index) *const Module.Union {
5038+
pub fn unionPtrConst(ip: *const InternPool, index: Module.Union.Index) *const Module.Union {
50395039
return ip.allocated_unions.at(@enumToInt(index));
50405040
}
50415041

50425042
pub fn funcPtr(ip: *InternPool, index: Module.Fn.Index) *Module.Fn {
50435043
return ip.allocated_funcs.at(@enumToInt(index));
50445044
}
50455045

5046-
pub fn funcPtrConst(ip: InternPool, index: Module.Fn.Index) *const Module.Fn {
5046+
pub fn funcPtrConst(ip: *const InternPool, index: Module.Fn.Index) *const Module.Fn {
50475047
return ip.allocated_funcs.at(@enumToInt(index));
50485048
}
50495049

50505050
pub fn inferredErrorSetPtr(ip: *InternPool, index: Module.Fn.InferredErrorSet.Index) *Module.Fn.InferredErrorSet {
50515051
return ip.allocated_inferred_error_sets.at(@enumToInt(index));
50525052
}
50535053

5054-
pub fn inferredErrorSetPtrConst(ip: InternPool, index: Module.Fn.InferredErrorSet.Index) *const Module.Fn.InferredErrorSet {
5054+
pub fn inferredErrorSetPtrConst(ip: *const InternPool, index: Module.Fn.InferredErrorSet.Index) *const Module.Fn.InferredErrorSet {
50555055
return ip.allocated_inferred_error_sets.at(@enumToInt(index));
50565056
}
50575057

@@ -5182,19 +5182,19 @@ pub fn getString(ip: *InternPool, s: []const u8) OptionalNullTerminatedString {
51825182
}
51835183
}
51845184

5185-
pub fn stringToSlice(ip: InternPool, s: NullTerminatedString) [:0]const u8 {
5185+
pub fn stringToSlice(ip: *const InternPool, s: NullTerminatedString) [:0]const u8 {
51865186
const string_bytes = ip.string_bytes.items;
51875187
const start = @enumToInt(s);
51885188
var end: usize = start;
51895189
while (string_bytes[end] != 0) end += 1;
51905190
return string_bytes[start..end :0];
51915191
}
51925192

5193-
pub fn stringToSliceUnwrap(ip: InternPool, s: OptionalNullTerminatedString) ?[:0]const u8 {
5193+
pub fn stringToSliceUnwrap(ip: *const InternPool, s: OptionalNullTerminatedString) ?[:0]const u8 {
51945194
return ip.stringToSlice(s.unwrap() orelse return null);
51955195
}
51965196

5197-
pub fn typeOf(ip: InternPool, index: Index) Index {
5197+
pub fn typeOf(ip: *const InternPool, index: Index) Index {
51985198
// This optimization of static keys is required so that typeOf can be called
51995199
// on static keys that haven't been added yet during static key initialization.
52005200
// An alternative would be to topological sort the static keys, but this would
@@ -5382,12 +5382,12 @@ pub fn typeOf(ip: InternPool, index: Index) Index {
53825382
}
53835383

53845384
/// Assumes that the enum's field indexes equal its value tags.
5385-
pub fn toEnum(ip: InternPool, comptime E: type, i: Index) E {
5385+
pub fn toEnum(ip: *const InternPool, comptime E: type, i: Index) E {
53865386
const int = ip.indexToKey(i).enum_tag.int;
53875387
return @intToEnum(E, ip.indexToKey(int).int.storage.u64);
53885388
}
53895389

5390-
pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {
5390+
pub fn aggregateTypeLen(ip: *const InternPool, ty: Index) u64 {
53915391
return switch (ip.indexToKey(ty)) {
53925392
.struct_type => |struct_type| ip.structPtrConst(struct_type.index.unwrap() orelse return 0).fields.count(),
53935393
.anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
@@ -5397,7 +5397,7 @@ pub fn aggregateTypeLen(ip: InternPool, ty: Index) u64 {
53975397
};
53985398
}
53995399

5400-
pub fn aggregateTypeLenIncludingSentinel(ip: InternPool, ty: Index) u64 {
5400+
pub fn aggregateTypeLenIncludingSentinel(ip: *const InternPool, ty: Index) u64 {
54015401
return switch (ip.indexToKey(ty)) {
54025402
.struct_type => |struct_type| ip.structPtrConst(struct_type.index.unwrap() orelse return 0).fields.count(),
54035403
.anon_struct_type => |anon_struct_type| anon_struct_type.types.len,
@@ -5407,7 +5407,7 @@ pub fn aggregateTypeLenIncludingSentinel(ip: InternPool, ty: Index) u64 {
54075407
};
54085408
}
54095409

5410-
pub fn isNoReturn(ip: InternPool, ty: Index) bool {
5410+
pub fn isNoReturn(ip: *const InternPool, ty: Index) bool {
54115411
return switch (ty) {
54125412
.noreturn_type => true,
54135413
else => switch (ip.indexToKey(ty)) {
@@ -5420,7 +5420,7 @@ pub fn isNoReturn(ip: InternPool, ty: Index) bool {
54205420

54215421
/// This is a particularly hot function, so we operate directly on encodings
54225422
/// rather than the more straightforward implementation of calling `indexToKey`.
5423-
pub fn zigTypeTagOrPoison(ip: InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId {
5423+
pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId {
54245424
return switch (index) {
54255425
.u1_type,
54265426
.u8_type,

0 commit comments

Comments
 (0)