Skip to content

Commit

Permalink
LibJVM: Refactor the constant pool into a class
Browse files Browse the repository at this point in the history
The constant pool now has its own class ConstantPool.
Also the invidivual constants now have nicer accesors which lookup their
indices in the given constant pool.
  • Loading branch information
noahhaasis committed Dec 30, 2021
1 parent acea722 commit a6cad50
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 105 deletions.
6 changes: 6 additions & 0 deletions Userland/Libraries/LibJVM/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
set(SOURCES
ClassFileParser.cpp
)

serenity_lib(LibJVM jvm)
target_link_libraries(LibJVM LibCore)
10 changes: 9 additions & 1 deletion Userland/Libraries/LibJVM/ClassFile.h
Original file line number Diff line number Diff line change
Expand Up @@ -20,27 +20,35 @@ struct AttributeInfo {
u16 attribute_name_index;
u32 attribute_length;
u8 const* info;

ConstantPool::Utf8 attribute_name(ConstantPool const& constant_pool) const { return constant_pool.utf8_at(attribute_name_index); }
};

struct FieldInfo {
u16 access_flags;
u16 name_index;
u16 descriptor_index;
AK::FixedArray<AttributeInfo> attributes;

ConstantPool::Utf8 name(ConstantPool const& constant_pool) const { return constant_pool.utf8_at(name_index); }
ConstantPool::Utf8 descriptor(ConstantPool const& constant_pool) const { return constant_pool.utf8_at(descriptor_index); }
};

struct MethodInfo {
u16 access_flags;
u16 name_index;
u16 descriptor_index;
AK::FixedArray<AttributeInfo> attributes;

ConstantPool::Utf8 name(ConstantPool const& constant_pool) const { return constant_pool.utf8_at(name_index); }
ConstantPool::Utf8 descriptor(ConstantPool const& constant_pool) const { return constant_pool.utf8_at(descriptor_index); }
};

