implement superclass instance field lookup

This commit is contained in:
Zack Buhman 2024-12-29 07:14:26 -06:00
parent 88318fde35
commit cb26d8cadf
8 changed files with 196 additions and 47 deletions

View File

@ -11,19 +11,6 @@
#include "printf.h"
#include "field_size.h"
static void class_resolver_create_interfaces_hash_table(struct class_entry * class_entry)
{
/*
struct class_file * class_file = class_entry->class_file;
uint32_t interfaces_hash_table_size = (sizeof (struct hash_table_entry)) * class_file->interfaces_count * 3 / 2;
struct hash_table_entry * interfaces_hash_table = malloc_class_arena(interfaces_hash_table_size);
for (int i = 0; i < class_file->interfaces_count; i++) {
}
*/
}
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];
@ -33,37 +20,109 @@ static int field_info_field_size(struct class_file * class_file, struct field_in
return field_size(field_descriptor_constant->utf8.bytes[0]);
}
static int32_t class_resolver_create_fields_hash_table(struct class_entry * class_entry)
static int32_t count_superclass_instance_fields(int class_hash_table_length,
struct hash_table_entry * class_hash_table,
struct class_entry * class_entry)
{
struct class_file * class_file = class_entry->class_file;
int fields_hash_table_length = hash_table_next_power_of_two(class_file->fields_count * 2);
struct class_entry * subclass_entry = class_entry;
int instance_field_count = 0;
while (class_entry->class_file->super_class != 0) {
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);
for (int i = 0; i < class_entry->class_file->fields_count; i++) {
struct field_info * field_info = &class_entry->class_file->fields[i];
if (!(field_info->access_flags & FIELD_ACC_STATIC)) {
instance_field_count += 1;
}
}
}
struct constant * class_constant = &subclass_entry->class_file->constant_pool[subclass_entry->class_file->this_class - 1];
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &subclass_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
debugf("count_superclass_instance_fields: ");
print_utf8_string(class_name_constant);
debugf(": %d\n", instance_field_count);
return instance_field_count;
}
static void add_superclass_instance_fields(int class_hash_table_length,
struct hash_table_entry * class_hash_table,
int fields_hash_table_length,
struct hash_table_entry * fields_hash_table,
struct class_entry * class_entry,
struct field_entry * field_entry,
int instance_index)
{
while (class_entry->class_file->super_class != 0) {
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);
for (int i = 0; i < class_entry->class_file->fields_count; i++) {
struct field_info * field_info = &class_entry->class_file->fields[i];
if (!(field_info->access_flags & FIELD_ACC_STATIC)) {
field_entry[i].instance_index = instance_index;
field_entry[i].field_info = field_info;
instance_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];
assert(name_constant->tag == CONSTANT_Utf8);
debugf("hash table entry for field: ");
print_utf8_string(name_constant);
debugf(": %d\n", instance_index);
hash_table_add(fields_hash_table_length,
fields_hash_table,
name_constant->utf8.bytes,
name_constant->utf8.length,
(void *)&field_entry[i]);
}
}
}
}
static int32_t class_resolver_create_fields_hash_table(int class_hash_table_length,
struct hash_table_entry * class_hash_table,
struct class_entry * class_entry)
{
int total_fields_count = class_entry->class_file->fields_count + count_superclass_instance_fields(class_hash_table_length,
class_hash_table,
class_entry);
int fields_hash_table_length = hash_table_next_power_of_two(class_entry->class_file->fields_count * 2);
uint32_t fields_hash_table_size = (sizeof (struct hash_table_entry)) * fields_hash_table_length;
struct hash_table_entry * fields_hash_table = malloc_class_arena(fields_hash_table_size);
uint32_t field_entry_size = (sizeof (struct field_entry)) * class_file->fields_count;
uint32_t field_entry_size = (sizeof (struct field_entry)) * total_fields_count;
struct field_entry * field_entry = malloc_class_arena(field_entry_size);
int32_t static_index = 0;
int32_t instance_index = 0;
for (int i = 0; i < class_file->fields_count; i++) {
u2 name_index = class_file->fields[i].name_index;
struct constant * name_constant = &class_file->constant_pool[name_index - 1];
assert(name_constant->tag == CONSTANT_Utf8);
debugf("hash table entry for field: ");
print_utf8_string(name_constant);
debugf("\n");
struct field_info * field_info = &class_file->fields[i];
for (int i = 0; i < class_entry->class_file->fields_count; i++) {
struct field_info * field_info = &class_entry->class_file->fields[i];
if (field_info->access_flags & FIELD_ACC_STATIC) {
field_entry[i].static_index = static_index;
static_index += field_info_field_size(class_file, field_info);
static_index += field_info_field_size(class_entry->class_file, field_info);
} else {
field_entry[i].instance_index = instance_index;
instance_index += field_info_field_size(class_file, field_info);
instance_index += field_info_field_size(class_entry->class_file, field_info);
}
field_entry[i].field_info = field_info;
struct constant * name_constant = &class_entry->class_file->constant_pool[field_info->name_index - 1];
assert(name_constant->tag == CONSTANT_Utf8);
debugf("hash table entry for field: ");
print_utf8_string(name_constant);
debugf(": %d\n", i);
hash_table_add(fields_hash_table_length,
fields_hash_table,
name_constant->utf8.bytes,
@ -73,6 +132,15 @@ static int32_t class_resolver_create_fields_hash_table(struct class_entry * clas
class_entry->fields.length = fields_hash_table_length;
class_entry->fields.entry = fields_hash_table;
class_entry->instance_fields_count = instance_index;
add_superclass_instance_fields(class_hash_table_length,
class_hash_table,
fields_hash_table_length,
fields_hash_table,
class_entry,
&field_entry[class_entry->class_file->fields_count],
instance_index);
return static_index;
}
@ -142,6 +210,7 @@ struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buff
uint32_t class_entry_size = (sizeof (struct class_entry)) * length;
struct class_entry * class_entry = malloc_class_arena(class_entry_size);
// populate class_hash_table first, to allow for superclass lookups
for (int i = 0; i < length; i++) {
struct class_file * class_file = class_file_parse(buffers[i]);
@ -154,7 +223,6 @@ struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buff
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
debugf("hash table entry for class: ");
print_utf8_string(class_name_constant);
debugf("\n");
@ -165,22 +233,24 @@ struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buff
class_name_constant->utf8.length,
&class_entry[i]);
// make hash table for interfaces
class_resolver_create_interfaces_hash_table(&class_entry[i]);
// make hash table for fields
int32_t static_field_count = class_resolver_create_fields_hash_table(&class_entry[i]);
// make hash table for methods
class_resolver_create_methods_hash_table(&class_entry[i]);
// allocate static fields
class_resolver_allocate_static_fields(&class_entry[i], static_field_count);
// allocate attribute_entry
class_resolver_allocate_attribute_entry(&class_entry[i]);
};
// these functions may reference class_hash_table for superclass lookups
for (int i = 0; i < length; i++) {
// make hash table for fields
int32_t static_field_count = class_resolver_create_fields_hash_table(class_hash_table_length,
class_hash_table,
&class_entry[i]);
// allocate static fields
class_resolver_allocate_static_fields(&class_entry[i], static_field_count);
}
*hash_table_length = class_hash_table_length;
return class_hash_table;

View File

@ -31,6 +31,7 @@ struct class_entry {
enum initialization_state initialization_state;
union attribute_entry * attribute_entry;
int32_t * static_fields;
int32_t instance_fields_count;
struct {
int length;

View File

@ -232,7 +232,14 @@ void print_class_file(struct class_file * class_file)
debugf("interfaces:\n");
for (int i = 0; i < class_file->interfaces_count; i++) {
debugf("% 3d: %d\n", i + 1, class_file->interfaces[i]);
debugf(" interface %3d:\n", i);
int interface_index = class_file->interfaces[i];
debugs(" ");
struct constant * class_constant = &class_file->constant_pool[interface_index - 1];
print_constant(class_constant);
debugs(" ");
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
print_constant(class_name_constant);
}
debugf("fields_count %d\n", class_file->fields_count);

View File

@ -10,7 +10,7 @@ void op_aaload(struct vm * vm)
{
int32_t index = operand_stack_pop_u32(vm->current_frame);
int32_t * arrayref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
assertvm(vm, arrayref[0] > 0 && index < arrayref[0]);
assert(arrayref[0] > 0 && index < arrayref[0]);
uint32_t * referencearray = (uint32_t *)&arrayref[1];
uint32_t value = referencearray[index];
operand_stack_push_u32(vm->current_frame, value);
@ -684,7 +684,7 @@ void op_getfield(struct vm * vm, uint32_t index)
&field_entry,
&field_descriptor_constant);
debugf("putfield instance_index %d\n", field_entry->instance_index);
debugf("getfield instance_index %d\n", field_entry->instance_index);
int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
assert(objectref != nullptr);
@ -1684,7 +1684,7 @@ void op_new(struct vm * vm, uint32_t index)
initialized to their default initial values (§2.3, §2.4). The objectref, a
reference to the instance, is pushed onto the operand stack. */
int fields_count = class_entry->class_file->fields_count;
int fields_count = class_entry->instance_fields_count;
int32_t * objectref = memory_allocate(fields_count * 2 * 4 + 4);
assert(objectref != nullptr);
objectref[0] = (int32_t)class_entry;

View File

@ -79,7 +79,9 @@ struct hash_table_entry * hash_table_find(int hash_table_length,
const uint8_t * key,
int key_length)
{
assert(hash_table_length != 0);
if (hash_table_length == 0)
return nullptr;
assert((hash_table_length & (hash_table_length - 1)) == 0);
uint32_t hash = fnv_1(fnv_offset_basis, key, key_length) & (hash_table_length - 1);
struct hash_table_entry * e = &entry[hash];
@ -151,7 +153,9 @@ struct hash_table_entry * hash_table_find2(int hash_table_length,
const uint8_t * key2,
int key2_length)
{
assert(hash_table_length != 0);
if (hash_table_length == 0)
return nullptr;
assert((hash_table_length & (hash_table_length - 1)) == 0);
uint32_t hash = fnv_offset_basis;
hash = fnv_1(hash, key1, key1_length);

View File

@ -118,6 +118,8 @@ uint32_t java_misc_resource_getresource_1(uint32_t * args)
uint32_t resource = find_resource(name, name_length);
return resource;
#else
(void)name;
(void)name_length;
return 0;
#endif
}

View File

@ -199,7 +199,7 @@ class DreamcastVideo2 {
Memory.putSQ1(vt0, MemoryMap.ta_fifo_polygon_converter);
vt0.parameter_control_word = TAParameter.para_control__para_type__vertex_parameter
| TAParameter.para_control__end_of_strip;
| TAParameter.para_control__end_of_strip;
vt0.x = quad[2].x;
vt0.y = quad[2].y;
vt0.u = quad_uv[2].x;
@ -293,7 +293,8 @@ class DreamcastVideo2 {
framebuffer_width);
Core.wait_end_of_render_tsp();
while ((CoreBits.spg_status__vsync(Memory.getU4(Holly.SPG_STATUS)) != 0));
while ((CoreBits.spg_status__vsync(Memory.getU4(Holly.SPG_STATUS)) == 0));
while (!(CoreBits.spg_status__vsync(Memory.getU4(Holly.SPG_STATUS)) == 0));
Core.fb_r_enable();
Memory.putU4(Holly.FB_R_SOF1, TextureMemoryAllocation.framebuffer_start[0]);
}

64
p/InheritanceTest.java Normal file
View File

@ -0,0 +1,64 @@
package p;
class A {
int egg;
static int baz = 3;
static int bleh = 4;
/*
public int foo(int a, int b) {
return a + b;
}
*/
}
class B extends A {
static int baz = 5;
int horse;
/*
public int bar(int a) {
return a * egg;
}
*/
}
class InheritanceTest {
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() {
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 int instance_test() {
B b = new B();
b.egg = 1;
b.horse = 2;
System.out.println(b.egg);
System.out.println(b.horse);
b.egg = 3;
b.horse = 4;
System.out.println(b.egg);
System.out.println(b.horse);
return b.egg * b.horse;
}
public static void main() {
instance_test();
}
}