Refactor constant pool

This commit is contained in:
ktkk 2026-07-05 23:29:37 +02:00
parent 9135e95dbd
commit 146d90ccec
6 changed files with 257 additions and 500 deletions

View file

@ -5,6 +5,10 @@ const AttributeInfo = Class.AttributeInfo;
const ParseError = Class.ParseError;
const ResolveError = Class.ResolveError;
constant_pool: []?Info,
const Self = @This();
pub const Info = union(Info.Tag) {
class: Info.Class,
field_ref: FieldRef,
@ -54,14 +58,8 @@ pub const Info = union(Info.Tag) {
pub const Class = struct {
name_index: u16,
const Self = @This();
pub fn name(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const name_index = self.name_index - 1;
if (name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_index];
if (cp_info == null or @as(Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn name(self: *const Info.Class, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.name_index, .utf8);
}
};
@ -69,22 +67,12 @@ pub const Info = union(Info.Tag) {
class_index: u16,
name_and_type_index: u16,
const Self = @This();
pub fn class(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const class_index = self.class_index - 1;
if (class_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[class_index];
if (cp_info == null or @as(Tag, cp_info.?) != .class) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn class(self: *const FieldRef, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.class_index, .class);
}
pub fn nameAndType(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const name_and_type_index = self.name_and_type_index - 1;
if (name_and_type_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_and_type_index];
if (cp_info == null or @as(Tag, cp_info.?) != .name_and_type) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn nameAndType(self: *const FieldRef, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.name_and_type_index, .name_and_type);
}
};
@ -92,22 +80,12 @@ pub const Info = union(Info.Tag) {
class_index: u16,
name_and_type_index: u16,
const Self = @This();
pub fn class(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const class_index = self.class_index - 1;
if (class_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[class_index];
if (cp_info == null or @as(Tag, cp_info.?) != .class) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn class(self: *const MethodRef, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.class_index, .class);
}
pub fn nameAndType(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const name_and_type_index = self.name_and_type_index - 1;
if (name_and_type_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_and_type_index];
if (cp_info == null or @as(Tag, cp_info.?) != .name_and_type) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn nameAndType(self: *const MethodRef, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.name_and_type_index, .name_and_type);
}
};
@ -115,36 +93,20 @@ pub const Info = union(Info.Tag) {
class_index: u16,
name_and_type_index: u16,
const Self = @This();
pub fn class(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const class_index = self.class_index - 1;
if (class_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[class_index];
if (cp_info == null or @as(Tag, cp_info.?) != .class) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn class(self: *const InterfaceMethodRef, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.class_index, .class);
}
pub fn nameAndType(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const name_and_type_index = self.name_and_type_index - 1;
if (name_and_type_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_and_type_index];
if (cp_info == null or @as(Tag, cp_info.?) != .name_and_type) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn nameAndType(self: *const InterfaceMethodRef, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.name_and_type_index, .name_and_type);
}
};
pub const String = struct {
string_index: u16,
const Self = @This();
pub fn string(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const string_index = self.string_index - 1;
if (string_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[string_index];
if (cp_info == null or @as(Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn string(self: *const String, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.string_index, .utf8);
}
};
@ -170,22 +132,12 @@ pub const Info = union(Info.Tag) {
name_index: u16,
descriptor_index: u16,
const Self = @This();
pub fn name(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const name_index = self.name_index - 1;
if (name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_index];
if (cp_info == null or @as(Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn name(self: *const NameAndType, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.name_index, .utf8);
}
pub fn descriptor(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const descriptor_index = self.descriptor_index - 1;
if (descriptor_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[descriptor_index];
if (cp_info == null or @as(Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn descriptor(self: *const NameAndType, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.descriptor_index, .utf8);
}
};
@ -197,8 +149,6 @@ pub const Info = union(Info.Tag) {
reference_kind: Kind,
reference_index: u16,
const Self = @This();
pub const Kind = enum(u8) {
get_field = 1,
get_static = 2,
@ -211,22 +161,20 @@ pub const Info = union(Info.Tag) {
invoke_interface = 9,
};
pub fn reference(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const reference_index = self.reference_index - 1;
if (reference_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[reference_index];
pub fn reference(self: *const MethodHandle, constant_pool: Self) ResolveError!Info {
const info = try constant_pool.get(self.reference_index);
return switch (self.reference_kind) {
.get_field, .get_static, .put_field, .put_static => blk: {
if (cp_info == null or @as(Tag, cp_info.?) != .field_ref) break :blk ResolveError.InvalidConstantType;
break :blk cp_info.?;
if (@as(Tag, info) != .field_ref) break :blk ResolveError.InvalidConstantType;
break :blk info;
},
.invoke_virtual, .invoke_static, .invoke_special, .new_invoke_special => blk: {
if (cp_info == null or @as(Tag, cp_info.?) != .method_ref) break :blk ResolveError.InvalidConstantType;
break :blk cp_info.?;
if (@as(Tag, info) != .method_ref) break :blk ResolveError.InvalidConstantType;
break :blk info;
},
.invoke_interface => blk: {
if (cp_info == null or @as(Tag, cp_info.?) != .interface_method_ref) break :blk ResolveError.InvalidConstantType;
break :blk cp_info.?;
if (@as(Tag, info) != .interface_method_ref) break :blk ResolveError.InvalidConstantType;
break :blk info;
},
};
}
@ -235,14 +183,8 @@ pub const Info = union(Info.Tag) {
pub const MethodType = struct {
descriptor_index: u16,
const Self = @This();
pub fn descriptor(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const descriptor_index = self.descriptor_index - 1;
if (descriptor_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[descriptor_index];
if (cp_info == null or @as(Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn descriptor(self: *const MethodType, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.descriptor_index, .utf8);
}
};
@ -250,14 +192,8 @@ pub const Info = union(Info.Tag) {
bootstrap_method_attr_index: u16,
name_and_type_index: u16,
const Self = @This();
pub fn nameAndType(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const name_and_type_index = self.name_and_type_index - 1;
if (name_and_type_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_and_type_index];
if (cp_info == null or @as(Tag, cp_info.?) != .name_and_type) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn nameAndType(self: *const Dynamic, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.name_and_type_index, .name_and_type);
}
};
@ -265,42 +201,24 @@ pub const Info = union(Info.Tag) {
bootstrap_method_attr_index: u16,
name_and_type_index: u16,
const Self = @This();
pub fn nameAndType(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const name_and_type_index = self.name_and_type_index - 1;
if (name_and_type_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_and_type_index];
if (cp_info == null or @as(Tag, cp_info.?) != .name_and_type) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn nameAndType(self: *const InvokeDynamic, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.name_and_type_index, .name_and_type);
}
};
pub const Module = struct {
name_index: u16,
const Self = @This();
pub fn name(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const name_index = self.name_index - 1;
if (name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_index];
if (cp_info == null or @as(Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn name(self: *const Module, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.name_index, .utf8);
}
};
pub const Package = struct {
name_index: u16,
const Self = @This();
pub fn name(self: *const Self, constant_pool: []const ?Info) ResolveError!Info {
const name_index = self.name_index - 1;
if (name_index >= constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const cp_info = constant_pool[name_index];
if (cp_info == null or @as(Tag, cp_info.?) != .utf8) return ResolveError.InvalidConstantType;
return cp_info.?;
pub fn name(self: *const Package, constant_pool: Self) ResolveError!Info {
return constant_pool.getTag(self.name_index, .utf8);
}
};
@ -450,7 +368,7 @@ pub const Info = union(Info.Tag) {
w: *std.Io.Writer,
depth: usize,
indent: u8,
constant_pool: []const ?Info,
constant_pool: Self,
) std.Io.Writer.Error!void {
try w.splatByteAll(' ', depth * indent);
try w.print("constant_value_type: {s}\n", .{ @tagName(self.*) });
@ -579,3 +497,71 @@ pub const Info = union(Info.Tag) {
}
}
};
pub fn parse(input: *std.Io.Reader, allocator: std.mem.Allocator) ParseError!Self {
const constant_pool_size = try input.takeInt(u16, .big);
const constant_pool = try allocator.alloc(?Info, constant_pool_size - 1);
errdefer allocator.free(constant_pool);
var i: usize = 0;
while (i < constant_pool_size - 1) {
defer i += 1;
const info: Info = try .parse(input, allocator);
constant_pool[i] = info;
switch (info) {
.long, .double => {
i += 1;
constant_pool[i] = null;
},
else => {},
}
}
return .{
.constant_pool = constant_pool,
};
}
pub fn deinit(self: *Self, allocator: std.mem.Allocator) void {
for (self.constant_pool) |*info| {
if (info.*) |*c| c.deinit(allocator);
}
allocator.free(self.constant_pool);
}
pub fn get(self: *const Self, index: u16) ResolveError!Info {
const actual_index = index - 1;
if (actual_index >= self.constant_pool.len) return ResolveError.InvalidConstantPoolIndex;
const info = self.constant_pool[actual_index];
if (info == null) return ResolveError.InvalidConstantType;
return info.?;
}
pub fn getOptional(self: *const Self, index: u16) ResolveError!?Info {
if (index == 0) return null;
return self.get(index);
}
pub fn getTag(self: *const Self, index: u16, expected_tag: Info.Tag) ResolveError!Info {
const info = try self.get(index);
if (@as(Info.Tag, info) != expected_tag) return ResolveError.InvalidConstantType;
return info;
}
pub fn getTagOptional(self: *const Self, index: u16, expected_tag: Info.Tag) ResolveError!?Info {
if (index == 0) return null;
return try self.getTag(index, expected_tag);
}
pub fn getLoadable(self: *const Self, index: u16) ResolveError!Info {
const info = try self.get(index);
if (!@as(Info.Tag, info).loadable()) return ResolveError.InvalidConstantType;
return info;
}
pub fn getLoadableOptional(self: *const Self, index: u16) ResolveError!?Info {
if (index == 0) return null;
return self.getLoadable(index);
}