| ... | @@ -69,6 +69,7 @@ const assert = std.debug.assert; | ... | @@ -69,6 +69,7 @@ const assert = std.debug.assert; |
| 69 | const BigIntConst = std.math.big.int.Const; | 69 | const BigIntConst = std.math.big.int.Const; |
| 70 | const BigIntMutable = std.math.big.int.Mutable; | 70 | const BigIntMutable = std.math.big.int.Mutable; |
| 71 | const Limb = std.math.big.Limb; | 71 | const Limb = std.math.big.Limb; |
| | 72 | const Hash = std.hash.Wyhash; |
| 72 | | 73 | |
| 73 | const InternPool = @This(); | 74 | const InternPool = @This(); |
| 74 | const Module = @import("Module.zig"); | 75 | const Module = @import("Module.zig"); |
| ... | @@ -675,34 +676,34 @@ pub const Key = union(enum) { | ... | @@ -675,34 +676,34 @@ pub const Key = union(enum) { |
| 675 | .empty_enum_value, | 676 | .empty_enum_value, |
| 676 | .inferred_error_set_type, | 677 | .inferred_error_set_type, |
| 677 | .un, | 678 | .un, |
| 678 | => |x| WyhashKing.hash(seed, asBytes(&x)), | 679 | => |x| Hash.hash(seed, asBytes(&x)), |
| 679 | | 680 | |
| 680 | .int_type => |x| WyhashKing.hash(seed + @enumToInt(x.signedness), asBytes(&x.bits)), | 681 | .int_type => |x| Hash.hash(seed + @enumToInt(x.signedness), asBytes(&x.bits)), |
| 681 | .union_type => |x| WyhashKing.hash(seed + @enumToInt(x.runtime_tag), asBytes(&x.index)), | 682 | .union_type => |x| Hash.hash(seed + @enumToInt(x.runtime_tag), asBytes(&x.index)), |
| 682 | | 683 | |
| 683 | .error_union => |x| switch (x.val) { | 684 | .error_union => |x| switch (x.val) { |
| 684 | .err_name => |y| WyhashKing.hash(seed + 0, asBytes(&x.ty) ++ asBytes(&y)), | 685 | .err_name => |y| Hash.hash(seed + 0, asBytes(&x.ty) ++ asBytes(&y)), |
| 685 | .payload => |y| WyhashKing.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)), | 686 | .payload => |y| Hash.hash(seed + 1, asBytes(&x.ty) ++ asBytes(&y)), |
| 686 | }, | 687 | }, |
| 687 | | 688 | |
| 688 | .runtime_value => |x| WyhashKing.hash(seed, asBytes(&x.val)), | 689 | .runtime_value => |x| Hash.hash(seed, asBytes(&x.val)), |
| 689 | .opaque_type => |x| WyhashKing.hash(seed, asBytes(&x.decl)), | 690 | .opaque_type => |x| Hash.hash(seed, asBytes(&x.decl)), |
| 690 | | 691 | |
| 691 | .enum_type => |enum_type| { | 692 | .enum_type => |enum_type| { |
| 692 | var hasher = std.hash.Wyhash.init(seed); | 693 | var hasher = Hash.init(seed); |
| 693 | std.hash.autoHash(&hasher, enum_type.decl); | 694 | std.hash.autoHash(&hasher, enum_type.decl); |
| 694 | return hasher.final(); | 695 | return hasher.final(); |
| 695 | }, | 696 | }, |
| 696 | | 697 | |
| 697 | .variable => |variable| { | 698 | .variable => |variable| { |
| 698 | var hasher = std.hash.Wyhash.init(seed); | 699 | var hasher = Hash.init(seed); |
| 699 | std.hash.autoHash(&hasher, variable.decl); | 700 | std.hash.autoHash(&hasher, variable.decl); |
| 700 | return hasher.final(); | 701 | return hasher.final(); |
| 701 | }, | 702 | }, |
| 702 | .extern_func => |x| WyhashKing.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)), | 703 | .extern_func => |x| Hash.hash(seed, asBytes(&x.ty) ++ asBytes(&x.decl)), |
| 703 | | 704 | |
| 704 | .int => |int| { | 705 | .int => |int| { |
| 705 | var hasher = std.hash.Wyhash.init(seed); | 706 | var hasher = Hash.init(seed); |
| 706 | // Canonicalize all integers by converting them to BigIntConst. | 707 | // Canonicalize all integers by converting them to BigIntConst. |
| 707 | switch (int.storage) { | 708 | switch (int.storage) { |
| 708 | .u64, .i64, .big_int => { | 709 | .u64, .i64, .big_int => { |
| ... | @@ -725,7 +726,7 @@ pub const Key = union(enum) { | ... | @@ -725,7 +726,7 @@ pub const Key = union(enum) { |
| 725 | }, | 726 | }, |
| 726 | | 727 | |
| 727 | .float => |float| { | 728 | .float => |float| { |
| 728 | var hasher = std.hash.Wyhash.init(seed); | 729 | var hasher = Hash.init(seed); |
| 729 | std.hash.autoHash(&hasher, float.ty); | 730 | std.hash.autoHash(&hasher, float.ty); |
| 730 | switch (float.storage) { | 731 | switch (float.storage) { |
| 731 | inline else => |val| std.hash.autoHash( | 732 | inline else => |val| std.hash.autoHash( |
| ... | @@ -743,19 +744,19 @@ pub const Key = union(enum) { | ... | @@ -743,19 +744,19 @@ pub const Key = union(enum) { |
| 743 | const seed2 = seed + @enumToInt(addr); | 744 | const seed2 = seed + @enumToInt(addr); |
| 744 | const common = asBytes(&ptr.ty) ++ asBytes(&ptr.len); | 745 | const common = asBytes(&ptr.ty) ++ asBytes(&ptr.len); |
| 745 | return switch (ptr.addr) { | 746 | return switch (ptr.addr) { |
| 746 | .decl => |x| WyhashKing.hash(seed2, common ++ asBytes(&x)), | 747 | .decl => |x| Hash.hash(seed2, common ++ asBytes(&x)), |
| 747 | | 748 | |
| 748 | .mut_decl => |x| WyhashKing.hash( | 749 | .mut_decl => |x| Hash.hash( |
| 749 | seed2, | 750 | seed2, |
| 750 | asBytes(&x.decl) ++ asBytes(&x.runtime_index), | 751 | asBytes(&x.decl) ++ asBytes(&x.runtime_index), |
| 751 | ), | 752 | ), |
| 752 | | 753 | |
| 753 | .int, .eu_payload, .opt_payload, .comptime_field => |int| WyhashKing.hash( | 754 | .int, .eu_payload, .opt_payload, .comptime_field => |int| Hash.hash( |
| 754 | seed2, | 755 | seed2, |
| 755 | asBytes(&int), | 756 | asBytes(&int), |
| 756 | ), | 757 | ), |
| 757 | | 758 | |
| 758 | .elem, .field => |x| WyhashKing.hash( | 759 | .elem, .field => |x| Hash.hash( |
| 759 | seed2, | 760 | seed2, |
| 760 | asBytes(&x.base) ++ asBytes(&x.index), | 761 | asBytes(&x.base) ++ asBytes(&x.index), |
| 761 | ), | 762 | ), |
| ... | @@ -763,7 +764,7 @@ pub const Key = union(enum) { | ... | @@ -763,7 +764,7 @@ pub const Key = union(enum) { |
| 763 | }, | 764 | }, |
| 764 | | 765 | |
| 765 | .aggregate => |aggregate| { | 766 | .aggregate => |aggregate| { |
| 766 | var hasher = std.hash.Wyhash.init(seed); | 767 | var hasher = Hash.init(seed); |
| 767 | std.hash.autoHash(&hasher, aggregate.ty); | 768 | std.hash.autoHash(&hasher, aggregate.ty); |
| 768 | const len = ip.aggregateTypeLen(aggregate.ty); | 769 | const len = ip.aggregateTypeLen(aggregate.ty); |
| 769 | const child = switch (ip.indexToKey(aggregate.ty)) { | 770 | const child = switch (ip.indexToKey(aggregate.ty)) { |
| ... | @@ -823,13 +824,13 @@ pub const Key = union(enum) { | ... | @@ -823,13 +824,13 @@ pub const Key = union(enum) { |
| 823 | }, | 824 | }, |
| 824 | | 825 | |
| 825 | .error_set_type => |error_set_type| { | 826 | .error_set_type => |error_set_type| { |
| 826 | var hasher = std.hash.Wyhash.init(seed); | 827 | var hasher = Hash.init(seed); |
| 827 | for (error_set_type.names) |elem| std.hash.autoHash(&hasher, elem); | 828 | for (error_set_type.names) |elem| std.hash.autoHash(&hasher, elem); |
| 828 | return hasher.final(); | 829 | return hasher.final(); |
| 829 | }, | 830 | }, |
| 830 | | 831 | |
| 831 | .anon_struct_type => |anon_struct_type| { | 832 | .anon_struct_type => |anon_struct_type| { |
| 832 | var hasher = std.hash.Wyhash.init(seed); | 833 | var hasher = Hash.init(seed); |
| 833 | for (anon_struct_type.types) |elem| std.hash.autoHash(&hasher, elem); | 834 | for (anon_struct_type.types) |elem| std.hash.autoHash(&hasher, elem); |
| 834 | for (anon_struct_type.values) |elem| std.hash.autoHash(&hasher, elem); | 835 | for (anon_struct_type.values) |elem| std.hash.autoHash(&hasher, elem); |
| 835 | for (anon_struct_type.names) |elem| std.hash.autoHash(&hasher, elem); | 836 | for (anon_struct_type.names) |elem| std.hash.autoHash(&hasher, elem); |
| ... | @@ -837,7 +838,7 @@ pub const Key = union(enum) { | ... | @@ -837,7 +838,7 @@ pub const Key = union(enum) { |
| 837 | }, | 838 | }, |
| 838 | | 839 | |
| 839 | .func_type => |func_type| { | 840 | .func_type => |func_type| { |
| 840 | var hasher = std.hash.Wyhash.init(seed); | 841 | var hasher = Hash.init(seed); |
| 841 | for (func_type.param_types) |param_type| std.hash.autoHash(&hasher, param_type); | 842 | for (func_type.param_types) |param_type| std.hash.autoHash(&hasher, param_type); |
| 842 | std.hash.autoHash(&hasher, func_type.return_type); | 843 | std.hash.autoHash(&hasher, func_type.return_type); |
| 843 | std.hash.autoHash(&hasher, func_type.comptime_bits); | 844 | std.hash.autoHash(&hasher, func_type.comptime_bits); |
| ... | @@ -851,7 +852,7 @@ pub const Key = union(enum) { | ... | @@ -851,7 +852,7 @@ pub const Key = union(enum) { |
| 851 | }, | 852 | }, |
| 852 | | 853 | |
| 853 | .memoized_call => |memoized_call| { | 854 | .memoized_call => |memoized_call| { |
| 854 | var hasher = std.hash.Wyhash.init(seed); | 855 | var hasher = Hash.init(seed); |
| 855 | std.hash.autoHash(&hasher, memoized_call.func); | 856 | std.hash.autoHash(&hasher, memoized_call.func); |
| 856 | for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg); | 857 | for (memoized_call.arg_values) |arg| std.hash.autoHash(&hasher, arg); |
| 857 | return hasher.final(); | 858 | return hasher.final(); |
| ... | @@ -5744,79 +5745,3 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois | ... | @@ -5744,79 +5745,3 @@ pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPois |
| 5744 | .none => unreachable, // special tag | 5745 | .none => unreachable, // special tag |
| 5745 | }; | 5746 | }; |
| 5746 | } | 5747 | } |
| 5747 | | | |
| 5748 | /// I got this from King, using this temporarily until std lib hashing can be | | |
| 5749 | /// improved to make stateless hashing performant. Currently the | | |
| 5750 | /// implementations suffer from not special casing small lengths and not taking | | |
| 5751 | /// advantage of comptime-known lengths, both of which this implementation | | |
| 5752 | /// does. | | |
| 5753 | const WyhashKing = struct { | | |
| 5754 | inline fn mum(pair: *[2]u64) void { | | |
| 5755 | const x = @as(u128, pair[0]) *% pair[1]; | | |
| 5756 | pair[0] = @truncate(u64, x); | | |
| 5757 | pair[1] = @truncate(u64, x >> 64); | | |
| 5758 | } | | |
| 5759 | | | |
| 5760 | inline fn mix(a: u64, b: u64) u64 { | | |
| 5761 | var pair = [_]u64{ a, b }; | | |
| 5762 | mum(&pair); | | |
| 5763 | return pair[0] ^ pair[1]; | | |
| 5764 | } | | |
| 5765 | | | |
| 5766 | inline fn read(comptime I: type, in: []const u8) I { | | |
| 5767 | return std.mem.readIntLittle(I, in[0..@sizeOf(I)]); | | |
| 5768 | } | | |
| 5769 | | | |
| 5770 | const secret = [_]u64{ | | |
| 5771 | 0xa0761d6478bd642f, | | |
| 5772 | 0xe7037ed1a0b428db, | | |
| 5773 | 0x8ebc6af09c88c6e3, | | |
| 5774 | 0x589965cc75374cc3, | | |
| 5775 | }; | | |
| 5776 | | | |
| 5777 | fn hash(seed: u64, input: anytype) u64 { | | |
| 5778 | var in: []const u8 = input; | | |
| 5779 | var last = std.mem.zeroes([2]u64); | | |
| 5780 | const starting_len: u64 = input.len; | | |
| 5781 | var state = seed ^ mix(seed ^ secret[0], secret[1]); | | |
| 5782 | | | |
| 5783 | if (in.len <= 16) { | | |
| 5784 | if (in.len >= 4) { | | |
| 5785 | const end = (in.len >> 3) << 2; | | |
| 5786 | last[0] = (@as(u64, read(u32, in)) << 32) | read(u32, in[end..]); | | |
| 5787 | last[1] = (@as(u64, read(u32, in[in.len - 4 ..])) << 32) | read(u32, in[in.len - 4 - end ..]); | | |
| 5788 | } else if (in.len > 0) { | | |
| 5789 | last[0] = (@as(u64, in[0]) << 16) | (@as(u64, in[in.len >> 1]) << 8) | in[in.len - 1]; | | |
| 5790 | } | | |
| 5791 | } else { | | |
| 5792 | large: { | | |
| 5793 | if (in.len <= 48) break :large; | | |
| 5794 | var split = [_]u64{ state, state, state }; | | |
| 5795 | while (true) { | | |
| 5796 | for (&split, 0..) |*lane, i| { | | |
| 5797 | const a = read(u64, in[(i * 2) * 8 ..]) ^ secret[i + 1]; | | |
| 5798 | const b = read(u64, in[((i * 2) + 1) * 8 ..]) ^ lane.*; | | |
| 5799 | lane.* = mix(a, b); | | |
| 5800 | } | | |
| 5801 | in = in[48..]; | | |
| 5802 | if (in.len > 48) continue; | | |
| 5803 | state = split[0] ^ (split[1] ^ split[2]); | | |
| 5804 | break :large; | | |
| 5805 | } | | |
| 5806 | } | | |
| 5807 | while (true) { | | |
| 5808 | if (in.len <= 16) break; | | |
| 5809 | state = mix(read(u64, in) ^ secret[1], read(u64, in[8..]) ^ state); | | |
| 5810 | in = in[16..]; | | |
| 5811 | if (in.len <= 16) break; | | |
| 5812 | } | | |
| 5813 | last[0] = read(u64, in[in.len - 16 ..]); | | |
| 5814 | last[1] = read(u64, in[in.len - 8 ..]); | | |
| 5815 | } | | |
| 5816 | | | |
| 5817 | last[0] ^= secret[1]; | | |
| 5818 | last[1] ^= state; | | |
| 5819 | mum(&last); | | |
| 5820 | return mix(last[0] ^ secret[0] ^ starting_len, last[1] ^ secret[1]); | | |
| 5821 | } | | |
| 5822 | }; | | |