class_resolver: add constantpool-index-to-{class,method,field,string} cache
Object fields are now tightly packed. The intent is to make Object instances more useful in native methods.
This commit is contained in:
parent
0c41658958
commit
16eb6aa523
@ -12,6 +12,143 @@
|
|||||||
#include "debug_class_file.h"
|
#include "debug_class_file.h"
|
||||||
#include "memory_allocator.h"
|
#include "memory_allocator.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_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];
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(field_descriptor_constant->tag == CONSTANT_Utf8);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
switch (field_descriptor_constant->utf8.bytes[0]) {
|
||||||
|
case 'B': [[fallthrough]];
|
||||||
|
case 'C': [[fallthrough]];
|
||||||
|
case 'F': [[fallthrough]];
|
||||||
|
case 'I': [[fallthrough]];
|
||||||
|
case 'L': [[fallthrough]];
|
||||||
|
case 'S': [[fallthrough]];
|
||||||
|
case 'Z': [[fallthrough]];
|
||||||
|
case '[':
|
||||||
|
return 1;
|
||||||
|
case 'D': [[fallthrough]];
|
||||||
|
case 'J':
|
||||||
|
return 2;
|
||||||
|
default:
|
||||||
|
assert(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static int32_t class_resolver_create_fields_hash_table(struct class_entry * class_entry)
|
||||||
|
{
|
||||||
|
struct class_file * class_file = class_entry->class_file;
|
||||||
|
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)) * class_file->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);
|
||||||
|
printf("hash table entry for field: ");
|
||||||
|
print_utf8_string(name_constant);
|
||||||
|
printf("\n");
|
||||||
|
|
||||||
|
struct field_info * field_info = &class_file->fields[i];
|
||||||
|
|
||||||
|
if (field_info->access_flags & FIELD_ACC_STATIC) {
|
||||||
|
field_entry[i].static_index = static_index;
|
||||||
|
static_index += field_size(class_file, field_info);
|
||||||
|
} else {
|
||||||
|
field_entry[i].instance_index = instance_index;
|
||||||
|
instance_index += field_size(class_file, field_info);
|
||||||
|
}
|
||||||
|
field_entry[i].field_info = field_info;
|
||||||
|
|
||||||
|
hash_table_add(fields_hash_table_length,
|
||||||
|
fields_hash_table,
|
||||||
|
name_constant->utf8.bytes,
|
||||||
|
name_constant->utf8.length,
|
||||||
|
(void *)&field_entry[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
class_entry->fields.length = fields_hash_table_length;
|
||||||
|
class_entry->fields.entry = fields_hash_table;
|
||||||
|
|
||||||
|
return static_index;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void class_resolver_create_methods_hash_table(struct class_entry * class_entry)
|
||||||
|
{
|
||||||
|
struct class_file * class_file = class_entry->class_file;
|
||||||
|
int methods_hash_table_length = class_file->methods_count * 2;
|
||||||
|
uint32_t methods_hash_table_size = (sizeof (struct hash_table_entry)) * methods_hash_table_length;
|
||||||
|
struct hash_table_entry * methods_hash_table = malloc_class_arena(methods_hash_table_size);
|
||||||
|
for (int i = 0; i < class_file->methods_count; i++) {
|
||||||
|
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_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->methods.length = methods_hash_table_length;
|
||||||
|
class_entry->methods.entry = methods_hash_table;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void class_resolver_allocate_static_fields(struct class_entry * class_entry, int32_t static_field_count)
|
||||||
|
{
|
||||||
|
uint32_t static_fields_size = (sizeof (int32_t)) * static_field_count;
|
||||||
|
int32_t * static_fields = malloc_class_arena(static_fields_size);
|
||||||
|
|
||||||
|
for (int i = 0; i < static_field_count; i++) {
|
||||||
|
static_fields[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
class_entry->static_fields = static_fields;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void class_resolver_allocate_attribute_entry(struct class_entry * class_entry)
|
||||||
|
{
|
||||||
|
struct class_file * class_file = class_entry->class_file;
|
||||||
|
uint32_t attribute_entry_size = (sizeof (union attribute_entry)) * class_file->constant_pool_count;
|
||||||
|
union attribute_entry * attribute_entry = malloc_class_arena(attribute_entry_size);
|
||||||
|
|
||||||
|
for (int i = 0; i < class_file->constant_pool_count; i++) {
|
||||||
|
attribute_entry[i].class_entry = nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
class_entry->attribute_entry = attribute_entry;
|
||||||
|
}
|
||||||
|
|
||||||
struct hash_table_entry * class_resolver_load_from_filenames(const char * filenames[], int length, int * hash_table_length)
|
struct hash_table_entry * class_resolver_load_from_filenames(const char * filenames[], int length, int * hash_table_length)
|
||||||
{
|
{
|
||||||
int class_hash_table_length = length * 2;
|
int class_hash_table_length = length * 2;
|
||||||
@ -48,80 +185,20 @@ struct hash_table_entry * class_resolver_load_from_filenames(const char * filena
|
|||||||
class_name_length,
|
class_name_length,
|
||||||
&class_entry[i]);
|
&class_entry[i]);
|
||||||
|
|
||||||
// make hash table for strings
|
|
||||||
int strings_hash_table_length = class_file->constant_pool_count;
|
|
||||||
uint32_t strings_hash_table_size = (sizeof (struct hash_table_entry)) * strings_hash_table_length;
|
|
||||||
struct hash_table_entry * strings_hash_table = malloc_class_arena(strings_hash_table_size);
|
|
||||||
class_entry[i].strings.length = strings_hash_table_length;
|
|
||||||
class_entry[i].strings.entry = strings_hash_table;
|
|
||||||
|
|
||||||
// make hash table for interfaces
|
// make hash table for interfaces
|
||||||
/*
|
class_resolver_create_interfaces_hash_table(&class_entry[i]);
|
||||||
if (class_file->interfaces_count != 0) {
|
|
||||||
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++) {
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
*/
|
|
||||||
// make hash table for fields
|
// make hash table for fields
|
||||||
if (class_file->fields_count != 0) {
|
int32_t static_field_count = class_resolver_create_fields_hash_table(&class_entry[i]);
|
||||||
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)) * 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;
|
|
||||||
struct constant * name_constant = &class_file->constant_pool[name_index - 1];
|
|
||||||
assert(name_constant->tag == CONSTANT_Utf8);
|
|
||||||
printf("hash table entry for field: ");
|
|
||||||
print_utf8_string(name_constant);
|
|
||||||
printf("\n");
|
|
||||||
|
|
||||||
field_entry[i].field_info = &class_file->fields[i];
|
|
||||||
field_entry[i].value64 = 0;
|
|
||||||
|
|
||||||
hash_table_add(fields_hash_table_length,
|
|
||||||
fields_hash_table,
|
|
||||||
name_constant->utf8.bytes,
|
|
||||||
name_constant->utf8.length,
|
|
||||||
(void *)&field_entry[i]);
|
|
||||||
}
|
|
||||||
|
|
||||||
class_entry[i].fields.length = fields_hash_table_length;
|
|
||||||
class_entry[i].fields.entry = fields_hash_table;
|
|
||||||
}
|
|
||||||
|
|
||||||
// make hash table for methods
|
// make hash table for methods
|
||||||
if (class_file->methods_count != 0) {
|
class_resolver_create_methods_hash_table(&class_entry[i]);
|
||||||
int methods_hash_table_length = class_file->methods_count * 2;
|
|
||||||
uint32_t methods_hash_table_size = (sizeof (struct hash_table_entry)) * methods_hash_table_length;
|
|
||||||
struct hash_table_entry * methods_hash_table = malloc_class_arena(methods_hash_table_size);
|
|
||||||
for (int i = 0; i < class_file->methods_count; i++) {
|
|
||||||
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_add2(methods_hash_table_length,
|
// allocate static fields
|
||||||
methods_hash_table,
|
class_resolver_allocate_static_fields(&class_entry[i], static_field_count);
|
||||||
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;
|
// allocate attribute_entry
|
||||||
class_entry[i].methods.entry = methods_hash_table;
|
class_resolver_allocate_attribute_entry(&class_entry[i]);
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
*hash_table_length = class_hash_table_length;
|
*hash_table_length = class_hash_table_length;
|
||||||
@ -147,8 +224,38 @@ struct class_entry * class_resolver_lookup_class(int class_hash_table_length,
|
|||||||
return (struct class_entry *)e->value;
|
return (struct class_entry *)e->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash_table_length,
|
||||||
|
struct hash_table_entry * class_hash_table,
|
||||||
|
struct class_entry * class_entry,
|
||||||
|
int32_t class_index)
|
||||||
|
{
|
||||||
|
if (class_entry->attribute_entry[class_index - 1].class_entry != nullptr) {
|
||||||
|
printf("class_resolver_lookup_class_from_class_index %d: [cached]\n", class_index);
|
||||||
|
return class_entry->attribute_entry[class_index - 1].class_entry;
|
||||||
|
}
|
||||||
|
|
||||||
struct field_entry * class_resolver_lookup_field(struct class_entry * class_entry,
|
struct constant * class_constant = &class_entry->class_file->constant_pool[class_index - 1];
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(class_constant->tag == CONSTANT_Class);
|
||||||
|
#endif
|
||||||
|
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct class_entry * _class_entry = class_resolver_lookup_class(class_hash_table_length,
|
||||||
|
class_hash_table,
|
||||||
|
class_name_constant->utf8.bytes,
|
||||||
|
class_name_constant->utf8.length);
|
||||||
|
|
||||||
|
// cache the result
|
||||||
|
class_entry->attribute_entry[class_index - 1].class_entry = _class_entry;
|
||||||
|
|
||||||
|
return _class_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct field_entry * class_resolver_lookup_field(int fields_hash_table_length,
|
||||||
|
struct hash_table_entry * fields_hash_table,
|
||||||
const uint8_t * field_name,
|
const uint8_t * field_name,
|
||||||
int field_name_length)
|
int field_name_length)
|
||||||
{
|
{
|
||||||
@ -156,9 +263,6 @@ struct field_entry * class_resolver_lookup_field(struct class_entry * class_entr
|
|||||||
for (int i = 0; i < field_name_length; i++) { fputc(field_name[i], stdout); }
|
for (int i = 0; i < field_name_length; i++) { fputc(field_name[i], stdout); }
|
||||||
fputc('\n', stdout);
|
fputc('\n', stdout);
|
||||||
|
|
||||||
int fields_hash_table_length = class_entry->fields.length;
|
|
||||||
struct hash_table_entry * fields_hash_table = class_entry->fields.entry;
|
|
||||||
|
|
||||||
struct hash_table_entry * e = hash_table_find(fields_hash_table_length,
|
struct hash_table_entry * e = hash_table_find(fields_hash_table_length,
|
||||||
fields_hash_table,
|
fields_hash_table,
|
||||||
field_name,
|
field_name,
|
||||||
@ -168,7 +272,42 @@ struct field_entry * class_resolver_lookup_field(struct class_entry * class_entr
|
|||||||
return (struct field_entry *)e->value;
|
return (struct field_entry *)e->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
struct method_info * class_resolver_lookup_method(struct class_entry * class_entry,
|
struct field_entry * class_resolver_lookup_field_from_fieldref_index(int fields_hash_table_length,
|
||||||
|
struct hash_table_entry * fields_hash_table,
|
||||||
|
struct class_entry * class_entry,
|
||||||
|
int fieldref_index)
|
||||||
|
{
|
||||||
|
if (class_entry->attribute_entry[fieldref_index - 1].field_entry != nullptr) {
|
||||||
|
printf("class_resolver_lookup_method_from_fieldref_index %d: [cached]\n", fieldref_index);
|
||||||
|
return class_entry->attribute_entry[fieldref_index - 1].field_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct constant * fieldref_constant = &class_entry->class_file->constant_pool[fieldref_index - 1];
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(fieldref_constant->tag == CONSTANT_Fieldref);
|
||||||
|
#endif
|
||||||
|
struct constant * nameandtype_constant = &class_entry->class_file->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1];
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
|
||||||
|
#endif
|
||||||
|
struct constant * field_name_constant = &class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(field_name_constant->tag == CONSTANT_Utf8);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct field_entry * field_entry = class_resolver_lookup_field(fields_hash_table_length,
|
||||||
|
fields_hash_table,
|
||||||
|
field_name_constant->utf8.bytes,
|
||||||
|
field_name_constant->utf8.length);
|
||||||
|
|
||||||
|
// cache the result
|
||||||
|
class_entry->attribute_entry[fieldref_index - 1].field_entry = field_entry;
|
||||||
|
|
||||||
|
return field_entry;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct method_info * class_resolver_lookup_method(int methods_hash_table_length,
|
||||||
|
struct hash_table_entry * methods_hash_table,
|
||||||
const uint8_t * method_name,
|
const uint8_t * method_name,
|
||||||
int method_name_length,
|
int method_name_length,
|
||||||
const uint8_t * method_descriptor,
|
const uint8_t * method_descriptor,
|
||||||
@ -180,9 +319,6 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent
|
|||||||
for (int i = 0; i < method_descriptor_length; i++) { fputc(method_descriptor[i], 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;
|
|
||||||
struct hash_table_entry * methods_hash_table = class_entry->methods.entry;
|
|
||||||
|
|
||||||
struct hash_table_entry * e = hash_table_find2(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,
|
||||||
@ -195,22 +331,55 @@ struct method_info * class_resolver_lookup_method(struct class_entry * class_ent
|
|||||||
return (struct method_info *)e->value;
|
return (struct method_info *)e->value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct method_info * class_resolver_lookup_method_from_methodref_index(int methods_hash_table_length,
|
||||||
|
struct hash_table_entry * methods_hash_table,
|
||||||
|
struct class_entry * class_entry,
|
||||||
|
int methodref_index)
|
||||||
|
{
|
||||||
|
if (class_entry->attribute_entry[methodref_index - 1].method_info != nullptr) {
|
||||||
|
printf("class_resolver_lookup_method_from_methodref_index %d: [cached]\n", methodref_index);
|
||||||
|
return class_entry->attribute_entry[methodref_index - 1].method_info;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct constant * methodref_constant = &class_entry->class_file->constant_pool[methodref_index - 1];
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(methodref_constant->tag == CONSTANT_Methodref);
|
||||||
|
#endif
|
||||||
|
struct constant * nameandtype_constant = &class_entry->class_file->constant_pool[methodref_constant->methodref.name_and_type_index - 1];
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
|
||||||
|
#endif
|
||||||
|
struct constant * method_name_constant = &class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(method_name_constant->tag == CONSTANT_Utf8);
|
||||||
|
#endif
|
||||||
|
struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
|
||||||
|
#ifdef DEBUG
|
||||||
|
assert(method_descriptor_constant->tag == CONSTANT_Utf8);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
struct method_info * method_info = class_resolver_lookup_method(methods_hash_table_length,
|
||||||
|
methods_hash_table,
|
||||||
|
method_name_constant->utf8.bytes,
|
||||||
|
method_name_constant->utf8.length,
|
||||||
|
method_descriptor_constant->utf8.bytes,
|
||||||
|
method_descriptor_constant->utf8.length);
|
||||||
|
|
||||||
|
// cache the result
|
||||||
|
class_entry->attribute_entry[methodref_index - 1].method_info = method_info;
|
||||||
|
|
||||||
|
return method_info;
|
||||||
|
}
|
||||||
|
|
||||||
int32_t * class_resolver_lookup_string(int class_hash_table_length,
|
int32_t * class_resolver_lookup_string(int class_hash_table_length,
|
||||||
struct hash_table_entry * class_hash_table,
|
struct hash_table_entry * class_hash_table,
|
||||||
struct class_entry * class_entry,
|
struct class_entry * class_entry,
|
||||||
const int string_index)
|
const int string_index)
|
||||||
{
|
{
|
||||||
printf("class_resolver_lookup_string: %d\n", string_index);
|
printf("class_resolver_lookup_string: %d\n", string_index);
|
||||||
|
if (class_entry->attribute_entry[string_index - 1].string_objectref != nullptr) {
|
||||||
int strings_hash_table_length = class_entry->strings.length;
|
printf("class_resolver_lookup_string: [cached]\n");
|
||||||
struct hash_table_entry * strings_hash_table = class_entry->strings.entry;
|
return class_entry->attribute_entry[string_index - 1].string_objectref;
|
||||||
|
|
||||||
struct hash_table_entry * e = hash_table_find_int(strings_hash_table_length,
|
|
||||||
strings_hash_table,
|
|
||||||
string_index);
|
|
||||||
if (e != nullptr) {
|
|
||||||
int32_t * objectref = (int32_t *)e->value;
|
|
||||||
return objectref;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_index - 1];
|
struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_index - 1];
|
||||||
@ -235,10 +404,8 @@ int32_t * class_resolver_lookup_string(int class_hash_table_length,
|
|||||||
objectref[0] = (int32_t)string_class_entry;
|
objectref[0] = (int32_t)string_class_entry;
|
||||||
objectref[1] = (int32_t)arrayref;
|
objectref[1] = (int32_t)arrayref;
|
||||||
|
|
||||||
hash_table_add_int(strings_hash_table_length,
|
// cache the result
|
||||||
strings_hash_table,
|
class_entry->attribute_entry[string_index - 1].string_objectref = objectref;
|
||||||
string_index,
|
|
||||||
objectref);
|
|
||||||
|
|
||||||
return objectref;
|
return objectref;
|
||||||
}
|
}
|
||||||
|
@ -5,28 +5,32 @@
|
|||||||
#include "class_file.h"
|
#include "class_file.h"
|
||||||
#include "hash_table.h"
|
#include "hash_table.h"
|
||||||
|
|
||||||
struct field_entry {
|
|
||||||
struct field_info * field_info;
|
|
||||||
union {
|
|
||||||
uint64_t value64;
|
|
||||||
uint32_t value32;
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
enum initialization_state {
|
enum initialization_state {
|
||||||
CLASS_UNINITIALIZED,
|
CLASS_UNINITIALIZED,
|
||||||
CLASS_INITIALIZING,
|
CLASS_INITIALIZING,
|
||||||
CLASS_INITIALIZED,
|
CLASS_INITIALIZED,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
union attribute_entry {
|
||||||
|
struct class_entry * class_entry;
|
||||||
|
struct method_info * method_info;
|
||||||
|
struct field_entry * field_entry;
|
||||||
|
int32_t * string_objectref;
|
||||||
|
};
|
||||||
|
|
||||||
|
struct field_entry {
|
||||||
|
struct field_info * field_info;
|
||||||
|
union {
|
||||||
|
int32_t instance_index;
|
||||||
|
int32_t static_index;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
struct class_entry {
|
struct class_entry {
|
||||||
struct class_file * class_file;
|
struct class_file * class_file;
|
||||||
enum initialization_state initialization_state;
|
enum initialization_state initialization_state;
|
||||||
|
union attribute_entry * attribute_entry;
|
||||||
struct {
|
int32_t * static_fields;
|
||||||
int length;
|
|
||||||
struct hash_table_entry * entry;
|
|
||||||
} strings;
|
|
||||||
|
|
||||||
struct {
|
struct {
|
||||||
int length;
|
int length;
|
||||||
@ -49,14 +53,29 @@ struct class_entry * class_resolver_lookup_class(int class_hash_table_length,
|
|||||||
struct hash_table_entry * class_hash_table,
|
struct hash_table_entry * class_hash_table,
|
||||||
const uint8_t * class_name,
|
const uint8_t * class_name,
|
||||||
int class_name_length);
|
int class_name_length);
|
||||||
struct method_info * class_resolver_lookup_method(struct class_entry * class_entry,
|
struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash_table_length,
|
||||||
|
struct hash_table_entry * class_hash_table,
|
||||||
|
struct class_entry * class_entry,
|
||||||
|
int32_t class_index);
|
||||||
|
struct method_info * class_resolver_lookup_method(int methods_hash_table_length,
|
||||||
|
struct hash_table_entry * methods_hash_table,
|
||||||
const uint8_t * method_name,
|
const uint8_t * method_name,
|
||||||
int method_name_length,
|
int method_name_length,
|
||||||
const uint8_t * method_descriptor,
|
const uint8_t * method_descriptor,
|
||||||
int method_descriptor_length);
|
int method_descriptor_length);
|
||||||
struct field_entry * class_resolver_lookup_field(struct class_entry * class_entry,
|
struct method_info * class_resolver_lookup_method_from_methodref_index(int methods_hash_table_length,
|
||||||
|
struct hash_table_entry * methods_hash_table,
|
||||||
|
struct class_entry * class_entry,
|
||||||
|
int methodref_index);
|
||||||
|
struct field_entry * class_resolver_lookup_field(int fields_hash_table_length,
|
||||||
|
struct hash_table_entry * fields_hash_table,
|
||||||
const uint8_t * field_name,
|
const uint8_t * field_name,
|
||||||
int field_name_length);
|
int index);
|
||||||
|
struct field_entry * class_resolver_lookup_field_from_fieldref_index(int fields_hash_table_length,
|
||||||
|
struct hash_table_entry * fields_hash_table,
|
||||||
|
struct class_entry * class_entry,
|
||||||
|
int fieldref_index);
|
||||||
|
|
||||||
int32_t * class_resolver_lookup_string(int class_hash_table_length,
|
int32_t * class_resolver_lookup_string(int class_hash_table_length,
|
||||||
struct hash_table_entry * class_hash_table,
|
struct hash_table_entry * class_hash_table,
|
||||||
struct class_entry * class_entry,
|
struct class_entry * class_entry,
|
||||||
|
45
c/execute.c
45
c/execute.c
@ -683,10 +683,7 @@ void op_getfield(struct vm * vm, uint32_t index)
|
|||||||
&field_entry,
|
&field_entry,
|
||||||
&field_descriptor_constant);
|
&field_descriptor_constant);
|
||||||
|
|
||||||
//assert(field_descriptor_constant->utf8.length == 1 || field_descriptor_constant->utf8.length == 2);
|
printf("putfield instance_index %d\n", field_entry->instance_index);
|
||||||
|
|
||||||
uint32_t field_index = field_entry->field_info - class_entry->class_file->fields;
|
|
||||||
printf("putfield field_index %d\n", field_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);
|
||||||
int32_t * objectfields = &objectref[1];
|
int32_t * objectfields = &objectref[1];
|
||||||
@ -701,15 +698,15 @@ void op_getfield(struct vm * vm, uint32_t index)
|
|||||||
case 'Z': [[fallthrough]];
|
case 'Z': [[fallthrough]];
|
||||||
case '[':
|
case '[':
|
||||||
{
|
{
|
||||||
uint32_t value = objectfields[field_index];
|
uint32_t value = objectfields[field_entry->instance_index];
|
||||||
operand_stack_push_u32(vm->current_frame, value);
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'D': [[fallthrough]];
|
case 'D': [[fallthrough]];
|
||||||
case 'J':
|
case 'J':
|
||||||
{
|
{
|
||||||
uint32_t low = objectfields[field_index * 2];
|
uint32_t low = objectfields[field_entry->instance_index];
|
||||||
uint32_t high = objectfields[field_index * 2 + 1];
|
uint32_t high = objectfields[field_entry->instance_index + 1];
|
||||||
operand_stack_push_u32(vm->current_frame, low);
|
operand_stack_push_u32(vm->current_frame, low);
|
||||||
operand_stack_push_u32(vm->current_frame, high);
|
operand_stack_push_u32(vm->current_frame, high);
|
||||||
}
|
}
|
||||||
@ -736,8 +733,6 @@ void op_getstatic(struct vm * vm, uint32_t index)
|
|||||||
if (!vm_initialize_class(vm, class_entry))
|
if (!vm_initialize_class(vm, class_entry))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//assert(field_descriptor_constant->utf8.length == 1 || field_descriptor_constant->utf8.length == 2);
|
|
||||||
|
|
||||||
switch (field_descriptor_constant->utf8.bytes[0]) {
|
switch (field_descriptor_constant->utf8.bytes[0]) {
|
||||||
case 'B': [[fallthrough]];
|
case 'B': [[fallthrough]];
|
||||||
case 'C': [[fallthrough]];
|
case 'C': [[fallthrough]];
|
||||||
@ -748,15 +743,17 @@ void op_getstatic(struct vm * vm, uint32_t index)
|
|||||||
case 'Z': [[fallthrough]];
|
case 'Z': [[fallthrough]];
|
||||||
case '[':
|
case '[':
|
||||||
{
|
{
|
||||||
uint32_t value = field_entry->value32;
|
uint32_t value = class_entry->static_fields[field_entry->static_index];
|
||||||
operand_stack_push_u32(vm->current_frame, value);
|
operand_stack_push_u32(vm->current_frame, value);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'D': [[fallthrough]];
|
case 'D': [[fallthrough]];
|
||||||
case 'J':
|
case 'J':
|
||||||
{
|
{
|
||||||
uint64_t value = field_entry->value64;
|
uint32_t low = class_entry->static_fields[field_entry->static_index];
|
||||||
operand_stack_push_u64(vm->current_frame, value);
|
uint32_t high = class_entry->static_fields[field_entry->static_index + 1];
|
||||||
|
operand_stack_push_u32(vm->current_frame, low);
|
||||||
|
operand_stack_push_u32(vm->current_frame, high);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1709,7 +1706,8 @@ void op_putfield(struct vm * vm, uint32_t index)
|
|||||||
struct class_entry * class_entry;
|
struct class_entry * class_entry;
|
||||||
struct field_entry * field_entry;
|
struct field_entry * field_entry;
|
||||||
struct constant * field_descriptor_constant;
|
struct constant * field_descriptor_constant;
|
||||||
class_entry_field_entry_from_constant_index(vm, index,
|
class_entry_field_entry_from_constant_index(vm,
|
||||||
|
index,
|
||||||
&class_entry,
|
&class_entry,
|
||||||
&field_entry,
|
&field_entry,
|
||||||
&field_descriptor_constant);
|
&field_descriptor_constant);
|
||||||
@ -1722,10 +1720,7 @@ void op_putfield(struct vm * vm, uint32_t index)
|
|||||||
type or an array type, then the value must be a value of the field descriptor
|
type or an array type, then the value must be a value of the field descriptor
|
||||||
type. */
|
type. */
|
||||||
|
|
||||||
//assert(field_descriptor_constant->utf8.length == 1 || field_descriptor_constant->utf8.length == 2);
|
printf("putfield instance_index %d\n", field_entry->instance_index);
|
||||||
|
|
||||||
uint32_t field_index = field_entry->field_info - class_entry->class_file->fields;
|
|
||||||
printf("putfield field_index %d\n", field_index);
|
|
||||||
|
|
||||||
switch (field_descriptor_constant->utf8.bytes[0]) {
|
switch (field_descriptor_constant->utf8.bytes[0]) {
|
||||||
case 'B': [[fallthrough]];
|
case 'B': [[fallthrough]];
|
||||||
@ -1740,7 +1735,7 @@ void op_putfield(struct vm * vm, uint32_t index)
|
|||||||
uint32_t value = operand_stack_pop_u32(vm->current_frame);
|
uint32_t value = operand_stack_pop_u32(vm->current_frame);
|
||||||
int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
|
int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
|
||||||
int32_t * objectfields = &objectref[1];
|
int32_t * objectfields = &objectref[1];
|
||||||
objectfields[field_index] = value;
|
objectfields[field_entry->instance_index] = value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'D': [[fallthrough]];
|
case 'D': [[fallthrough]];
|
||||||
@ -1750,8 +1745,8 @@ void op_putfield(struct vm * vm, uint32_t index)
|
|||||||
uint32_t low = operand_stack_pop_u32(vm->current_frame);
|
uint32_t low = operand_stack_pop_u32(vm->current_frame);
|
||||||
int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
|
int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
|
||||||
int32_t * objectfields = &objectref[1];
|
int32_t * objectfields = &objectref[1];
|
||||||
objectfields[field_index * 2 + 1] = high;
|
objectfields[field_entry->instance_index + 1] = high;
|
||||||
objectfields[field_index * 2] = low;
|
objectfields[field_entry->instance_index] = low;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
@ -1784,8 +1779,6 @@ void op_putstatic(struct vm * vm, uint32_t index)
|
|||||||
if (!vm_initialize_class(vm, class_entry))
|
if (!vm_initialize_class(vm, class_entry))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//assert(field_descriptor_constant->utf8.length == 1 || field_descriptor_constant->utf8.length == 2);
|
|
||||||
|
|
||||||
switch (field_descriptor_constant->utf8.bytes[0]) {
|
switch (field_descriptor_constant->utf8.bytes[0]) {
|
||||||
case 'B': [[fallthrough]];
|
case 'B': [[fallthrough]];
|
||||||
case 'C': [[fallthrough]];
|
case 'C': [[fallthrough]];
|
||||||
@ -1797,14 +1790,16 @@ void op_putstatic(struct vm * vm, uint32_t index)
|
|||||||
case '[':
|
case '[':
|
||||||
{
|
{
|
||||||
uint32_t value = operand_stack_pop_u32(vm->current_frame);
|
uint32_t value = operand_stack_pop_u32(vm->current_frame);
|
||||||
field_entry->value32 = value;
|
class_entry->static_fields[field_entry->static_index] = value;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'D': [[fallthrough]];
|
case 'D': [[fallthrough]];
|
||||||
case 'J':
|
case 'J':
|
||||||
{
|
{
|
||||||
uint64_t value = operand_stack_pop_u64(vm->current_frame);
|
uint32_t high = operand_stack_pop_u32(vm->current_frame);
|
||||||
field_entry->value64 = value;
|
uint32_t low = operand_stack_pop_u32(vm->current_frame);
|
||||||
|
class_entry->static_fields[field_entry->static_index + 1] = high;
|
||||||
|
class_entry->static_fields[field_entry->static_index] = low;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
#include "debug_class_file.h"
|
#include "debug_class_file.h"
|
||||||
|
|
||||||
static inline void class_entry_field_entry_from_constant_index(struct vm * vm,
|
static inline void class_entry_field_entry_from_constant_index(struct vm * vm,
|
||||||
uint32_t index,
|
int32_t index,
|
||||||
struct class_entry ** class_entry,
|
struct class_entry ** class_entry,
|
||||||
struct field_entry ** field_entry,
|
struct field_entry ** field_entry,
|
||||||
struct constant ** field_descriptor_constant)
|
struct constant ** field_descriptor_constant)
|
||||||
@ -10,41 +10,35 @@ static inline void class_entry_field_entry_from_constant_index(struct vm * vm,
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
assert(fieldref_constant->tag == CONSTANT_Fieldref);
|
assert(fieldref_constant->tag == CONSTANT_Fieldref);
|
||||||
#endif
|
#endif
|
||||||
struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[fieldref_constant->fieldref.class_index - 1];
|
|
||||||
#ifdef DEBUG
|
*class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length,
|
||||||
assert(class_constant->tag == CONSTANT_Class);
|
vm->class_hash_table.entry,
|
||||||
#endif
|
vm->current_frame->class_entry,
|
||||||
|
fieldref_constant->fieldref.class_index);
|
||||||
|
|
||||||
|
assert(*class_entry != nullptr);
|
||||||
|
|
||||||
|
int fields_hash_table_length = (*class_entry)->fields.length;
|
||||||
|
struct hash_table_entry * fields_hash_table = (*class_entry)->fields.entry;
|
||||||
|
|
||||||
|
*field_entry = class_resolver_lookup_field_from_fieldref_index(fields_hash_table_length,
|
||||||
|
fields_hash_table,
|
||||||
|
vm->current_frame->class_entry,
|
||||||
|
index);
|
||||||
|
assert(*field_entry != nullptr);
|
||||||
|
|
||||||
struct constant * nameandtype_constant = &vm->current_frame->class_entry->class_file->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1];
|
struct constant * nameandtype_constant = &vm->current_frame->class_entry->class_file->constant_pool[fieldref_constant->fieldref.name_and_type_index - 1];
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
|
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
|
||||||
#endif
|
#endif
|
||||||
struct constant * class_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
|
||||||
#ifdef DEBUG
|
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
|
||||||
#endif
|
|
||||||
struct constant * field_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];
|
|
||||||
#ifdef DEBUG
|
|
||||||
assert(field_name_constant->tag == CONSTANT_Utf8);
|
|
||||||
#endif
|
|
||||||
*field_descriptor_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
|
*field_descriptor_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
assert((*field_descriptor_constant)->tag == CONSTANT_Utf8);
|
assert((*field_descriptor_constant)->tag == CONSTANT_Utf8);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
*class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
|
|
||||||
vm->class_hash_table.entry,
|
|
||||||
class_name_constant->utf8.bytes,
|
|
||||||
class_name_constant->utf8.length);
|
|
||||||
assert(*class_entry != nullptr);
|
|
||||||
|
|
||||||
*field_entry = class_resolver_lookup_field(*class_entry,
|
|
||||||
field_name_constant->utf8.bytes,
|
|
||||||
field_name_constant->utf8.length);
|
|
||||||
assert(*field_entry != nullptr);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void class_entry_method_info_from_constant_index(struct vm * vm,
|
static inline void class_entry_method_info_from_constant_index(struct vm * vm,
|
||||||
uint32_t index,
|
int32_t index,
|
||||||
struct class_entry ** class_entry,
|
struct class_entry ** class_entry,
|
||||||
struct method_info ** method_info)
|
struct method_info ** method_info)
|
||||||
{
|
{
|
||||||
@ -52,37 +46,19 @@ static inline void class_entry_method_info_from_constant_index(struct vm * vm,
|
|||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
assert(methodref_constant->tag == CONSTANT_Methodref);
|
assert(methodref_constant->tag == CONSTANT_Methodref);
|
||||||
#endif
|
#endif
|
||||||
struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[methodref_constant->methodref.class_index - 1];
|
|
||||||
#ifdef DEBUG
|
|
||||||
assert(class_constant->tag == CONSTANT_Class);
|
|
||||||
#endif
|
|
||||||
struct constant * nameandtype_constant = &vm->current_frame->class_entry->class_file->constant_pool[methodref_constant->methodref.name_and_type_index - 1];
|
|
||||||
#ifdef DEBUG
|
|
||||||
assert(nameandtype_constant->tag == CONSTANT_NameAndType);
|
|
||||||
#endif
|
|
||||||
struct constant * class_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
|
|
||||||
#ifdef DEBUG
|
|
||||||
assert(class_name_constant->tag == CONSTANT_Utf8);
|
|
||||||
#endif
|
|
||||||
struct constant * method_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.name_index - 1];
|
|
||||||
#ifdef DEBUG
|
|
||||||
assert(method_name_constant->tag == CONSTANT_Utf8);
|
|
||||||
#endif
|
|
||||||
struct constant * method_descriptor_constant = &vm->current_frame->class_entry->class_file->constant_pool[nameandtype_constant->nameandtype.descriptor_index - 1];
|
|
||||||
#ifdef DEBUG
|
|
||||||
assert(method_descriptor_constant->tag == CONSTANT_Utf8);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
*class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
|
*class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length,
|
||||||
vm->class_hash_table.entry,
|
vm->class_hash_table.entry,
|
||||||
class_name_constant->utf8.bytes,
|
vm->current_frame->class_entry,
|
||||||
class_name_constant->utf8.length);
|
methodref_constant->methodref.class_index);
|
||||||
assert(*class_entry != nullptr);
|
assert(*class_entry != nullptr);
|
||||||
|
|
||||||
*method_info = class_resolver_lookup_method(*class_entry,
|
int methods_hash_table_length = (*class_entry)->methods.length;
|
||||||
method_name_constant->utf8.bytes,
|
struct hash_table_entry * methods_hash_table = (*class_entry)->methods.entry;
|
||||||
method_name_constant->utf8.length,
|
|
||||||
method_descriptor_constant->utf8.bytes,
|
*method_info = class_resolver_lookup_method_from_methodref_index(methods_hash_table_length,
|
||||||
method_descriptor_constant->utf8.length);
|
methods_hash_table,
|
||||||
|
vm->current_frame->class_entry,
|
||||||
|
index);
|
||||||
assert(*method_info != nullptr);
|
assert(*method_info != nullptr);
|
||||||
}
|
}
|
||||||
|
20
c/frame.c
20
c/frame.c
@ -133,13 +133,19 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
|
|||||||
|
|
||||||
struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1];
|
struct constant * name_constant = &class_file->constant_pool[field_info->name_index - 1];
|
||||||
assert(name_constant->tag == CONSTANT_Utf8);
|
assert(name_constant->tag == CONSTANT_Utf8);
|
||||||
struct field_entry * field_entry = class_resolver_lookup_field(class_entry,
|
|
||||||
|
int fields_hash_table_length = class_entry->fields.length;
|
||||||
|
struct hash_table_entry * fields_hash_table = class_entry->fields.entry;
|
||||||
|
|
||||||
|
struct field_entry * field_entry = class_resolver_lookup_field(fields_hash_table_length,
|
||||||
|
fields_hash_table,
|
||||||
name_constant->utf8.bytes,
|
name_constant->utf8.bytes,
|
||||||
name_constant->utf8.length);
|
name_constant->utf8.length);
|
||||||
assert(field_entry != nullptr);
|
assert(field_info != nullptr);
|
||||||
field_entry->value32 = constantvalue->integer.bytes;
|
class_entry->static_fields[field_entry->static_index] = constantvalue->integer.bytes;
|
||||||
printf(" constantvalue: %d\n", field_entry->value32);
|
printf(" constantvalue: %d\n", constantvalue->integer.bytes);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -152,7 +158,11 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
|
|||||||
const uint8_t * method_descriptor = (const uint8_t *)"()V";
|
const uint8_t * method_descriptor = (const uint8_t *)"()V";
|
||||||
int method_descriptor_length = 3;
|
int method_descriptor_length = 3;
|
||||||
|
|
||||||
struct method_info * method_info = class_resolver_lookup_method(class_entry,
|
int methods_hash_table_length = class_entry->methods.length;
|
||||||
|
struct hash_table_entry * methods_hash_table = class_entry->methods.entry;
|
||||||
|
|
||||||
|
struct method_info * method_info = class_resolver_lookup_method(methods_hash_table_length,
|
||||||
|
methods_hash_table,
|
||||||
method_name,
|
method_name,
|
||||||
method_name_length,
|
method_name_length,
|
||||||
method_descriptor,
|
method_descriptor,
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
#include <assert.h>
|
||||||
|
|
||||||
#include "malloc.h"
|
#include "malloc.h"
|
||||||
#include "hash_table.h"
|
#include "hash_table.h"
|
||||||
|
|
||||||
@ -41,6 +43,7 @@ void hash_table_add(int hash_table_length,
|
|||||||
int key_length,
|
int key_length,
|
||||||
void * value)
|
void * value)
|
||||||
{
|
{
|
||||||
|
assert(hash_table_length != 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];
|
||||||
|
|
||||||
@ -78,6 +81,7 @@ 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);
|
||||||
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];
|
||||||
|
|
||||||
@ -115,6 +119,7 @@ void hash_table_add2(int hash_table_length,
|
|||||||
int key2_length,
|
int key2_length,
|
||||||
void * value)
|
void * value)
|
||||||
{
|
{
|
||||||
|
assert(hash_table_length != 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);
|
||||||
hash = fnv_1(hash, key2, key2_length);
|
hash = fnv_1(hash, key2, key2_length);
|
||||||
@ -146,6 +151,7 @@ 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);
|
||||||
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);
|
||||||
hash = fnv_1(hash, key2, key2_length);
|
hash = fnv_1(hash, key2, key2_length);
|
||||||
@ -167,6 +173,7 @@ struct hash_table_entry * hash_table_find2(int hash_table_length,
|
|||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
void hash_table_add_int(int hash_table_length,
|
void hash_table_add_int(int hash_table_length,
|
||||||
struct hash_table_entry * entry,
|
struct hash_table_entry * entry,
|
||||||
int key,
|
int key,
|
||||||
@ -188,3 +195,4 @@ struct hash_table_entry * hash_table_find_int(int hash_table_length,
|
|||||||
(const uint8_t *)&key,
|
(const uint8_t *)&key,
|
||||||
4);
|
4);
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
@ -38,6 +38,7 @@ 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);
|
||||||
|
|
||||||
|
/*
|
||||||
void hash_table_add_int(int hash_table_length,
|
void hash_table_add_int(int hash_table_length,
|
||||||
struct hash_table_entry * entry,
|
struct hash_table_entry * entry,
|
||||||
int key,
|
int key,
|
||||||
@ -46,3 +47,4 @@ void hash_table_add_int(int hash_table_length,
|
|||||||
struct hash_table_entry * hash_table_find_int(int hash_table_length,
|
struct hash_table_entry * hash_table_find_int(int hash_table_length,
|
||||||
struct hash_table_entry * entry,
|
struct hash_table_entry * entry,
|
||||||
int key);
|
int key);
|
||||||
|
*/
|
||||||
|
7
c/main.c
7
c/main.c
@ -24,7 +24,12 @@ int main(int argc, const char * argv[])
|
|||||||
int method_name_length = string_length(method_name);
|
int method_name_length = string_length(method_name);
|
||||||
const char * method_descriptor = "()V";
|
const char * method_descriptor = "()V";
|
||||||
int method_descriptor_length = string_length(method_descriptor);
|
int method_descriptor_length = string_length(method_descriptor);
|
||||||
struct method_info * method_info = class_resolver_lookup_method(class_entry,
|
|
||||||
|
int methods_hash_table_length = class_entry->methods.length;
|
||||||
|
struct hash_table_entry * methods_hash_table = class_entry->methods.entry;
|
||||||
|
|
||||||
|
struct method_info * method_info = class_resolver_lookup_method(methods_hash_table_length,
|
||||||
|
methods_hash_table,
|
||||||
(const uint8_t *)method_name,
|
(const uint8_t *)method_name,
|
||||||
method_name_length,
|
method_name_length,
|
||||||
(const uint8_t *)method_descriptor,
|
(const uint8_t *)method_descriptor,
|
||||||
|
@ -18,6 +18,9 @@ struct arena class_arena = {
|
|||||||
|
|
||||||
void * malloc_class_arena(uint32_t size)
|
void * malloc_class_arena(uint32_t size)
|
||||||
{
|
{
|
||||||
|
if (size == 0)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
assert((class_arena.ix & (~3)) == class_arena.ix);
|
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);
|
size = (size + 3) & (~3);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user