implement static method overloading
This commit is contained in:
parent
d2863035e4
commit
baa3db16b1
1
.gitignore
vendored
1
.gitignore
vendored
@ -4,5 +4,6 @@
|
|||||||
*.gch
|
*.gch
|
||||||
*.csv
|
*.csv
|
||||||
*.class
|
*.class
|
||||||
|
*.out
|
||||||
main
|
main
|
||||||
print_class
|
print_class
|
@ -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;
|
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;
|
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)) * 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);
|
struct field_entry * field_entry = malloc_class_arena(field_entry_size);
|
||||||
for (int i = 0; i < class_file->fields_count; i++) {
|
for (int i = 0; i < class_file->fields_count; i++) {
|
||||||
u2 name_index = class_file->fields[i].name_index;
|
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;
|
u2 name_index = class_file->methods[i].name_index;
|
||||||
struct constant * name_constant = &class_file->constant_pool[name_index - 1];
|
struct constant * name_constant = &class_file->constant_pool[name_index - 1];
|
||||||
assert(name_constant->tag == CONSTANT_Utf8);
|
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: ");
|
printf("hash table entry for method: ");
|
||||||
print_utf8_string(name_constant);
|
print_utf8_string(name_constant);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
|
||||||
hash_table_add(methods_hash_table_length,
|
hash_table_add2(methods_hash_table_length,
|
||||||
methods_hash_table,
|
methods_hash_table,
|
||||||
name_constant->utf8.bytes,
|
name_constant->utf8.bytes,
|
||||||
name_constant->utf8.length,
|
name_constant->utf8.length,
|
||||||
(void *)&class_file->methods[i]);
|
descriptor_constant->utf8.bytes,
|
||||||
|
descriptor_constant->utf8.length,
|
||||||
|
(void *)&class_file->methods[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
class_entry[i].methods.length = methods_hash_table_length;
|
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,
|
struct method_info * class_resolver_lookup_method(struct class_entry * class_entry,
|
||||||
const uint8_t * method_name,
|
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: ");
|
printf("class_resolver_lookup_method: ");
|
||||||
for (int i = 0; i < method_name_length; i++) { fputc(method_name[i], stdout); }
|
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);
|
fputc('\n', stdout);
|
||||||
|
|
||||||
int methods_hash_table_length = class_entry->methods.length;
|
int methods_hash_table_length = class_entry->methods.length;
|
||||||
struct hash_table_entry * methods_hash_table = class_entry->methods.entry;
|
struct hash_table_entry * methods_hash_table = class_entry->methods.entry;
|
||||||
|
|
||||||
struct hash_table_entry * e = hash_table_find(methods_hash_table_length,
|
struct hash_table_entry * e = hash_table_find2(methods_hash_table_length,
|
||||||
methods_hash_table,
|
methods_hash_table,
|
||||||
method_name,
|
method_name,
|
||||||
method_name_length);
|
method_name_length,
|
||||||
|
method_descriptor,
|
||||||
|
method_descriptor_length);
|
||||||
assert(e != nullptr);
|
assert(e != nullptr);
|
||||||
|
|
||||||
return (struct method_info *)e->value;
|
return (struct method_info *)e->value;
|
||||||
|
@ -43,7 +43,9 @@ struct class_entry * class_resolver_lookup_class(int class_hash_table_length,
|
|||||||
int class_name_length);
|
int class_name_length);
|
||||||
struct method_info * class_resolver_lookup_method(struct class_entry * class_entry,
|
struct method_info * class_resolver_lookup_method(struct class_entry * class_entry,
|
||||||
const uint8_t * method_name,
|
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,
|
struct field_entry * class_resolver_lookup_field(struct class_entry * class_entry,
|
||||||
const uint8_t * field_name,
|
const uint8_t * field_name,
|
||||||
int field_name_length);
|
int field_name_length);
|
||||||
|
@ -920,6 +920,10 @@ void op_invokestatic(struct vm * vm, uint32_t index)
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
assert(method_name_constant->tag == CONSTANT_Utf8);
|
assert(method_name_constant->tag == CONSTANT_Utf8);
|
||||||
#endif
|
#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,
|
struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
|
||||||
vm->class_hash_table.entry,
|
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,
|
struct method_info * method_info = class_resolver_lookup_method(class_entry,
|
||||||
method_name_constant->utf8.bytes,
|
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);
|
assert(method_info != nullptr);
|
||||||
|
|
||||||
/* On successful resolution of the method, the class or interface that
|
/* On successful resolution of the method, the class or interface that
|
||||||
|
@ -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
|
/* Next, if C declares a class or interface initialization method, execute
|
||||||
that method. */
|
that method. */
|
||||||
const uint8_t * method_name = (const uint8_t *)"<clinit>";
|
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,
|
struct method_info * method_info = class_resolver_lookup_method(class_entry,
|
||||||
method_name,
|
method_name,
|
||||||
method_length);
|
method_name_length,
|
||||||
|
method_descriptor,
|
||||||
|
method_descriptor_length);
|
||||||
if (method_info != nullptr) {
|
if (method_info != nullptr) {
|
||||||
assert((method_info->access_flags & METHOD_ACC_STATIC) != 0);
|
assert((method_info->access_flags & METHOD_ACC_STATIC) != 0);
|
||||||
printf("<clinit>\n");
|
printf("<clinit>\n");
|
||||||
|
110
c/hash_table.c
110
c/hash_table.c
@ -1,12 +1,11 @@
|
|||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
#include "hash_table.h"
|
#include "hash_table.h"
|
||||||
|
|
||||||
static uint32_t fnv_1(const uint8_t * buf, int length)
|
static const uint32_t fnv_offset_basis = 0x811c9dc5;
|
||||||
{
|
|
||||||
const uint32_t fnv_offset_basis = 0x811c9dc5;
|
|
||||||
const uint32_t fnv_prime = 0x01000193;
|
|
||||||
|
|
||||||
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++) {
|
for (int i = 0; i < length; i++) {
|
||||||
hash = hash * fnv_prime;
|
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,
|
void hash_table_add(int hash_table_length,
|
||||||
struct hash_table_entry * entry,
|
struct hash_table_entry * entry,
|
||||||
const uint8_t * key,
|
const uint8_t * key,
|
||||||
int key_length,
|
int key_length,
|
||||||
void * value)
|
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];
|
struct hash_table_entry * e = &entry[hash];
|
||||||
|
|
||||||
while (e->next != nullptr) {
|
while (e->next != nullptr) {
|
||||||
@ -44,7 +54,12 @@ void hash_table_add(int hash_table_length,
|
|||||||
e = e->next;
|
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->key_length = key_length;
|
||||||
e->value = value;
|
e->value = value;
|
||||||
}
|
}
|
||||||
@ -63,11 +78,88 @@ 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)
|
||||||
{
|
{
|
||||||
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];
|
struct hash_table_entry * e = &entry[hash];
|
||||||
|
|
||||||
while (e != nullptr && e->key != nullptr) {
|
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;
|
return e;
|
||||||
}
|
}
|
||||||
e = e->next;
|
e = e->next;
|
||||||
|
@ -22,3 +22,18 @@ struct hash_table_entry * hash_table_find(int hash_table_length,
|
|||||||
struct hash_table_entry * entry,
|
struct hash_table_entry * entry,
|
||||||
const uint8_t * key,
|
const uint8_t * key,
|
||||||
int key_length);
|
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);
|
||||||
|
6
c/main.c
6
c/main.c
@ -21,9 +21,13 @@ int main(int argc, const char * argv[])
|
|||||||
|
|
||||||
const char * method_name = "main";
|
const char * method_name = "main";
|
||||||
int method_name_length = string_length(method_name);
|
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,
|
struct method_info * method_info = class_resolver_lookup_method(class_entry,
|
||||||
(const uint8_t *)method_name,
|
(const uint8_t *)method_name,
|
||||||
method_name_length);
|
method_name_length,
|
||||||
|
(const uint8_t *)method_descriptor,
|
||||||
|
method_descriptor_length);
|
||||||
|
|
||||||
struct vm vm;
|
struct vm vm;
|
||||||
vm.class_hash_table.entry = class_hash_table;
|
vm.class_hash_table.entry = class_hash_table;
|
||||||
|
@ -1,5 +1,7 @@
|
|||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
|
|
||||||
|
#include <assert.h>
|
||||||
|
|
||||||
struct arena {
|
struct arena {
|
||||||
uint8_t * mem;
|
uint8_t * mem;
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
@ -16,7 +18,9 @@ struct arena class_arena = {
|
|||||||
|
|
||||||
void * malloc_class_arena(uint32_t size)
|
void * malloc_class_arena(uint32_t size)
|
||||||
{
|
{
|
||||||
|
assert((class_arena.ix & (~3)) == class_arena.ix);
|
||||||
void * ptr = &class_arena.mem[class_arena.ix];
|
void * ptr = &class_arena.mem[class_arena.ix];
|
||||||
|
size = (size + 3) & (~3);
|
||||||
class_arena.ix += size;
|
class_arena.ix += size;
|
||||||
return ptr;
|
return ptr;
|
||||||
}
|
}
|
||||||
|
@ -145,6 +145,12 @@ static uint32_t _strlen(const char * s)
|
|||||||
return si - 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 main()
|
||||||
{
|
{
|
||||||
int hash_table_length = 128 * 2;
|
int hash_table_length = 128 * 2;
|
||||||
@ -170,6 +176,7 @@ int main()
|
|||||||
printf("collision %s\n", e->key);
|
printf("collision %s\n", e->key);
|
||||||
}
|
}
|
||||||
assert(e != nullptr);
|
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
24
p/Instance.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
19
p/StaticMethodOverloading.java
Normal file
19
p/StaticMethodOverloading.java
Normal 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();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user