From 6b56f4ff0bf9ac9c5e0b4a11cf0536472447bc4a Mon Sep 17 00:00:00 2001 From: Jacob Young Date: Tue, 20 Jun 2023 13:42:25 -0400 Subject: [PATCH] Value: optimize `isPtrToThreadLocal` --- src/InternPool.zig | 24 ++++++++++++++++++++++++ src/value.zig | 30 +++--------------------------- 2 files changed, 27 insertions(+), 27 deletions(-) diff --git a/src/InternPool.zig b/src/InternPool.zig index 7cddfef693..bece6dbc4a 100644 --- a/src/InternPool.zig +++ b/src/InternPool.zig @@ -5706,6 +5706,30 @@ pub fn isRuntimeValue(ip: *const InternPool, val: Index) bool { return ip.items.items(.tag)[@intFromEnum(val)] == .runtime_value; } +pub fn getBackingDecl(ip: *const InternPool, val: Index) Module.Decl.OptionalIndex { + var base = @intFromEnum(val); + while (true) { + switch (ip.items.items(.tag)[base]) { + inline .ptr_decl, + .ptr_mut_decl, + => |tag| return @enumFromInt(Module.Decl.OptionalIndex, ip.extra.items[ + ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "decl").? + ]), + inline .ptr_eu_payload, + .ptr_opt_payload, + .ptr_elem, + .ptr_field, + => |tag| base = ip.extra.items[ + ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "base").? + ], + inline .ptr_slice => |tag| base = ip.extra.items[ + ip.items.items(.data)[base] + std.meta.fieldIndex(tag.Payload(), "ptr").? + ], + else => return .none, + } + } +} + /// This is a particularly hot function, so we operate directly on encodings /// rather than the more straightforward implementation of calling `indexToKey`. pub fn zigTypeTagOrPoison(ip: *const InternPool, index: Index) error{GenericPoison}!std.builtin.TypeId { diff --git a/src/value.zig b/src/value.zig index 00c8fa924c..0a5131d3f8 100644 --- a/src/value.zig +++ b/src/value.zig @@ -1851,33 +1851,9 @@ pub const Value = struct { } pub fn isPtrToThreadLocal(val: Value, mod: *Module) bool { - return val.ip_index != .none and switch (mod.intern_pool.indexToKey(val.toIntern())) { - .variable => false, - else => val.isPtrToThreadLocalInner(mod), - }; - } - - pub fn isPtrToThreadLocalInner(val: Value, mod: *Module) bool { - return val.ip_index != .none and switch (mod.intern_pool.indexToKey(val.toIntern())) { - .variable => |variable| variable.is_threadlocal, - .ptr => |ptr| switch (ptr.addr) { - .decl => |decl_index| { - const decl = mod.declPtr(decl_index); - assert(decl.has_tv); - return decl.val.isPtrToThreadLocalInner(mod); - }, - .mut_decl => |mut_decl| { - const decl = mod.declPtr(mut_decl.decl); - assert(decl.has_tv); - return decl.val.isPtrToThreadLocalInner(mod); - }, - .int => false, - .eu_payload, .opt_payload => |base_ptr| base_ptr.toValue().isPtrToThreadLocalInner(mod), - .comptime_field => |comptime_field| comptime_field.toValue().isPtrToThreadLocalInner(mod), - .elem, .field => |base_index| base_index.base.toValue().isPtrToThreadLocalInner(mod), - }, - else => false, - }; + const backing_decl = mod.intern_pool.getBackingDecl(val.toIntern()).unwrap() orelse return false; + const variable = mod.declPtr(backing_decl).getOwnedVariable(mod) orelse return false; + return variable.is_threadlocal; } // Asserts that the provided start/end are in-bounds.