Commit 6b56f4ff0b

Jacob Young <jacobly0@users.noreply.github.com>
2023-06-20 19:42:25
Value: optimize `isPtrToThreadLocal`
1 parent d69e324
Changed files (2)
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 {
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.