class_resolver: correct behavior for instance field lookup from superclass

This commit is contained in:
Zack Buhman 2024-12-31 07:55:04 -06:00
parent e22f2e87e8
commit 2fe03bf38f
2 changed files with 101 additions and 59 deletions

View File

@ -56,41 +56,50 @@ static int32_t count_superclass_instance_fields(int class_hash_table_length,
return instance_field_count; return instance_field_count;
} }
static void add_superclass_instance_fields(int class_hash_table_length, static int add_superclass_instance_fields(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
int fields_hash_table_length, int fields_hash_table_length,
struct hash_table_entry * fields_hash_table, struct hash_table_entry * fields_hash_table,
struct class_entry * class_entry, struct class_entry * class_entry,
struct field_entry * field_entry,
int instance_index) int instance_index)
{ {
while (class_entry->class_file->super_class != 0) { if (class_entry->class_file->super_class != 0) {
class_entry = class_resolver_lookup_class_from_class_index(class_hash_table_length, struct class_entry * superclass_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); class_entry->class_file->super_class);
assert(class_entry != nullptr); assert(superclass_entry != nullptr);
instance_index = add_superclass_instance_fields(class_hash_table_length,
class_hash_table,
fields_hash_table_length,
fields_hash_table,
superclass_entry,
instance_index);
}
for (int i = 0; i < class_entry->class_file->fields_count; i++) { for (int i = 0; i < class_entry->class_file->fields_count; i++) {
struct field_info * field_info = &class_entry->class_file->fields[i]; struct field_info * field_info = &class_entry->class_file->fields[i];
if (!(field_info->access_flags & FIELD_ACC_STATIC)) { if (!(field_info->access_flags & FIELD_ACC_STATIC)) {
field_entry[i].instance_index = instance_index; struct field_entry * field_entry = malloc_class_arena((sizeof (struct field_entry)));
field_entry[i].field_info = field_info; field_entry->instance_index = instance_index;
instance_index += field_info_field_size(class_entry->class_file, field_info); field_entry->field_info = 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];
assert(name_constant->tag == CONSTANT_Utf8); assert(name_constant->tag == CONSTANT_Utf8);
debugf("hash table entry for field: "); debugf("hash table entry for instance field: ");
print_utf8_string(name_constant); print_utf8_string(name_constant);
debugf(": %d\n", instance_index); debugf(": %d %p\n", instance_index, field_entry);
hash_table_add(fields_hash_table_length, hash_table_add(fields_hash_table_length,
fields_hash_table, fields_hash_table,
name_constant->utf8.bytes, name_constant->utf8.bytes,
name_constant->utf8.length, name_constant->utf8.length,
(void *)&field_entry[i]); (void *)field_entry);
}
instance_index += field_info_field_size(class_entry->class_file, field_info);
} }
} }
return instance_index;
} }
static int32_t class_resolver_create_fields_hash_table(int class_hash_table_length, static int32_t class_resolver_create_fields_hash_table(int class_hash_table_length,
@ -104,46 +113,42 @@ static int32_t class_resolver_create_fields_hash_table(int class_hash_table_leng
uint32_t fields_hash_table_size = (sizeof (struct hash_table_entry)) * fields_hash_table_length; 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); struct hash_table_entry * fields_hash_table = malloc_class_arena(fields_hash_table_size);
uint32_t field_entry_size = (sizeof (struct field_entry)) * total_fields_count; int static_index = 0;
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_entry->class_file->fields_count; i++) { for (int i = 0; i < class_entry->class_file->fields_count; i++) {
struct field_info * field_info = &class_entry->class_file->fields[i]; struct field_info * field_info = &class_entry->class_file->fields[i];
if (field_info->access_flags & FIELD_ACC_STATIC) { if (field_info->access_flags & FIELD_ACC_STATIC) {
field_entry[i].static_index = static_index; struct field_entry * field_entry = malloc_class_arena((sizeof (struct field_entry)));
field_entry->static_index = static_index;
field_entry->field_info = field_info;
static_index += field_info_field_size(class_entry->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_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]; 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);
debugf("hash table entry for field: "); debugf("hash table entry for static field: ");
print_utf8_string(name_constant); print_utf8_string(name_constant);
debugf(": %d\n", i); debugf(": %d %p\n", static_index, field_entry);
hash_table_add(fields_hash_table_length, hash_table_add(fields_hash_table_length,
fields_hash_table, fields_hash_table,
name_constant->utf8.bytes, name_constant->utf8.bytes,
name_constant->utf8.length, name_constant->utf8.length,
(void *)&field_entry[i]); (void *)field_entry);
}
} }
class_entry->fields.length = fields_hash_table_length; int instance_index = add_superclass_instance_fields(class_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, class_hash_table,
fields_hash_table_length, fields_hash_table_length,
fields_hash_table, fields_hash_table,
class_entry, class_entry,
&field_entry[class_entry->class_file->fields_count], 0);
instance_index);
debugf("static_index=%d instance_index=%d total_fields_count=%d\n", static_index, instance_index, total_fields_count);
class_entry->fields.length = fields_hash_table_length;
class_entry->fields.entry = fields_hash_table;
class_entry->instance_fields_count = instance_index;
return static_index; return static_index;
} }
@ -325,6 +330,7 @@ struct field_entry * class_resolver_lookup_field(int fields_hash_table_length,
field_name, field_name,
field_name_length); field_name_length);
assert(e != nullptr); assert(e != nullptr);
debugf("%p\n", e->value);
return (struct field_entry *)e->value; return (struct field_entry *)e->value;
} }

36
p/InstanceFields.java Normal file
View File

@ -0,0 +1,36 @@
package p;
class Super {
public int aa;
public int bb;
int bar() {
return bb;
}
};
class Fields extends Super {
public int cc;
public int dd;
int foo() {
return bar();
}
}
class InstanceFields {
public static int test() {
Fields f = new Fields();
f.aa = 11;
f.bb = 22;
f.cc = 33;
f.dd = 44;
return f.foo();
//return f.bb;
}
public static void main() {
test();
}
}