// https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html
struct ClassFile {
u16 minor_version;
u16 major_version;
FixedArray<ConstantPool::Constant> constant_pool;
ConstantPool constant_pool;
u16 access_flags;
ConstantPool::Class this_class;
AK::Optional<ConstantPool::Class> super_class;
Expand Down
19 changes: 8 additions & 11 deletions Userland/Libraries/LibJVM/ClassFileParser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,9 @@ void ClassFileParser::parse_constant_pool()
{
u16 constant_pool_count = read_u16() - 1;

auto constant_pool = FixedArray<ConstantPool::Constant>(constant_pool_count);
m_classfile->constant_pool = constant_pool;
for (auto& constant : m_classfile->constant_pool)
auto constants = FixedArray<ConstantPool::Constant>(constant_pool_count);
m_classfile->constant_pool.set_constants(constants);
for (auto& constant : m_classfile->constant_pool.constants())
constant = parse_constant_info();
}

Expand All @@ -58,8 +58,7 @@ ConstantPool::Constant ClassFileParser::parse_constant_info()
switch (tag) {
case ConstantPool::Constant::Tag::Class: {
ConstantPool::Class class_constant;
[[maybe_unused]] u16 name_index = read_u16() - 1;
// class_constant.name = (Constant const*)(m_classfile->constant_pool.span().offset_pointer(name_index));
class_constant.name_index = read_u16() - 1;
return ConstantPool::Constant(class_constant);
}
case ConstantPool::Constant::Tag::Utf8: {
Expand Down Expand Up @@ -93,22 +92,20 @@ ConstantPool::Constant ClassFileParser::parse_constant_info()

void ClassFileParser::parse_class_references()
{
m_classfile->this_class = (m_classfile->constant_pool.span().offset_pointer(read_u16() - 1))->as_class();
m_classfile->this_class = m_classfile->constant_pool.class_at(read_u16() - 1);
u16 super_class_index = read_u16() - 1;
if (super_class_index == 0)
m_classfile->super_class = {};
else
m_classfile->super_class = m_classfile->constant_pool.span().offset_pointer(super_class_index)->as_class();
m_classfile->super_class = m_classfile->constant_pool.class_at(super_class_index);
}

void ClassFileParser::parse_interfaces()
{
u16 interfaces_count = read_u16();
auto interfaces = FixedArray<ConstantPool::Class>(interfaces_count);
for (auto& interface : interfaces) {
u16 interface_index = read_u16() - 1;
interface = m_classfile->constant_pool.span().offset_pointer(interface_index)->as_class();
}
for (auto& interface : interfaces)
interface = m_classfile->constant_pool.class_at(read_u16() - 1);

m_classfile->interfaces = interfaces;
}
Expand Down
237 changes: 144 additions & 93 deletions Userland/Libraries/LibJVM/ConstantPool.h
Original file line number Diff line number Diff line change
Expand Up @@ -11,130 +11,181 @@
namespace JVM {

// https://docs.oracle.com/javase/specs/jvms/se7/html/jvms-4.html#jvms-4.4
class ConstantPool {
public:
struct Utf8 {
u32 length;
u8 const* bytes;
};

namespace ConstantPool {

struct Utf8 {
u32 length;
u8 const* bytes;
};

struct Class {
u16 name_and_type_index;
};
struct NameAndType {
u16 name_index;
u16 descriptor_index;

struct Integer {
u32 bytes;
};
Utf8 name(ConstantPool const& constant_pool) const { return constant_pool.utf8_at(name_index); }
Utf8 descriptor(ConstantPool const& constant_pool) const { return constant_pool.utf8_at(descriptor_index); }
};

struct NameAndType {
u16 name_index;
u16 descriptor_index;
};
struct Class {
u16 name_index;

struct Methodref {
u16 class_index;
u16 name_and_type_index;
};
Utf8 name(ConstantPool const& constant_pool) const { return constant_pool.utf8_at(name_index); }
};

class Constant {
public:
enum Tag : u8 {
Class = 7,
Fieldref = 9,
Methodref = 10,
InterfaceMethodref = 11,
String = 8,
Integer = 3,
Float = 4,
Long = 5,
Double = 6,
NameAndType = 12,
Utf8 = 1,
MethodHandle = 15,
MethodType = 16,
Invokedynamic = 18,
struct Integer {
u32 bytes;
};

Constant() {};
struct Methodref {
u16 class_index;
u16 name_and_type_index;

Constant(struct Utf8 value)
: m_tag(Tag::Utf8)
{
m_value.as_utf8 = value;
};
Class class_info(ConstantPool const& constant_pool) const
{
return constant_pool.class_at(class_index);
}

Constant(struct Class value)
: m_tag(Tag::Class)
{
m_value.as_class = value;
NameAndType name_and_type(ConstantPool const& constant_pool) const
{
return constant_pool.name_and_type_at(name_and_type_index);
}
};

Constant(struct Integer value)
: m_tag(Tag::Integer)
{
m_value.as_integer = value;
class Constant {
public:
enum Tag : u8 {
Class = 7,
Fieldref = 9,
Methodref = 10,
InterfaceMethodref = 11,
String = 8,
Integer = 3,
Float = 4,
Long = 5,
Double = 6,
NameAndType = 12,
Utf8 = 1,
MethodHandle = 15,
MethodType = 16,
Invokedynamic = 18,
};

Constant() {};

Constant(struct Utf8 value)
: m_tag(Tag::Utf8)
{
m_value.as_utf8 = value;
};

Constant(struct Class value)
: m_tag(Tag::Class)
{
m_value.as_class = value;
};

Constant(struct Integer value)
: m_tag(Tag::Integer)
{
m_value.as_integer = value;
};

Constant(struct NameAndType value)
: m_tag(Tag::NameAndType)
{
m_value.as_name_and_type = value;
};

Constant(struct Methodref value)
: m_tag(Tag::Methodref)
{
m_value.as_methodref = value;
};

struct Utf8 as_utf8() const
{
VERIFY(is_utf8());
return m_value.as_utf8;
}

struct Class as_class() const
{
VERIFY(is_class());
return m_value.as_class;
}

struct Integer as_integer() const
{
VERIFY(is_integer());
return m_value.as_integer;
}

struct NameAndType as_name_and_type() const
{
VERIFY(is_name_and_type());
return m_value.as_name_and_type;
}

struct Methodref as_methodref() const
{
VERIFY(is_methodref());
return m_value.as_methodref;
}

bool is_utf8() const { return m_tag == Tag::Utf8; }
bool is_class() const { return m_tag == Tag::Class; }
bool is_integer() const { return m_tag == Tag::Integer; }
bool is_name_and_type() const { return m_tag == Tag::NameAndType; }
bool is_methodref() const { return m_tag == Tag::Methodref; }

private:
Tag m_tag;
union {
struct Utf8 as_utf8;
struct Class as_class;
struct Integer as_integer;
struct NameAndType as_name_and_type;
struct Methodref as_methodref;
} m_value;
};

Constant(struct NameAndType value)
: m_tag(Tag::NameAndType)
{
m_value.as_name_and_type = value;
};
ConstantPool() = default;

Constant(struct Methodref value)
: m_tag(Tag::Methodref)
{
m_value.as_methodref = value;
};
FixedArray<Constant>& constants() { return m_constants; }
void set_constants(FixedArray<Constant> constants) { m_constants = constants; }

struct Utf8 as_utf8() const
Utf8 utf8_at(unsigned index) const
{
VERIFY(is_utf8());
return m_value.as_utf8;
VERIFY(index < m_constants.size());
return m_constants[index].as_utf8();
}

struct Class as_class() const
Class class_at(unsigned index) const
{
VERIFY(is_class());
return m_value.as_class;
VERIFY(index < m_constants.size());
return m_constants[index].as_class();
}

struct Integer as_integer() const
Integer integer_at(unsigned index) const
{
VERIFY(is_integer());
return m_value.as_integer;
VERIFY(index < m_constants.size());
return m_constants[index].as_integer();
}

struct NameAndType as_name_and_type() const
NameAndType name_and_type_at(unsigned index) const
{
VERIFY(is_name_and_type());
return m_value.as_name_and_type;
VERIFY(index < m_constants.size());
return m_constants[index].as_name_and_type();
}

struct Methodref as_methodref() const
Methodref methodref_at(unsigned index) const
{
VERIFY(is_methodref());
return m_value.as_methodref;
VERIFY(index < m_constants.size());
return m_constants[index].as_methodref();
}

bool is_utf8() const { return m_tag == Tag::Utf8; }
bool is_class() const { return m_tag == Tag::Class; }
bool is_integer() const { return m_tag == Tag::Integer; }
bool is_name_and_type() const { return m_tag == Tag::NameAndType; }
bool is_methodref() const { return m_tag == Tag::Methodref; }

private:
Tag m_tag;
union {
struct Utf8 as_utf8;
struct Class as_class;
struct Integer as_integer;
struct NameAndType as_name_and_type;
struct Methodref as_methodref;
} m_value;
FixedArray<Constant> m_constants;
};

}

}

0 comments on commit a6cad50

Please sign in to comment.