This commit is contained in:
Zack Buhman 2025-01-11 16:25:10 -06:00
parent ec525bbfbc
commit 025013ba3a
5 changed files with 290 additions and 245 deletions

View File

@ -20,9 +20,7 @@
static int field_info_field_size(struct class_file * class_file, struct field_info * field_info) static int field_info_field_size(struct class_file * class_file, struct field_info * field_info)
{ {
struct constant * field_descriptor_constant = &class_file->constant_pool[field_info->descriptor_index - 1]; struct constant * field_descriptor_constant = &class_file->constant_pool[field_info->descriptor_index - 1];
#ifdef DEBUG
assert(field_descriptor_constant->tag == CONSTANT_Utf8); assert(field_descriptor_constant->tag == CONSTANT_Utf8);
#endif
return field_size(field_descriptor_constant->utf8.bytes[0]); return field_size(field_descriptor_constant->utf8.bytes[0]);
} }
@ -86,6 +84,7 @@ static int add_superclass_instance_fields(int class_hash_table_length,
struct field_entry * field_entry = malloc_class_arena((sizeof (struct field_entry))); struct field_entry * field_entry = malloc_class_arena((sizeof (struct field_entry)));
field_entry->instance_index = instance_index; field_entry->instance_index = instance_index;
field_entry->field_info = field_info; field_entry->field_info = field_info;
field_entry->class_entry = class_entry;
struct constant * name_constant = &class_entry->class_file->constant_pool[field_info->name_index - 1]; struct constant * name_constant = &class_entry->class_file->constant_pool[field_info->name_index - 1];
assert(name_constant->tag == CONSTANT_Utf8); assert(name_constant->tag == CONSTANT_Utf8);
@ -126,6 +125,7 @@ static int32_t class_resolver_create_fields_hash_table(int class_hash_table_leng
struct field_entry * field_entry = malloc_class_arena((sizeof (struct field_entry))); struct field_entry * field_entry = malloc_class_arena((sizeof (struct field_entry)));
field_entry->static_index = static_index; field_entry->static_index = static_index;
field_entry->field_info = field_info; field_entry->field_info = field_info;
field_entry->class_entry = class_entry;
static_index += field_info_field_size(class_entry->class_file, field_info); static_index += field_info_field_size(class_entry->class_file, field_info);
struct constant * name_constant = &class_entry->class_file->constant_pool[field_info->name_index - 1]; struct constant * name_constant = &class_entry->class_file->constant_pool[field_info->name_index - 1];
@ -326,55 +326,87 @@ struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash
return _class_entry; return _class_entry;
} }
struct field_entry * class_resolver_lookup_field(int fields_hash_table_length, static struct field_entry * resolve_field_entry(int fields_hash_table_length,
struct hash_table_entry * fields_hash_table, struct hash_table_entry * fields_hash_table,
const uint8_t * field_name, const uint8_t * field_name,
int field_name_length) int field_name_length)
{ {
debugf("class_resolver_lookup_field: "); debugf("resolve_field_entry: ");
for (int i = 0; i < field_name_length; i++) { debugc(field_name[i]); } debug_print__string(field_name, field_name_length);
debugc('\n'); debugc('\n');
struct hash_table_entry * e = hash_table_find(fields_hash_table_length, struct hash_table_entry * e = hash_table_find(fields_hash_table_length,
fields_hash_table, fields_hash_table,
field_name, field_name,
field_name_length); field_name_length);
assert(e != nullptr); if (e == nullptr)
debugf("%p\n", e->value); return nullptr;
else
return (struct field_entry *)e->value; return (struct field_entry *)e->value;
} }
struct field_entry * class_resolver_lookup_field_from_fieldref_index(int fields_hash_table_length, struct field_entry * resolve_field_entry_from_superclasses(int class_hash_table_length,
struct hash_table_entry * fields_hash_table, struct hash_table_entry * class_hash_table,
struct class_entry * class_entry, struct class_entry * class_entry,
int fieldref_index) struct constant * field_name_constant)
{ {
if (class_entry->attribute_entry[fieldref_index - 1].field_entry != nullptr) { while (true) {
debugf("class_resolver_lookup_field_from_fieldref_index %d: [cached]\n", fieldref_index); struct field_entry * field_entry = resolve_field_entry(class_entry->fields.length,
return class_entry->attribute_entry[fieldref_index - 1].field_entry; class_entry->fields.entry,
}
struct constant * fieldref_constant = &class_entry->class_file->constant_pool[fieldref_index - 1];
#ifdef DEBUG
assert(fieldref_constant->tag == CONSTANT_Fieldref);
#endif
struct constant * nameandtype_constant = &class_entry->class_file->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1];
#ifdef DEBUG
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
#endif
struct constant * field_name_constant = &class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];
#ifdef DEBUG
assert(field_name_constant->tag == CONSTANT_Utf8);
#endif
struct field_entry * field_entry = class_resolver_lookup_field(fields_hash_table_length,
fields_hash_table,
field_name_constant->utf8.bytes, field_name_constant->utf8.bytes,
field_name_constant->utf8.length); field_name_constant->utf8.length);
if (field_entry != nullptr)
return field_entry;
if (class_entry->class_file->super_class == 0)
break;
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->super_class - 1];
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
// lookup the field from the superclass
class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length,
class_hash_table,
class_entry,
class_entry->class_file->super_class);
assert(class_entry != nullptr);
}
return nullptr;
}
struct field_entry * class_resolver_lookup_field_from_fieldref_index(int class_hash_table_length,
struct hash_table_entry * class_hash_table,
struct class_entry * origin_class_entry,
struct class_entry * objectref_class_entry,
int fieldref_index)
{
if (origin_class_entry->attribute_entry[fieldref_index - 1].field_entry != nullptr) {
debugf("class_resolver_lookup_field_from_fieldref_index %d: [cached]\n", fieldref_index);
return origin_class_entry->attribute_entry[fieldref_index - 1].field_entry;
}
struct constant * fieldref_constant = &origin_class_entry->class_file->constant_pool[fieldref_index - 1];
assert(fieldref_constant->tag == CONSTANT_Fieldref);
struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1];
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
struct constant * field_name_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];
assert(field_name_constant->tag == CONSTANT_Utf8);
struct field_entry * field_entry = resolve_field_entry_from_superclasses(class_hash_table_length,
class_hash_table,
objectref_class_entry,
field_name_constant);
assert(field_entry != nullptr);
if ((field_entry->field_info->access_flags & FIELD_ACC_STATIC) == 0) {
assert(field_entry->class_entry == objectref_class_entry);
}
// cache the result // cache the result
class_entry->attribute_entry[fieldref_index - 1].field_entry = field_entry; origin_class_entry->attribute_entry[fieldref_index - 1].field_entry = field_entry;
return field_entry; return field_entry;
} }
@ -404,60 +436,67 @@ struct method_info * class_resolver_lookup_method(int methods_hash_table_length,
return (struct method_info *)e->value; return (struct method_info *)e->value;
} }
struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(int class_hash_table_length, static struct Code_attribute * resolve_code_attribute(struct class_entry * class_entry,
struct hash_table_entry * class_hash_table, struct method_info * method_info)
int32_t interfacemethodref_index,
struct class_entry * objectref_class_entry,
struct class_entry * origin_class_entry)
{ {
struct constant * interfacemethodref_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_index - 1]; if ((method_info->access_flags & METHOD_ACC_NATIVE) != 0) {
assert(interfacemethodref_constant->tag == CONSTANT_InterfaceMethodref || interfacemethodref_constant->tag == CONSTANT_Methodref); return nullptr;
struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_constant->interfacemethodref.name_and_type_index - 1]; }
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
struct constant * method_name_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];
assert(method_name_constant->tag == CONSTANT_Utf8);
struct constant * method_descriptor_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
assert(method_descriptor_constant->tag == CONSTANT_Utf8);
struct class_entry * class_entry = objectref_class_entry;
while (true) {
struct method_info * method_info = class_resolver_lookup_method(class_entry->methods.length,
class_entry->methods.entry,
method_name_constant->utf8.bytes,
method_name_constant->utf8.length,
method_descriptor_constant->utf8.bytes,
method_descriptor_constant->utf8.length);
if (method_info != nullptr) {
debugf("method resolved:\n");
debugf(" class: ");
debug_print__class_file__class_name(class_entry->class_file);
debugf("\n method: ");
debug_print__method_info__method_name(class_entry->class_file, method_info);
debugc('\n');
int code_index = find_code_name_index(class_entry->class_file); int code_index = find_code_name_index(class_entry->class_file);
assert(code_index != 0); assert(code_index != 0);
struct attribute_info * attribute = find_attribute(code_index, struct attribute_info * attribute = find_attribute(code_index,
method_info->attributes_count, method_info->attributes_count,
method_info->attributes); method_info->attributes);
if ((method_info->access_flags & METHOD_ACC_NATIVE) != 0) {
return (struct method_entry){
.class_entry = class_entry,
.method_info = method_info,
.code_attribute = nullptr,
};
} else {
assert(attribute != nullptr); assert(attribute != nullptr);
return (struct method_entry){ return attribute->code;
.class_entry = class_entry,
.method_info = method_info,
.code_attribute = attribute->code,
};
} }
static void resolve_method_entry(struct class_entry * class_entry,
struct constant * method_name_constant,
struct constant * method_descriptor_constant,
struct method_entry * method_entry)
{
struct method_info * method_info = class_resolver_lookup_method(class_entry->methods.length,
class_entry->methods.entry,
method_name_constant->utf8.bytes,
method_name_constant->utf8.length,
method_descriptor_constant->utf8.bytes,
method_descriptor_constant->utf8.length);
if (method_info == nullptr)
return;
method_entry->class_entry = class_entry;
method_entry->method_info = method_info;
method_entry->code_attribute = resolve_code_attribute(class_entry, method_info);
debugf("method resolved:\n");
debugf(" class: ");
debug_print__class_file__class_name(class_entry->class_file);
debugf("\n method: ");
debug_print__method_info__method_name(class_entry->class_file, method_info);
debugc('\n');
} }
static void resolve_method_entry_from_superclasses(int class_hash_table_length,
struct hash_table_entry * class_hash_table,
struct class_entry * class_entry,
struct constant * method_name_constant,
struct constant * method_descriptor_constant,
struct method_entry * method_entry)
{
assert(method_entry != nullptr);
method_entry->method_info = nullptr;
while (true) {
resolve_method_entry(class_entry,
method_name_constant,
method_descriptor_constant,
method_entry);
if (method_entry->method_info != nullptr)
break;
if (class_entry->class_file->super_class == 0) if (class_entry->class_file->super_class == 0)
break; break;
@ -465,8 +504,6 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i
assert(class_constant->tag == CONSTANT_Class); assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8); assert(class_name_constant->tag == CONSTANT_Utf8);
debug_print__constant__utf8_string(class_name_constant);
debugf("\n");
// lookup the method from the superclass // lookup the method from the superclass
class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length, class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length,
@ -475,19 +512,44 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i
class_entry->class_file->super_class); class_entry->class_file->super_class);
assert(class_entry != nullptr); assert(class_entry != nullptr);
} }
print__class_file__class_name(objectref_class_entry->class_file);
printc('\n');
assert(!"interfacemethodref method does not exist");
} }
struct method_entry * class_resolver_lookup_method_from_methodref_index(int class_hash_table_length, struct method_entry class_resolver_lookup_method_from_objectref_class(int class_hash_table_length,
struct hash_table_entry * class_hash_table,
int32_t methodref_index,
struct class_entry * objectref_class_entry,
struct class_entry * origin_class_entry)
{
struct constant * methodref_constant = &origin_class_entry->class_file->constant_pool[methodref_index - 1];
assert(methodref_constant->tag == CONSTANT_InterfaceMethodref || methodref_constant->tag == CONSTANT_Methodref);
struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[methodref_constant->methodref.name_and_type_index - 1];
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
struct constant * method_name_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];
assert(method_name_constant->tag == CONSTANT_Utf8);
struct constant * method_descriptor_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
assert(method_descriptor_constant->tag == CONSTANT_Utf8);
struct class_entry * class_entry = objectref_class_entry;
struct method_entry method_entry;
resolve_method_entry_from_superclasses(class_hash_table_length,
class_hash_table,
class_entry,
method_name_constant,
method_descriptor_constant,
&method_entry);
return method_entry;
}
struct method_entry * class_resolver_lookup_method_from_origin_class(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
int32_t methodref_index, int32_t methodref_index,
struct class_entry * origin_class_entry) struct class_entry * origin_class_entry)
{ {
if (origin_class_entry->attribute_entry[methodref_index - 1].method_entry != nullptr) { if (origin_class_entry->attribute_entry[methodref_index - 1].method_entry != nullptr) {
debugf("class_resolver_lookup_method_from_methodref_index %d: [cached]\n", methodref_index); debugf("class_resolver_lookup_method_from_origin_class %d: [cached]\n", methodref_index);
return origin_class_entry->attribute_entry[methodref_index - 1].method_entry; return origin_class_entry->attribute_entry[methodref_index - 1].method_entry;
} }
@ -505,61 +567,20 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas
origin_class_entry, origin_class_entry,
methodref_constant->methodref.class_index); methodref_constant->methodref.class_index);
while (true) {
struct method_info * method_info = class_resolver_lookup_method(class_entry->methods.length,
class_entry->methods.entry,
method_name_constant->utf8.bytes,
method_name_constant->utf8.length,
method_descriptor_constant->utf8.bytes,
method_descriptor_constant->utf8.length);
if (method_info != nullptr) {
// cache the result
debugf("method resolved:\n");
debugf(" class: ");
debug_print__class_file__class_name(class_entry->class_file);
debugf("\n method: ");
debug_print__method_info__method_name(class_entry->class_file, method_info);
debugc('\n');
struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry))); struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry)));
method_entry->class_entry = class_entry;
method_entry->method_info = method_info;
int code_index = find_code_name_index(class_entry->class_file);
assert(code_index != 0);
struct attribute_info * attribute = find_attribute(code_index,
method_info->attributes_count,
method_info->attributes);
if ((method_info->access_flags & METHOD_ACC_NATIVE) != 0) {
assert(attribute == nullptr);
method_entry->code_attribute = nullptr;
} else {
assert(attribute != nullptr);
method_entry->code_attribute = attribute->code;
}
origin_class_entry->attribute_entry[methodref_index - 1].method_entry = method_entry; resolve_method_entry_from_superclasses(class_hash_table_length,
return method_entry;
}
if (class_entry->class_file->super_class == 0)
break;
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->super_class - 1];
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
debug_print__constant__utf8_string(class_name_constant);
debugf("\n");
// lookup the method from the superclass
class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length,
class_hash_table, class_hash_table,
class_entry, class_entry,
class_entry->class_file->super_class); method_name_constant,
assert(class_entry != nullptr); method_descriptor_constant,
} method_entry);
assert(!"methodref method does not exist"); assert(method_entry->method_info != nullptr);
origin_class_entry->attribute_entry[methodref_index - 1].method_entry = method_entry;
return method_entry;
} }
struct method_entry class_resolver_lookup_method_from_method_name_method_descriptor(struct class_entry * class_entry, struct method_entry class_resolver_lookup_method_from_method_name_method_descriptor(struct class_entry * class_entry,

View File

@ -26,6 +26,7 @@ union attribute_entry {
}; };
struct field_entry { struct field_entry {
struct class_entry * class_entry;
struct field_info * field_info; struct field_info * field_info;
union { union {
int32_t instance_index; int32_t instance_index;
@ -63,15 +64,17 @@ struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
struct class_entry * class_entry, struct class_entry * class_entry,
int32_t class_index); int32_t class_index);
struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(int class_hash_table_length,
struct method_entry class_resolver_lookup_method_from_objectref_class(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
int32_t interfacemethodref_index, int32_t methodref_index,
struct class_entry * objectref_class_entry, struct class_entry * objectref_class_entry,
struct class_entry * origin_class_entry); struct class_entry * origin_class_entry);
struct method_entry * class_resolver_lookup_method_from_methodref_index(int class_hash_table_length, struct method_entry * class_resolver_lookup_method_from_origin_class(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
int32_t methodref_index, int32_t methodref_index,
struct class_entry * origin_class_entry); struct class_entry * origin_class_entry);
struct method_entry class_resolver_lookup_method_from_method_name_method_descriptor(struct class_entry * class_entry, struct method_entry class_resolver_lookup_method_from_method_name_method_descriptor(struct class_entry * class_entry,
const uint8_t * method_name, const uint8_t * method_name,
int method_name_length, int method_name_length,

View File

@ -734,20 +734,20 @@ void op_fsub(struct vm * vm)
void op_getfield(struct vm * vm, uint32_t index) void op_getfield(struct vm * vm, uint32_t index)
{ {
struct class_entry * class_entry;
struct field_entry * field_entry;
struct constant * field_descriptor_constant;
class_entry_field_entry_from_constant_index(vm, index,
&class_entry,
&field_entry,
&field_descriptor_constant);
debugf("getfield instance_index %d\n", field_entry->instance_index);
struct objectref * objectref = operand_stack_pop_ref(vm->current_frame); struct objectref * objectref = operand_stack_pop_ref(vm->current_frame);
if (objectref == nullptr) if (objectref == nullptr)
return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException"));
struct constant * field_descriptor_constant;
struct field_entry * field_entry = field_entry_from_constant_index(vm->class_hash_table.length,
vm->class_hash_table.entry,
vm->current_frame->class_entry,
objectref->class_entry,
index,
&field_descriptor_constant);
debugf("getfield instance_index %d\n", field_entry->instance_index);
switch (field_descriptor_constant->utf8.bytes[0]) { switch (field_descriptor_constant->utf8.bytes[0]) {
case 'B': [[fallthrough]]; case 'B': [[fallthrough]];
case 'C': [[fallthrough]]; case 'C': [[fallthrough]];
@ -778,12 +778,12 @@ void op_getfield(struct vm * vm, uint32_t index)
void op_getstatic(struct vm * vm, uint32_t index) void op_getstatic(struct vm * vm, uint32_t index)
{ {
struct class_entry * class_entry;
struct field_entry * field_entry;
struct constant * field_descriptor_constant; struct constant * field_descriptor_constant;
class_entry_field_entry_from_constant_index(vm, index, struct field_entry * field_entry = field_entry_from_constant_index(vm->class_hash_table.length,
&class_entry, vm->class_hash_table.entry,
&field_entry, vm->current_frame->class_entry,
vm->current_frame->class_entry,
index,
&field_descriptor_constant); &field_descriptor_constant);
/* On successful resolution of the field, the class or interface that /* On successful resolution of the field, the class or interface that
@ -1184,13 +1184,12 @@ void op_invokeinterface(struct vm * vm, uint32_t index, uint32_t count)
struct objectref * objectref = operand_stack_peek_ref(vm->current_frame, count); struct objectref * objectref = operand_stack_peek_ref(vm->current_frame, count);
if (objectref == nullptr) if (objectref == nullptr)
return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException"));
struct class_entry * class_entry = objectref->class_entry;
struct method_entry method_entry = struct method_entry method_entry =
class_resolver_lookup_method_from_interfacemethodref_index(vm->class_hash_table.length, class_resolver_lookup_method_from_objectref_class(vm->class_hash_table.length,
vm->class_hash_table.entry, vm->class_hash_table.entry,
index, index,
class_entry, objectref->class_entry,
vm->current_frame->class_entry); vm->current_frame->class_entry);
vm_special_method_call(vm, method_entry.class_entry, &method_entry); vm_special_method_call(vm, method_entry.class_entry, &method_entry);
@ -1200,9 +1199,9 @@ void op_invokespecial(struct vm * vm, uint32_t index)
{ {
struct class_entry * origin_class_entry = vm->current_frame->class_entry; struct class_entry * origin_class_entry = vm->current_frame->class_entry;
struct constant * interfacemethodref_constant = &origin_class_entry->class_file->constant_pool[index - 1]; struct constant * methodref_constant = &origin_class_entry->class_file->constant_pool[index - 1];
assert(interfacemethodref_constant->tag == CONSTANT_Methodref); assert(methodref_constant->tag == CONSTANT_Methodref);
struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[interfacemethodref_constant->interfacemethodref.name_and_type_index - 1]; struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[methodref_constant->methodref.name_and_type_index - 1];
assert(nameandtype_constant->tag == CONSTANT_NameAndType); assert(nameandtype_constant->tag == CONSTANT_NameAndType);
struct constant * method_descriptor_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1]; struct constant * method_descriptor_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
assert(method_descriptor_constant->tag == CONSTANT_Utf8); assert(method_descriptor_constant->tag == CONSTANT_Utf8);
@ -1216,7 +1215,7 @@ void op_invokespecial(struct vm * vm, uint32_t index)
return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException"));
struct method_entry * method_entry = struct method_entry * method_entry =
class_resolver_lookup_method_from_methodref_index(vm->class_hash_table.length, class_resolver_lookup_method_from_origin_class(vm->class_hash_table.length,
vm->class_hash_table.entry, vm->class_hash_table.entry,
index, index,
vm->current_frame->class_entry); vm->current_frame->class_entry);
@ -1227,7 +1226,7 @@ void op_invokespecial(struct vm * vm, uint32_t index)
void op_invokestatic(struct vm * vm, uint32_t index) void op_invokestatic(struct vm * vm, uint32_t index)
{ {
struct method_entry * method_entry = struct method_entry * method_entry =
class_resolver_lookup_method_from_methodref_index(vm->class_hash_table.length, class_resolver_lookup_method_from_origin_class(vm->class_hash_table.length,
vm->class_hash_table.entry, vm->class_hash_table.entry,
index, index,
vm->current_frame->class_entry); vm->current_frame->class_entry);
@ -1257,13 +1256,12 @@ void op_invokevirtual(struct vm * vm, uint32_t index)
struct objectref * objectref = operand_stack_peek_ref(vm->current_frame, nargs + 1); struct objectref * objectref = operand_stack_peek_ref(vm->current_frame, nargs + 1);
if (objectref == nullptr) if (objectref == nullptr)
return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException")); return vm_exception(vm, vm_instance_create(vm, "java/lang/NullPointerException"));
struct class_entry * class_entry = objectref->class_entry;
struct method_entry method_entry = struct method_entry method_entry =
class_resolver_lookup_method_from_interfacemethodref_index(vm->class_hash_table.length, class_resolver_lookup_method_from_objectref_class(vm->class_hash_table.length,
vm->class_hash_table.entry, vm->class_hash_table.entry,
index, index,
class_entry, objectref->class_entry,
vm->current_frame->class_entry); vm->current_frame->class_entry);
vm_special_method_call(vm, method_entry.class_entry, &method_entry); vm_special_method_call(vm, method_entry.class_entry, &method_entry);
@ -1893,13 +1891,12 @@ void op_pop2(struct vm * vm)
void op_putfield(struct vm * vm, uint32_t index) void op_putfield(struct vm * vm, uint32_t index)
{ {
struct class_entry * class_entry;
struct field_entry * field_entry;
struct constant * field_descriptor_constant; struct constant * field_descriptor_constant;
class_entry_field_entry_from_constant_index(vm, struct field_entry * field_entry = field_entry_from_constant_index(vm->class_hash_table.length,
vm->class_hash_table.entry,
vm->current_frame->class_entry,
objectref->class_entry,
index, index,
&class_entry,
&field_entry,
&field_descriptor_constant); &field_descriptor_constant);
/* The type of a value stored by a putfield instruction must be compatible /* The type of a value stored by a putfield instruction must be compatible
@ -1948,12 +1945,12 @@ void op_putfield(struct vm * vm, uint32_t index)
void op_putstatic(struct vm * vm, uint32_t index) void op_putstatic(struct vm * vm, uint32_t index)
{ {
struct class_entry * class_entry;
struct field_entry * field_entry;
struct constant * field_descriptor_constant; struct constant * field_descriptor_constant;
class_entry_field_entry_from_constant_index(vm, index, struct field_entry * field_entry = field_entry_from_constant_index(vm->class_hash_table.length,
&class_entry, vm->class_hash_table.entry,
&field_entry, vm->current_frame->class_entry,
vm->current_frame->class_entry,
index,
&field_descriptor_constant); &field_descriptor_constant);
/* The type of a value stored by a putstatic instruction must be compatible /* The type of a value stored by a putstatic instruction must be compatible

View File

@ -3,39 +3,33 @@ struct objectref * class_resolver_lookup_string(struct vm * vm,
struct class_entry * class_entry, struct class_entry * class_entry,
const int string_index); const int string_index);
static inline void class_entry_field_entry_from_constant_index(struct vm * vm, static inline struct field_entry * field_entry_from_constant_index(int class_hash_table_length,
struct hash_table_entry * class_hash_table,
struct class_entry * origin_class_entry,
struct class_entry * objectref_class_entry,
int32_t index, int32_t index,
struct class_entry ** class_entry,
struct field_entry ** field_entry,
struct constant ** field_descriptor_constant) struct constant ** field_descriptor_constant)
{ {
struct constant * fieldref_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; struct constant * fieldref_constant = &origin_class_entry->class_file->constant_pool[index - 1];
#ifdef DEBUG
assert(fieldref_constant->tag == CONSTANT_Fieldref); assert(fieldref_constant->tag == CONSTANT_Fieldref);
#endif
*class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, struct class_entry * field_class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length,
vm->class_hash_table.entry, class_hash_table,
vm->current_frame->class_entry, origin_class_entry,
fieldref_constant->fieldref.class_index); fieldref_constant->fieldref.class_index);
assert(*class_entry != nullptr); assert(field_class_entry != nullptr);
int fields_hash_table_length = (*class_entry)->fields.length; struct field_entry * field_entry = class_resolver_lookup_field_from_fieldref_index(class_hash_table_length,
struct hash_table_entry * fields_hash_table = (*class_entry)->fields.entry; class_hash_table,
field_class_entry,
*field_entry = class_resolver_lookup_field_from_fieldref_index(fields_hash_table_length,
fields_hash_table,
vm->current_frame->class_entry,
index); index);
assert(*field_entry != nullptr); assert(field_entry != nullptr);
struct constant * nameandtype_constant = &vm->current_frame->class_entry->class_file->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1]; struct constant * nameandtype_constant = &origin_class_entry->class_file->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1];
#ifdef DEBUG
assert(nameandtype_constant->tag == CONSTANT_NameAndType); assert(nameandtype_constant->tag == CONSTANT_NameAndType);
#endif *field_descriptor_constant = &origin_class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
*field_descriptor_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
#ifdef DEBUG
assert((*field_descriptor_constant)->tag == CONSTANT_Utf8); assert((*field_descriptor_constant)->tag == CONSTANT_Utf8);
#endif
return field_entry;
} }

View File

@ -1,10 +1,14 @@
package p; package test;
class A { class A {
int egg; int egg;
static int baz = 3; static int baz = 3;
static int bleh = 4; static int bleh = 4;
public A() {
egg = -1;
}
public int foo(int a) { public int foo(int a) {
return a + baz; return a + baz;
} }
@ -19,14 +23,7 @@ class B extends A {
} }
} }
class InheritanceTest { class TestInheritance {
static int test() {
B b = new B();
b.egg = 2;
//return b.bar(b.foo(4, 3));
return B.baz * A.baz;
}
static void static_test() { static void static_test() {
System.out.println("A:"); System.out.println("A:");
@ -35,10 +32,36 @@ class InheritanceTest {
System.out.println("B:"); System.out.println("B:");
System.out.println(B.baz); System.out.println(B.baz);
System.out.println(B.bleh); System.out.println(B.bleh);
B.bleh = 33;
B.baz = 99;
System.out.println("A:");
System.out.println(A.baz);
System.out.println(A.bleh);
System.out.println("B:");
System.out.println(B.baz);
System.out.println(B.bleh);
/*
static_test:
A:
3
4
B:
5
4
A:
3
33
B:
99
33
*/
} }
static int instance_test() { static int instance_test() {
B b = new B(); B b = new B();
System.out.println(b.egg);
b.egg = 1; b.egg = 1;
b.horse = 2; b.horse = 2;
@ -60,7 +83,14 @@ class InheritanceTest {
return b.foo(b.bar(6)); return b.foo(b.bar(6));
} }
public static void main() { public static void main(String[] args) {
System.out.println("static_test:");
static_test();
/*
System.out.println("instance_test:");
System.out.println(instance_test());
System.out.println("method_test:");
method_test(); method_test();
*/
} }
} }