Refactor constant pool
This commit is contained in:
parent
9135e95dbd
commit
146d90ccec
6 changed files with 257 additions and 500 deletions
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue