InternPool: implement and use thread-safe list for items
This commit is contained in:
@@ -2745,7 +2745,7 @@ pub fn makeBinFileWritable(comp: *Compilation) !void {
|
||||
|
||||
const Header = extern struct {
|
||||
intern_pool: extern struct {
|
||||
items_len: u32,
|
||||
//items_len: u32,
|
||||
extra_len: u32,
|
||||
limbs_len: u32,
|
||||
//string_bytes_len: u32,
|
||||
@@ -2774,7 +2774,7 @@ pub fn saveState(comp: *Compilation) !void {
|
||||
const ip = &zcu.intern_pool;
|
||||
const header: Header = .{
|
||||
.intern_pool = .{
|
||||
.items_len = @intCast(ip.items.len),
|
||||
//.items_len = @intCast(ip.items.len),
|
||||
.extra_len = @intCast(ip.extra.items.len),
|
||||
.limbs_len = @intCast(ip.limbs.items.len),
|
||||
//.string_bytes_len = @intCast(ip.string_bytes.items.len),
|
||||
@@ -2792,8 +2792,8 @@ pub fn saveState(comp: *Compilation) !void {
|
||||
addBuf(&bufs_list, &bufs_len, mem.asBytes(&header));
|
||||
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.limbs.items));
|
||||
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.extra.items));
|
||||
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.data)));
|
||||
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.tag)));
|
||||
//addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.data)));
|
||||
//addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.items.items(.tag)));
|
||||
//addBuf(&bufs_list, &bufs_len, ip.string_bytes.items);
|
||||
addBuf(&bufs_list, &bufs_len, mem.sliceAsBytes(ip.tracked_insts.keys()));
|
||||
|
||||
|
||||
1462
src/InternPool.zig
1462
src/InternPool.zig
File diff suppressed because it is too large
Load Diff
25
src/Sema.zig
25
src/Sema.zig
@@ -2717,10 +2717,11 @@ fn getCaptures(sema: *Sema, block: *Block, type_src: LazySrcLoc, extra_index: us
|
||||
/// Given an `InternPool.WipNamespaceType` or `InternPool.WipEnumType`, apply
|
||||
/// `sema.builtin_type_target_index` to it if necessary.
|
||||
fn wrapWipTy(sema: *Sema, wip_ty: anytype) @TypeOf(wip_ty) {
|
||||
const pt = sema.pt;
|
||||
if (sema.builtin_type_target_index == .none) return wip_ty;
|
||||
var new = wip_ty;
|
||||
new.index = sema.builtin_type_target_index;
|
||||
sema.pt.zcu.intern_pool.resolveBuiltinType(new.index, wip_ty.index);
|
||||
pt.zcu.intern_pool.resolveBuiltinType(pt.tid, new.index, wip_ty.index);
|
||||
return new;
|
||||
}
|
||||
|
||||
@@ -2740,7 +2741,7 @@ fn maybeRemoveOutdatedType(sema: *Sema, ty: InternPool.Index) !bool {
|
||||
if (!was_outdated) return false;
|
||||
_ = zcu.outdated_ready.swapRemove(decl_as_depender);
|
||||
zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, AnalUnit.wrap(.{ .decl = decl_index }));
|
||||
zcu.intern_pool.remove(ty);
|
||||
zcu.intern_pool.remove(pt.tid, ty);
|
||||
zcu.declPtr(decl_index).analysis = .dependency_failure;
|
||||
try zcu.markDependeeOutdated(.{ .decl_val = decl_index });
|
||||
return true;
|
||||
@@ -2819,7 +2820,7 @@ fn zirStructDecl(
|
||||
},
|
||||
.wip => |wip| wip,
|
||||
});
|
||||
errdefer wip_ty.cancel(ip);
|
||||
errdefer wip_ty.cancel(ip, pt.tid);
|
||||
|
||||
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
|
||||
block,
|
||||
@@ -3056,7 +3057,7 @@ fn zirEnumDecl(
|
||||
// have finished constructing the type and are in the process of analyzing it.
|
||||
var done = false;
|
||||
|
||||
errdefer if (!done) wip_ty.cancel(ip);
|
||||
errdefer if (!done) wip_ty.cancel(ip, pt.tid);
|
||||
|
||||
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
|
||||
block,
|
||||
@@ -3324,7 +3325,7 @@ fn zirUnionDecl(
|
||||
},
|
||||
.wip => |wip| wip,
|
||||
});
|
||||
errdefer wip_ty.cancel(ip);
|
||||
errdefer wip_ty.cancel(ip, pt.tid);
|
||||
|
||||
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
|
||||
block,
|
||||
@@ -3414,7 +3415,7 @@ fn zirOpaqueDecl(
|
||||
},
|
||||
.wip => |wip| wip,
|
||||
};
|
||||
errdefer wip_ty.cancel(ip);
|
||||
errdefer wip_ty.cancel(ip, pt.tid);
|
||||
|
||||
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
|
||||
block,
|
||||
@@ -21705,7 +21706,7 @@ fn zirReify(
|
||||
.existing => |ty| return Air.internedToRef(ty),
|
||||
.wip => |wip| wip,
|
||||
};
|
||||
errdefer wip_ty.cancel(ip);
|
||||
errdefer wip_ty.cancel(ip, pt.tid);
|
||||
|
||||
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
|
||||
block,
|
||||
@@ -21901,7 +21902,7 @@ fn reifyEnum(
|
||||
.wip => |wip| wip,
|
||||
.existing => |ty| return Air.internedToRef(ty),
|
||||
};
|
||||
errdefer wip_ty.cancel(ip);
|
||||
errdefer wip_ty.cancel(ip, pt.tid);
|
||||
|
||||
if (tag_ty.zigTypeTag(mod) != .Int) {
|
||||
return sema.fail(block, src, "Type.Enum.tag_type must be an integer type", .{});
|
||||
@@ -22052,7 +22053,7 @@ fn reifyUnion(
|
||||
.wip => |wip| wip,
|
||||
.existing => |ty| return Air.internedToRef(ty),
|
||||
};
|
||||
errdefer wip_ty.cancel(ip);
|
||||
errdefer wip_ty.cancel(ip, pt.tid);
|
||||
|
||||
const new_decl_index = try sema.createAnonymousDeclTypeNamed(
|
||||
block,
|
||||
@@ -22158,7 +22159,7 @@ fn reifyUnion(
|
||||
const enum_tag_ty = try sema.generateUnionTagTypeSimple(block, field_names.keys(), mod.declPtr(new_decl_index));
|
||||
break :tag_ty .{ enum_tag_ty, false };
|
||||
};
|
||||
errdefer if (!has_explicit_tag) ip.remove(enum_tag_ty); // remove generated tag type on error
|
||||
errdefer if (!has_explicit_tag) ip.remove(pt.tid, enum_tag_ty); // remove generated tag type on error
|
||||
|
||||
for (field_types) |field_ty_ip| {
|
||||
const field_ty = Type.fromInterned(field_ty_ip);
|
||||
@@ -22305,7 +22306,7 @@ fn reifyStruct(
|
||||
.wip => |wip| wip,
|
||||
.existing => |ty| return Air.internedToRef(ty),
|
||||
};
|
||||
errdefer wip_ty.cancel(ip);
|
||||
errdefer wip_ty.cancel(ip, pt.tid);
|
||||
|
||||
if (is_tuple) switch (layout) {
|
||||
.@"extern" => return sema.fail(block, src, "extern tuples are not supported", .{}),
|
||||
@@ -36924,7 +36925,7 @@ pub fn typeHasOnePossibleValue(sema: *Sema, ty: Type) CompileError!?Value {
|
||||
.none,
|
||||
=> unreachable,
|
||||
|
||||
_ => switch (ip.items.items(.tag)[@intFromEnum(ty.toIntern())]) {
|
||||
_ => switch (ty.toIntern().getTag(ip)) {
|
||||
.removed => unreachable,
|
||||
|
||||
.type_int_signed, // i0 handled above
|
||||
|
||||
@@ -3686,7 +3686,7 @@ pub fn resolveFields(ty: Type, pt: Zcu.PerThread) SemaError!void {
|
||||
.empty_struct => unreachable,
|
||||
.generic_poison => unreachable,
|
||||
|
||||
else => switch (ip.items.items(.tag)[@intFromEnum(ty_ip)]) {
|
||||
else => switch (ty_ip.getTag(ip)) {
|
||||
.type_struct,
|
||||
.type_struct_packed,
|
||||
.type_struct_packed_inits,
|
||||
|
||||
36
src/Zcu.zig
36
src/Zcu.zig
@@ -3071,42 +3071,6 @@ pub const SemaDeclResult = packed struct {
|
||||
invalidate_decl_ref: bool,
|
||||
};
|
||||
|
||||
pub fn semaAnonOwnerDecl(zcu: *Zcu, decl_index: Decl.Index) !SemaDeclResult {
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
|
||||
assert(decl.has_tv);
|
||||
assert(decl.owns_tv);
|
||||
|
||||
log.debug("semaAnonOwnerDecl '{d}'", .{@intFromEnum(decl_index)});
|
||||
|
||||
switch (decl.typeOf(zcu).zigTypeTag(zcu)) {
|
||||
.Fn => @panic("TODO: update fn instance"),
|
||||
.Type => {},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
// We are the owner Decl of a type, and we were marked as outdated. That means the *structure*
|
||||
// of this type changed; not just its namespace. Therefore, we need a new InternPool index.
|
||||
//
|
||||
// However, as soon as we make that, the context that created us will require re-analysis anyway
|
||||
// (as it depends on this Decl's value), meaning the `struct_decl` (or equivalent) instruction
|
||||
// will be analyzed again. Since Sema already needs to be able to reconstruct types like this,
|
||||
// why should we bother implementing it here too when the Sema logic will be hit right after?
|
||||
//
|
||||
// So instead, let's just mark this Decl as failed - so that any remaining Decls which genuinely
|
||||
// reference it (via `@This`) end up silently erroring too - and we'll let Sema make a new type
|
||||
// with a new Decl.
|
||||
//
|
||||
// Yes, this does mean that any type owner Decl has a constant value for its entire lifetime.
|
||||
zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, AnalUnit.wrap(.{ .decl = decl_index }));
|
||||
zcu.intern_pool.remove(decl.val.toIntern());
|
||||
decl.analysis = .dependency_failure;
|
||||
return .{
|
||||
.invalidate_decl_val = true,
|
||||
.invalidate_decl_ref = true,
|
||||
};
|
||||
}
|
||||
|
||||
pub const ImportFileResult = struct {
|
||||
file: *File,
|
||||
file_index: File.Index,
|
||||
|
||||
@@ -574,7 +574,7 @@ pub fn ensureFuncBodyAnalyzed(pt: Zcu.PerThread, maybe_coerced_func_index: Inter
|
||||
if (decl.val.ip_index != func_index) {
|
||||
try zcu.markDependeeOutdated(.{ .func_ies = func_index });
|
||||
ip.removeDependenciesForDepender(gpa, InternPool.AnalUnit.wrap(.{ .func = func_index }));
|
||||
ip.remove(func_index);
|
||||
ip.remove(pt.tid, func_index);
|
||||
@panic("TODO: remove orphaned function from binary");
|
||||
}
|
||||
|
||||
@@ -823,7 +823,7 @@ fn getFileRootStruct(
|
||||
.existing => unreachable, // we wouldn't be analysing the file root if this type existed
|
||||
.wip => |wip| wip,
|
||||
};
|
||||
errdefer wip_ty.cancel(ip);
|
||||
errdefer wip_ty.cancel(ip, pt.tid);
|
||||
|
||||
if (zcu.comp.debug_incremental) {
|
||||
try ip.addDependency(
|
||||
@@ -885,7 +885,7 @@ fn semaFileUpdate(pt: Zcu.PerThread, file_index: Zcu.File.Index, type_outdated:
|
||||
ip.removeDependenciesForDepender(zcu.gpa, InternPool.AnalUnit.wrap(.{
|
||||
.decl = file_root_decl,
|
||||
}));
|
||||
ip.remove(decl.val.toIntern());
|
||||
ip.remove(pt.tid, decl.val.toIntern());
|
||||
decl.val = undefined;
|
||||
_ = try pt.getFileRootStruct(file_root_decl, decl.src_namespace, file_index);
|
||||
return true;
|
||||
@@ -959,7 +959,7 @@ fn semaFile(pt: Zcu.PerThread, file_index: Zcu.File.Index) Zcu.SemaError!void {
|
||||
assert(file.zir_loaded);
|
||||
|
||||
const struct_ty = try pt.getFileRootStruct(new_decl_index, new_namespace_index, file_index);
|
||||
errdefer zcu.intern_pool.remove(struct_ty);
|
||||
errdefer zcu.intern_pool.remove(pt.tid, struct_ty);
|
||||
|
||||
switch (zcu.comp.cache_use) {
|
||||
.whole => |whole| if (whole.cache_manifest) |man| {
|
||||
@@ -1002,7 +1002,7 @@ fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult {
|
||||
|
||||
if (decl.zir_decl_index == .none and decl.owns_tv) {
|
||||
// We are re-analyzing an anonymous owner Decl (for a function or a namespace type).
|
||||
return zcu.semaAnonOwnerDecl(decl_index);
|
||||
return pt.semaAnonOwnerDecl(decl_index);
|
||||
}
|
||||
|
||||
log.debug("semaDecl '{d}'", .{@intFromEnum(decl_index)});
|
||||
@@ -1270,6 +1270,43 @@ fn semaDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult {
|
||||
return result;
|
||||
}
|
||||
|
||||
pub fn semaAnonOwnerDecl(pt: Zcu.PerThread, decl_index: Zcu.Decl.Index) !Zcu.SemaDeclResult {
|
||||
const zcu = pt.zcu;
|
||||
const decl = zcu.declPtr(decl_index);
|
||||
|
||||
assert(decl.has_tv);
|
||||
assert(decl.owns_tv);
|
||||
|
||||
log.debug("semaAnonOwnerDecl '{d}'", .{@intFromEnum(decl_index)});
|
||||
|
||||
switch (decl.typeOf(zcu).zigTypeTag(zcu)) {
|
||||
.Fn => @panic("TODO: update fn instance"),
|
||||
.Type => {},
|
||||
else => unreachable,
|
||||
}
|
||||
|
||||
// We are the owner Decl of a type, and we were marked as outdated. That means the *structure*
|
||||
// of this type changed; not just its namespace. Therefore, we need a new InternPool index.
|
||||
//
|
||||
// However, as soon as we make that, the context that created us will require re-analysis anyway
|
||||
// (as it depends on this Decl's value), meaning the `struct_decl` (or equivalent) instruction
|
||||
// will be analyzed again. Since Sema already needs to be able to reconstruct types like this,
|
||||
// why should we bother implementing it here too when the Sema logic will be hit right after?
|
||||
//
|
||||
// So instead, let's just mark this Decl as failed - so that any remaining Decls which genuinely
|
||||
// reference it (via `@This`) end up silently erroring too - and we'll let Sema make a new type
|
||||
// with a new Decl.
|
||||
//
|
||||
// Yes, this does mean that any type owner Decl has a constant value for its entire lifetime.
|
||||
zcu.intern_pool.removeDependenciesForDepender(zcu.gpa, InternPool.AnalUnit.wrap(.{ .decl = decl_index }));
|
||||
zcu.intern_pool.remove(pt.tid, decl.val.toIntern());
|
||||
decl.analysis = .dependency_failure;
|
||||
return .{
|
||||
.invalidate_decl_val = true,
|
||||
.invalidate_decl_ref = true,
|
||||
};
|
||||
}
|
||||
|
||||
pub fn embedFile(
|
||||
pt: Zcu.PerThread,
|
||||
cur_file: *Zcu.File,
|
||||
|
||||
Reference in New Issue
Block a user