implement static method overloading

This commit is contained in:
Zack Buhman 2024-12-24 20:23:54 -06:00
parent d2863035e4
commit baa3db16b1
13 changed files with 215 additions and 26 deletions

1
.gitignore vendored
View File

@ -4,5 +4,6 @@
*.gch
*.csv
*.class
*.out
main
print_class

BIN
c/a.out

Binary file not shown.

View File

@ -62,7 +62,7 @@ struct hash_table_entry * class_resolver_load_from_filenames(const char * filena
int fields_hash_table_length = 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)) * length;
uint32_t field_entry_size = (sizeof (struct field_entry)) * class_file->fields_count;
struct field_entry * field_entry = malloc_class_arena(field_entry_size);
for (int i = 0; i < class_file->fields_count; i++) {
u2 name_index = class_file->fields[i].name_index;
@ -95,15 +95,20 @@ struct hash_table_entry * class_resolver_load_from_filenames(const char * filena
u2 name_index = class_file->methods[i].name_index;
struct constant * name_constant = &class_file->constant_pool[name_index - 1];
assert(name_constant->tag == CONSTANT_Utf8);
u2 descriptor_index = class_file->methods[i].descriptor_index;
struct constant * descriptor_constant = &class_file->constant_pool[descriptor_index - 1];
assert(descriptor_constant->tag == CONSTANT_Utf8);
printf("hash table entry for method: ");
print_utf8_string(name_constant);
printf("\n");
hash_table_add(methods_hash_table_length,
methods_hash_table,
name_constant->utf8.bytes,
name_constant->utf8.length,
(void *)&class_file->methods[i]);
hash_table_add2(methods_hash_table_length,
methods_hash_table,
name_constant->utf8.bytes,
name_constant->utf8.length,
descriptor_constant->utf8.bytes,
descriptor_constant->utf8.length,
(void *)&class_file->methods[i]);
}
class_entry[i].methods.length = methods_hash_table_length;
@ -157,19 +162,25 @@ struct field_entry * class_resolver_lookup_field(struct class_entry * class_entr
struct method_info * class_resolver_lookup_method(struct class_entry * class_entry,
const uint8_t * method_name,
int method_name_length)
int method_name_length,
const uint8_t * method_descriptor,
int method_descriptor_length)
{
printf("class_resolver_lookup_method: ");
for (int i = 0; i < method_name_length; i++) { fputc(method_name[i], stdout); }
fputc(' ', stdout);
for (int i = 0; i < method_descriptor_length; i++) { fputc(method_descriptor[i], stdout); }
fputc('\n', stdout);
int methods_hash_table_length = class_entry->methods.length;
struct hash_table_entry * methods_hash_table = class_entry->methods.entry;
struct hash_table_entry * e = hash_table_find(methods_hash_table_length,
methods_hash_table,
method_name,
method_name_length);
struct hash_table_entry * e = hash_table_find2(methods_hash_table_length,
methods_hash_table,
method_name,
method_name_length,
method_descriptor,
method_descriptor_length);
assert(e != nullptr);
return (struct method_info *)e->value;

View File

@ -43,7 +43,9 @@ struct class_entry * class_resolver_lookup_class(int class_hash_table_length,
int class_name_length);
struct method_info * class_resolver_lookup_method(struct class_entry * class_entry,
const uint8_t * method_name,
int method_name_length);
int method_name_length,
const uint8_t * method_descriptor,
int method_descriptor_length);
struct field_entry * class_resolver_lookup_field(struct class_entry * class_entry,
const uint8_t * field_name,
int field_name_length);

View File

@ -920,6 +920,10 @@ void op_invokestatic(struct vm * vm, uint32_t index)
#ifdef DEBUG
assert(method_name_constant->tag == CONSTANT_Utf8);
#endif
struct constant * method_descriptor_constant = &vm->current_thread.current_class->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
#ifdef DEBUG
assert(method_descriptor_constant->tag == CONSTANT_Utf8);
#endif
struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
vm->class_hash_table.entry,
@ -929,7 +933,9 @@ void op_invokestatic(struct vm * vm, uint32_t index)
struct method_info * method_info = class_resolver_lookup_method(class_entry,
method_name_constant->utf8.bytes,
method_name_constant->utf8.length);
method_name_constant->utf8.length,
method_descriptor_constant->utf8.bytes,
method_descriptor_constant->utf8.length);
assert(method_info != nullptr);
/* On successful resolution of the method, the class or interface that

View File

@ -121,11 +121,15 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
/* Next, if C declares a class or interface initialization method, execute
that method. */
const uint8_t * method_name = (const uint8_t *)"<clinit>";
int method_length = 8;
int method_name_length = 8;
const uint8_t * method_descriptor = (const uint8_t *)"()V";
int method_descriptor_length = 3;
struct method_info * method_info = class_resolver_lookup_method(class_entry,
method_name,
method_length);
method_name_length,
method_descriptor,
method_descriptor_length);
if (method_info != nullptr) {
assert((method_info->access_flags & METHOD_ACC_STATIC) != 0);
printf("<clinit>\n");

View File

@ -1,12 +1,11 @@
#include "malloc.h"
#include "hash_table.h"
static uint32_t fnv_1(const uint8_t * buf, int length)
{
const uint32_t fnv_offset_basis = 0x811c9dc5;
const uint32_t fnv_prime = 0x01000193;
static const uint32_t fnv_offset_basis = 0x811c9dc5;
uint32_t hash = fnv_offset_basis;
static uint32_t fnv_1(uint32_t hash, const uint8_t * buf, int length)
{
const uint32_t fnv_prime = 0x01000193;
for (int i = 0; i < length; i++) {
hash = hash * fnv_prime;
@ -25,13 +24,24 @@ void hash_table_init(int hash_table_length,
}
}
#include <stdio.h>
void print_key(const uint8_t * key, int key_length)
{
printf("key: ");
for (int i = 0; i < key_length; i++)
fputc(key[i], stdout);
fputc('\n', stdout);
}
void hash_table_add(int hash_table_length,
struct hash_table_entry * entry,
const uint8_t * key,
int key_length,
void * value)
{
uint32_t hash = fnv_1(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];
while (e->next != nullptr) {
@ -44,7 +54,12 @@ void hash_table_add(int hash_table_length,
e = e->next;
}
e->key = key;
uint8_t * key_copy = malloc_class_arena(key_length);
for (int i = 0; i < key_length; i++) key_copy[i] = key[i];
printf("key copy: %p ", key_copy);
print_key(key_copy, key_length);
e->key = key_copy;
e->key_length = key_length;
e->value = value;
}
@ -63,11 +78,88 @@ struct hash_table_entry * hash_table_find(int hash_table_length,
const uint8_t * key,
int key_length)
{
uint32_t hash = fnv_1(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];
while (e != nullptr && e->key != nullptr) {
if (e->key_length == key_length && key_equal(e->key, key, key_length)) {
printf("key find: %p ", e->key);
print_key(e->key, e->key_length);
if (e->key_length == key_length && key_equal(key, e->key, e->key_length)) {
return e;
}
e = e->next;
}
return nullptr;
}
static inline bool key_equal2(const uint8_t * a1, int a1_length,
const uint8_t * a2, int a2_length,
const uint8_t * b)
{
for (int i = 0; i < a1_length; i++) {
if (a1[i] != b[i])
return false;
}
for (int i = 0; i < a2_length; i++) {
if (a2[i] != b[a1_length + i])
return false;
}
return true;
}
void hash_table_add2(int hash_table_length,
struct hash_table_entry * entry,
const uint8_t * key1,
int key1_length,
const uint8_t * key2,
int key2_length,
void * value)
{
uint32_t hash = fnv_offset_basis;
hash = fnv_1(hash, key1, key1_length);
hash = fnv_1(hash, key2, key2_length);
hash &= (hash_table_length - 1);
struct hash_table_entry * e = &entry[hash];
while (e->next != nullptr) {
e = e->next;
}
if (e->key != nullptr) {
// allocate e from overflow
e->next = malloc_class_arena((sizeof (struct hash_table_entry)));
e = e->next;
}
uint8_t * key_copy = malloc_class_arena(key1_length + key2_length);
for (int i = 0; i < key1_length; i++) key_copy[i] = key1[i];
for (int i = 0; i < key2_length; i++) key_copy[key1_length + i] = key2[i];
e->key = key_copy;
e->key_length = key1_length + key2_length;
e->value = value;
}
struct hash_table_entry * hash_table_find2(int hash_table_length,
struct hash_table_entry * entry,
const uint8_t * key1,
int key1_length,
const uint8_t * key2,
int key2_length)
{
uint32_t hash = fnv_offset_basis;
hash = fnv_1(hash, key1, key1_length);
hash = fnv_1(hash, key2, key2_length);
hash &= (hash_table_length - 1);
struct hash_table_entry * e = &entry[hash];
while (e != nullptr && e->key != nullptr) {
bool equal =
e->key_length == (key1_length + key2_length) &&
key_equal2(key1, key1_length,
key2, key2_length,
e->key);
if (equal) {
return e;
}
e = e->next;

View File

@ -22,3 +22,18 @@ struct hash_table_entry * hash_table_find(int hash_table_length,
struct hash_table_entry * entry,
const uint8_t * key,
int key_length);
void hash_table_add2(int hash_table_length,
struct hash_table_entry * entry,
const uint8_t * key1,
int key1_length,
const uint8_t * key2,
int key2_length,
void * value);
struct hash_table_entry * hash_table_find2(int hash_table_length,
struct hash_table_entry * entry,
const uint8_t * key1,
int key1_length,
const uint8_t * key2,
int key2_length);

View File

@ -21,9 +21,13 @@ int main(int argc, const char * argv[])
const char * method_name = "main";
int method_name_length = string_length(method_name);
const char * method_descriptor = "()V";
int method_descriptor_length = string_length(method_descriptor);
struct method_info * method_info = class_resolver_lookup_method(class_entry,
(const uint8_t *)method_name,
method_name_length);
method_name_length,
(const uint8_t *)method_descriptor,
method_descriptor_length);
struct vm vm;
vm.class_hash_table.entry = class_hash_table;

View File

@ -1,5 +1,7 @@
#include "malloc.h"
#include <assert.h>
struct arena {
uint8_t * mem;
uint32_t size;
@ -16,7 +18,9 @@ struct arena class_arena = {
void * malloc_class_arena(uint32_t size)
{
assert((class_arena.ix & (~3)) == class_arena.ix);
void * ptr = &class_arena.mem[class_arena.ix];
size = (size + 3) & (~3);
class_arena.ix += size;
return ptr;
}

View File

@ -145,6 +145,12 @@ static uint32_t _strlen(const char * s)
return si - s;
}
void print_key(const uint8_t * key, int key_length)
{
for (int i = 0; i < key_length; i++)
fputc(key[i], stdout);
}
int main()
{
int hash_table_length = 128 * 2;
@ -170,6 +176,7 @@ int main()
printf("collision %s\n", e->key);
}
assert(e != nullptr);
printf("%s %d\n", e->key, (int)e->value);
print_key(e->key, e->key_length);
printf(" %d\n", (int)e->value);
}
}

24
p/Instance.java Normal file
View File

@ -0,0 +1,24 @@
package p;
class Instance {
int a;
int b;
public Instance(int a) {
this.a = a;
this.b = 13;
}
int mul() {
return a * b;
}
static int test() {
Instance i = new Instance(12);
return i.mul();
}
public static void main() {
test();
}
}

View File

@ -0,0 +1,19 @@
package p;
class StaticMethodOverloading {
static int test() {
return test(4);
}
static int test(int a) {
return test(a, 3);
}
static int test(int a, int b) {
return a * b + 1;
}
public static void main() {
test();
}
}