implement superclass instance field lookup
This commit is contained in:
parent
88318fde35
commit
cb26d8cadf
@ -11,19 +11,6 @@
|
|||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "field_size.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)
|
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];
|
||||||
@ -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]);
|
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;
|
struct class_entry * subclass_entry = class_entry;
|
||||||
int fields_hash_table_length = hash_table_next_power_of_two(class_file->fields_count * 2);
|
|
||||||
|
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;
|
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)) * 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);
|
struct field_entry * field_entry = malloc_class_arena(field_entry_size);
|
||||||
|
|
||||||
int32_t static_index = 0;
|
int32_t static_index = 0;
|
||||||
int32_t instance_index = 0;
|
int32_t instance_index = 0;
|
||||||
|
|
||||||
for (int i = 0; i < class_file->fields_count; i++) {
|
for (int i = 0; i < class_entry->class_file->fields_count; i++) {
|
||||||
u2 name_index = class_file->fields[i].name_index;
|
struct field_info * field_info = &class_entry->class_file->fields[i];
|
||||||
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];
|
|
||||||
|
|
||||||
if (field_info->access_flags & FIELD_ACC_STATIC) {
|
if (field_info->access_flags & FIELD_ACC_STATIC) {
|
||||||
field_entry[i].static_index = static_index;
|
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 {
|
} else {
|
||||||
field_entry[i].instance_index = instance_index;
|
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;
|
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,
|
hash_table_add(fields_hash_table_length,
|
||||||
fields_hash_table,
|
fields_hash_table,
|
||||||
name_constant->utf8.bytes,
|
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.length = fields_hash_table_length;
|
||||||
class_entry->fields.entry = fields_hash_table;
|
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;
|
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;
|
uint32_t class_entry_size = (sizeof (struct class_entry)) * length;
|
||||||
struct class_entry * class_entry = malloc_class_arena(class_entry_size);
|
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++) {
|
for (int i = 0; i < length; i++) {
|
||||||
struct class_file * class_file = class_file_parse(buffers[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);
|
assert(class_constant->tag == CONSTANT_Class);
|
||||||
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
|
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||||
|
|
||||||
debugf("hash table entry for class: ");
|
debugf("hash table entry for class: ");
|
||||||
print_utf8_string(class_name_constant);
|
print_utf8_string(class_name_constant);
|
||||||
debugf("\n");
|
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_name_constant->utf8.length,
|
||||||
&class_entry[i]);
|
&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
|
// make hash table for methods
|
||||||
class_resolver_create_methods_hash_table(&class_entry[i]);
|
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
|
// allocate attribute_entry
|
||||||
class_resolver_allocate_attribute_entry(&class_entry[i]);
|
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;
|
*hash_table_length = class_hash_table_length;
|
||||||
|
|
||||||
return class_hash_table;
|
return class_hash_table;
|
||||||
|
@ -31,6 +31,7 @@ struct class_entry {
|
|||||||
enum initialization_state initialization_state;
|
enum initialization_state initialization_state;
|
||||||
union attribute_entry * attribute_entry;
|
union attribute_entry * attribute_entry;
|
||||||
int32_t * static_fields;
|
int32_t * static_fields;
|
||||||
|
int32_t instance_fields_count;
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int length;
|
int length;
|
||||||
|
@ -232,7 +232,14 @@ void print_class_file(struct class_file * class_file)
|
|||||||
|
|
||||||
debugf("interfaces:\n");
|
debugf("interfaces:\n");
|
||||||
for (int i = 0; i < class_file->interfaces_count; i++) {
|
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);
|
debugf("fields_count %d\n", class_file->fields_count);
|
||||||
|
@ -10,7 +10,7 @@ void op_aaload(struct vm * vm)
|
|||||||
{
|
{
|
||||||
int32_t index = operand_stack_pop_u32(vm->current_frame);
|
int32_t index = operand_stack_pop_u32(vm->current_frame);
|
||||||
int32_t * arrayref = (int32_t *)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 * referencearray = (uint32_t *)&arrayref[1];
|
||||||
uint32_t value = referencearray[index];
|
uint32_t value = referencearray[index];
|
||||||
operand_stack_push_u32(vm->current_frame, value);
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
@ -684,7 +684,7 @@ void op_getfield(struct vm * vm, uint32_t index)
|
|||||||
&field_entry,
|
&field_entry,
|
||||||
&field_descriptor_constant);
|
&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);
|
int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
|
||||||
assert(objectref != nullptr);
|
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
|
initialized to their default initial values (§2.3, §2.4). The objectref, a
|
||||||
reference to the instance, is pushed onto the operand stack. */
|
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);
|
int32_t * objectref = memory_allocate(fields_count * 2 * 4 + 4);
|
||||||
assert(objectref != nullptr);
|
assert(objectref != nullptr);
|
||||||
objectref[0] = (int32_t)class_entry;
|
objectref[0] = (int32_t)class_entry;
|
||||||
|
@ -79,7 +79,9 @@ struct hash_table_entry * hash_table_find(int hash_table_length,
|
|||||||
const uint8_t * key,
|
const uint8_t * key,
|
||||||
int key_length)
|
int key_length)
|
||||||
{
|
{
|
||||||
assert(hash_table_length != 0);
|
if (hash_table_length == 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
assert((hash_table_length & (hash_table_length - 1)) == 0);
|
assert((hash_table_length & (hash_table_length - 1)) == 0);
|
||||||
uint32_t hash = fnv_1(fnv_offset_basis, key, key_length) & (hash_table_length - 1);
|
uint32_t hash = fnv_1(fnv_offset_basis, key, key_length) & (hash_table_length - 1);
|
||||||
struct hash_table_entry * e = &entry[hash];
|
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,
|
const uint8_t * key2,
|
||||||
int key2_length)
|
int key2_length)
|
||||||
{
|
{
|
||||||
assert(hash_table_length != 0);
|
if (hash_table_length == 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
assert((hash_table_length & (hash_table_length - 1)) == 0);
|
assert((hash_table_length & (hash_table_length - 1)) == 0);
|
||||||
uint32_t hash = fnv_offset_basis;
|
uint32_t hash = fnv_offset_basis;
|
||||||
hash = fnv_1(hash, key1, key1_length);
|
hash = fnv_1(hash, key1, key1_length);
|
||||||
|
@ -118,6 +118,8 @@ uint32_t java_misc_resource_getresource_1(uint32_t * args)
|
|||||||
uint32_t resource = find_resource(name, name_length);
|
uint32_t resource = find_resource(name, name_length);
|
||||||
return resource;
|
return resource;
|
||||||
#else
|
#else
|
||||||
|
(void)name;
|
||||||
|
(void)name_length;
|
||||||
return 0;
|
return 0;
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
@ -199,7 +199,7 @@ class DreamcastVideo2 {
|
|||||||
Memory.putSQ1(vt0, MemoryMap.ta_fifo_polygon_converter);
|
Memory.putSQ1(vt0, MemoryMap.ta_fifo_polygon_converter);
|
||||||
|
|
||||||
vt0.parameter_control_word = TAParameter.para_control__para_type__vertex_parameter
|
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.x = quad[2].x;
|
||||||
vt0.y = quad[2].y;
|
vt0.y = quad[2].y;
|
||||||
vt0.u = quad_uv[2].x;
|
vt0.u = quad_uv[2].x;
|
||||||
@ -293,7 +293,8 @@ class DreamcastVideo2 {
|
|||||||
framebuffer_width);
|
framebuffer_width);
|
||||||
Core.wait_end_of_render_tsp();
|
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();
|
Core.fb_r_enable();
|
||||||
Memory.putU4(Holly.FB_R_SOF1, TextureMemoryAllocation.framebuffer_start[0]);
|
Memory.putU4(Holly.FB_R_SOF1, TextureMemoryAllocation.framebuffer_start[0]);
|
||||||
}
|
}
|
||||||
|
64
p/InheritanceTest.java
Normal file
64
p/InheritanceTest.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user