backtrace / code_attribute / method_entry refactor

This commit is contained in:
Zack Buhman 2025-01-05 16:37:44 -06:00
parent 16db74a16a
commit d101710e0f
23 changed files with 638 additions and 359 deletions

13
.gitignore vendored
View File

@ -14,3 +14,16 @@ main
print_class
__pycache__
classes.txt
*.4ct
*.dvi
*.lg
*.log
*.tmp
*.toc
*.xref
doc/*.pdf
doc/*.css
doc/*.html
*.idv
*.aux
*.4tc

36
c/backtrace.c Normal file
View File

@ -0,0 +1,36 @@
#include "backtrace.h"
#include "printf.h"
#include "debug.h"
#include "find_attribute.h"
void backtrace_print(struct vm * vm)
{
for (int i = (vm->frame_stack.ix - 1); i >= 0; i--) {
printf("ix %d\n", i);
struct frame * frame = &vm->frame_stack.frame[i];
printf(" class: ");
print__class_entry__class_name(frame->class_entry);
printc('\n');
printf(" method: ");
print__method_info__method_name(frame->class_entry, frame->method_info);
printc('\n');
printf(" pc: %d\n", frame->pc);
int linenumbertable_name_index = find_linenumbertable_name_index(frame->class_entry->class_file);
struct attribute_info * attribute_info = find_attribute(linenumbertable_name_index,
frame->code_attribute->attributes_count,
frame->code_attribute->attributes);
assert(attribute_info != nullptr);
int line_number_table_length = attribute_info->line_number_table->line_number_table_length;
struct line_number_table * line_number_table = attribute_info->line_number_table->line_number_table;
int line_number = 0;
for (int i = 0; i < line_number_table_length; i++) {
if (frame->pc >= line_number_table[i].start_pc) {
line_number = line_number_table[i].line_number;
} else {
break;
}
}
printf(" line_number: %d\n", line_number);
}
}

5
c/backtrace.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include "frame.h"
void backtrace_print(struct vm * vm);

View File

@ -69,7 +69,7 @@ static inline void * parse_bytes(const uint8_t ** buf, int length)
return dest;
}
static inline bool bytes_equal(int length, const uint8_t * a, const char * b)
static inline bool bytes_equal_string(int length, const uint8_t * a, const char * b)
{
int i;
for (i = 0; i < length; i++) {
@ -78,3 +78,21 @@ static inline bool bytes_equal(int length, const uint8_t * a, const char * b)
}
return b[i] == 0;
}
static inline bool bytes_equal_bytes(const uint8_t * a, int a_length, const uint8_t * b, int b_length)
{
if (a_length != b_length)
return false;
for (int i = 0; i < a_length; i++) {
if ((a[i]) != (b[i]))
return false;
}
return true;
}
static inline bool constant_equal(struct constant * constant, const char * s)
{
assert(constant->tag == CONSTANT_Utf8);
return bytes_equal_string(constant->utf8.length, constant->utf8.bytes, s);
}

View File

@ -12,11 +12,11 @@ void * attribute_info_parse_info(const uint8_t * buf, struct attribute_info * at
assert(attribute_name->tag == CONSTANT_Utf8);
#endif
if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "ConstantValue")) {
if (constant_equal(attribute_name, "ConstantValue")) {
struct ConstantValue_attribute * constantvalue = malloc_class_arena((sizeof (struct ConstantValue_attribute)));
constantvalue->constantvalue_index = parse_u2(&buf);
return constantvalue;
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "Code")) {
} else if (constant_equal(attribute_name, "Code")) {
// parse Code
struct Code_attribute * code = malloc_class_arena((sizeof (struct Code_attribute)));
@ -40,34 +40,33 @@ void * attribute_info_parse_info(const uint8_t * buf, struct attribute_info * at
code->attributes = attribute_info_parse(&buf, code->attributes_count, constant_pool);
return code;
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "BootstrapMethods")) {
} else if (constant_equal(attribute_name, "BootstrapMethods")) {
// parse BootstrapMethods
struct BootstrapMethods_attribute * bootstrapmethods = malloc_class_arena((sizeof (struct BootstrapMethods_attribute)));
struct BootstrapMethods_attribute * bootstrap_methods = malloc_class_arena((sizeof (struct BootstrapMethods_attribute)));
bootstrapmethods->num_bootstrap_methods = parse_u2(&buf);
bootstrap_methods->num_bootstrap_methods = parse_u2(&buf);
uint32_t bootstrap_methods_size = (sizeof (struct bootstrap_method)) * bootstrapmethods->num_bootstrap_methods;
bootstrapmethods->bootstrap_methods = malloc_class_arena(bootstrap_methods_size);
uint32_t bootstrap_methods_size = (sizeof (struct bootstrap_method)) * bootstrap_methods->num_bootstrap_methods;
bootstrap_methods->bootstrap_methods = malloc_class_arena(bootstrap_methods_size);
for (int i = 0; i < bootstrapmethods->num_bootstrap_methods; i++) {
bootstrapmethods->bootstrap_methods[i].bootstrap_method_ref = parse_u2(&buf);
bootstrapmethods->bootstrap_methods[i].num_bootstrap_arguments = parse_u2(&buf);
for (int i = 0; i < bootstrap_methods->num_bootstrap_methods; i++) {
bootstrap_methods->bootstrap_methods[i].bootstrap_method_ref = parse_u2(&buf);
bootstrap_methods->bootstrap_methods[i].num_bootstrap_arguments = parse_u2(&buf);
uint32_t bootstrap_arguments_size = (sizeof (u2)) * bootstrapmethods->bootstrap_methods[i].num_bootstrap_arguments;
bootstrapmethods->bootstrap_methods[i].bootstrap_arguments = malloc_class_arena(bootstrap_arguments_size);
for (int j = 0; j < bootstrapmethods->bootstrap_methods[i].num_bootstrap_arguments; j++) {
bootstrapmethods->bootstrap_methods[i].bootstrap_arguments[j] = parse_u2(&buf);
uint32_t bootstrap_arguments_size = (sizeof (u2)) * bootstrap_methods->bootstrap_methods[i].num_bootstrap_arguments;
bootstrap_methods->bootstrap_methods[i].bootstrap_arguments = malloc_class_arena(bootstrap_arguments_size);
for (int j = 0; j < bootstrap_methods->bootstrap_methods[i].num_bootstrap_arguments; j++) {
bootstrap_methods->bootstrap_methods[i].bootstrap_arguments[j] = parse_u2(&buf);
}
}
return bootstrapmethods;
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "BootstrapMethods")) {
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "NestHost")) {
return bootstrap_methods;
} else if (constant_equal(attribute_name, "NestHost")) {
struct NestHost_attribute * nesthost = malloc_class_arena((sizeof (struct NestHost_attribute)));
nesthost->host_class_index = parse_u2(&buf);
return nesthost;
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "NestMembers")) {
} else if (constant_equal(attribute_name, "NestMembers")) {
struct NestMembers_attribute * nestmembers = malloc_class_arena((sizeof (struct NestMembers_attribute)));
nestmembers->number_of_classes = parse_u2(&buf);
@ -79,6 +78,18 @@ void * attribute_info_parse_info(const uint8_t * buf, struct attribute_info * at
}
return nestmembers;
} else if (constant_equal(attribute_name, "LineNumberTable")) {
struct LineNumberTable_attribute * line_number_table = malloc_class_arena((sizeof (struct LineNumberTable_attribute)));
line_number_table->line_number_table_length = parse_u2(&buf);
uint32_t line_number_table_size = (sizeof (struct line_number_table)) * line_number_table->line_number_table_length;
line_number_table->line_number_table = malloc_class_arena(line_number_table_size);
for (int i = 0; i < line_number_table->line_number_table_length; i++) {
line_number_table->line_number_table[i].start_pc = parse_u2(&buf);
line_number_table->line_number_table[i].line_number = parse_u2(&buf);
}
return line_number_table;
} else {
return nullptr;
}

View File

@ -135,6 +135,7 @@ struct BootstrapMethods_attribute;
struct NestHost_attribute;
struct NestMembers_attribute;
struct PermittedSubclasses_attribute;
struct LineNumberTable_attribute;
struct attribute_info {
u2 attribute_name_index;
@ -144,10 +145,11 @@ struct attribute_info {
struct ConstantValue_attribute * constantvalue;
struct Code_attribute * code;
//struct StackMapTable_attribute * stackmaptable;
struct BootstrapMethods_attribute * bootstrapmethods;
struct BootstrapMethods_attribute * bootstrap_methods;
struct NestHost_attribute * nesthost;
struct NestMembers_attribute * nestmembers;
//struct PermittedSubclasses_attribute * permittedsubclasses;
struct LineNumberTable_attribute * line_number_table;
};
};
@ -193,6 +195,16 @@ struct NestMembers_attribute {
u2 * classes;
};
struct line_number_table {
u2 start_pc;
u2 line_number;
};
struct LineNumberTable_attribute {
u2 line_number_table_length;
struct line_number_table * line_number_table;
};
enum FIELD_ACC {
FIELD_ACC_PUBLIC = 0x0001, // Declared public; may be accessed from outside its package.
FIELD_ACC_PRIVATE = 0x0002, // Declared private; accessible only within the defining class and other classes belonging to the same nest (§5.4.4).

View File

@ -6,13 +6,13 @@
#include "malloc.h"
#include "class_resolver.h"
#include "string.h"
#include "debug_class_file.h"
#include "memory_allocator.h"
#include "printf.h"
#include "field_size.h"
#include "debug.h"
#include "fatal.h"
#include "parse_type.h"
#include "find_attribute.h"
static int field_info_field_size(struct class_file * class_file, struct field_info * field_info)
{
@ -50,7 +50,7 @@ static int32_t count_superclass_instance_fields(int class_hash_table_length,
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);
debug_print__constant__utf8_string(class_name_constant);
debugf(": %d\n", instance_field_count);
return instance_field_count;
@ -87,7 +87,7 @@ static int add_superclass_instance_fields(int class_hash_table_length,
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 instance field: ");
print_utf8_string(name_constant);
debug_print__constant__utf8_string(name_constant);
debugf(": %d %p\n", instance_index, field_entry);
hash_table_add(fields_hash_table_length,
fields_hash_table,
@ -106,10 +106,11 @@ static int32_t class_resolver_create_fields_hash_table(int class_hash_table_leng
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,
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);
int fields_hash_table_length = hash_table_next_power_of_two(total_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);
hash_table_init(fields_hash_table_length, fields_hash_table);
@ -127,7 +128,7 @@ static int32_t class_resolver_create_fields_hash_table(int class_hash_table_leng
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 static field: ");
print_utf8_string(name_constant);
debug_print__constant__utf8_string(name_constant);
debugf(": %d %p\n", static_index, field_entry);
hash_table_add(fields_hash_table_length,
@ -204,7 +205,7 @@ static void class_resolver_allocate_attribute_entry(struct class_entry * class_e
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++) {
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
attribute_entry[i].class_entry = nullptr;
}
@ -237,7 +238,7 @@ struct hash_table_entry * class_resolver_load_from_buffers(const uint8_t ** buff
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
debugf("hash table entry for class: ");
print_utf8_string(class_name_constant);
debug_print__constant__utf8_string(class_name_constant);
debugf(" %p\n", &class_entry[i]);
hash_table_add(class_hash_table_length,
@ -431,9 +432,17 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i
debug_print__method_info__method_name(class_entry, method_info);
debugc('\n');
int code_index = find_code_name_index(class_entry->class_file);
assert(code_index != 0);
struct attribute_info * attribute = find_attribute(code_index,
method_info->attributes_count,
method_info->attributes);
assert(attribute != nullptr);
return (struct method_entry){
.class_entry = class_entry,
.method_info = method_info
.method_info = method_info,
.code_attribute = attribute->code,
};
}
@ -444,7 +453,7 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
print_utf8_string(class_name_constant);
debug_print__constant__utf8_string(class_name_constant);
debugf("\n");
// lookup the method from the superclass
@ -501,6 +510,14 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas
struct method_entry * method_entry = malloc_class_arena((sizeof (struct method_entry)));
method_entry->class_entry = class_entry;
method_entry->method_info = method_info;
int code_index = find_code_name_index(class_entry->class_file);
assert(code_index != 0);
struct attribute_info * attribute = find_attribute(code_index,
method_info->attributes_count,
method_info->attributes);
assert(attribute != nullptr);
method_entry->code_attribute = attribute->code;
origin_class_entry->attribute_entry[methodref_index - 1].method_entry = method_entry;
return method_entry;
}
@ -512,7 +529,7 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
print_utf8_string(class_name_constant);
debug_print__constant__utf8_string(class_name_constant);
debugf("\n");
// lookup the method from the superclass
@ -526,6 +543,42 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas
assert(!"methodref method does not exist");
}
struct method_entry class_resolver_lookup_method_from_method_name_method_descriptor(struct class_entry * class_entry,
const uint8_t * method_name,
int method_name_length,
const uint8_t * method_descriptor,
int method_descriptor_length)
{
struct method_info * method_info = class_resolver_lookup_method(class_entry->methods.length,
class_entry->methods.entry,
method_name,
method_name_length,
method_descriptor,
method_descriptor_length);
if (method_info != nullptr) {
int code_index = find_code_name_index(class_entry->class_file);
assert(code_index != 0);
debugf("code_index: %d\n", code_index);
struct attribute_info * attribute = find_attribute(code_index,
method_info->attributes_count,
method_info->attributes);
assert(attribute != nullptr);
return (struct method_entry){
.class_entry = class_entry,
.method_info = method_info,
.code_attribute = attribute->code,
};
} else {
return (struct method_entry){
.class_entry = nullptr,
.method_info = nullptr,
.code_attribute = nullptr,
};
}
}
int32_t * class_resolver_lookup_string(int class_hash_table_length,
struct hash_table_entry * class_hash_table,
struct class_entry * class_entry,

View File

@ -14,6 +14,7 @@ enum initialization_state {
struct method_entry {
struct class_entry * class_entry;
struct method_info * method_info;
struct Code_attribute * code_attribute;
};
union attribute_entry {
@ -60,12 +61,6 @@ struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash
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,
int method_name_length,
const uint8_t * method_descriptor,
int method_descriptor_length);
struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(int class_hash_table_length,
struct hash_table_entry * class_hash_table,
int32_t interfacemethodref_index,
@ -75,6 +70,11 @@ struct method_entry * class_resolver_lookup_method_from_methodref_index(int clas
struct hash_table_entry * class_hash_table,
int32_t methodref_index,
struct class_entry * origin_class_entry);
struct method_entry class_resolver_lookup_method_from_method_name_method_descriptor(struct class_entry * class_entry,
const uint8_t * method_name,
int method_name_length,
const uint8_t * method_descriptor,
int method_descriptor_length);
struct field_entry * class_resolver_lookup_field(int fields_hash_table_length,
struct hash_table_entry * fields_hash_table,
const uint8_t * field_name,

View File

@ -2,8 +2,16 @@
#include "debug.h"
#include "assert.h"
void debug_print__string(const uint8_t * bytes, int length)
{
for (int i = 0; i < length; i++) {
debugc(bytes[i]);
}
}
void debug_print__constant__utf8_string(struct constant * constant)
{
assert(constant->tag == CONSTANT_Utf8);
for (int i = 0; i < constant->utf8.length; i++) {
debugc(constant->utf8.bytes[i]);
}
@ -14,28 +22,49 @@ void debug_print__class_entry__class_name(struct class_entry * class_entry)
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1];
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
debug_print__constant__utf8_string(class_name_constant);
}
void debug_print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant)
{
debug_print__constant__utf8_string(name_constant);
debugc(' ');
debug_print__constant__utf8_string(descriptor_constant);
}
void debug_print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info)
{
struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_info->name_index - 1];
assert(method_name_constant->tag == CONSTANT_Utf8);
debug_print__constant__utf8_string(method_name_constant);
debugc(' ');
struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1];
assert(method_descriptor_constant->tag == CONSTANT_Utf8);
debug_print__constant__utf8_string(method_descriptor_constant);
debug_print__constant__method_name(method_name_constant, method_descriptor_constant);
}
void debug_print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant)
void print__constant__utf8_string(struct constant * constant)
{
assert(name_constant->tag == CONSTANT_Utf8);
debug_print__constant__utf8_string(name_constant);
debugc(' ');
assert(descriptor_constant->tag == CONSTANT_Utf8);
debug_print__constant__utf8_string(descriptor_constant);
assert(constant->tag == CONSTANT_Utf8);
for (int i = 0; i < constant->utf8.length; i++) {
printc(constant->utf8.bytes[i]);
}
}
void print__class_entry__class_name(struct class_entry * class_entry)
{
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1];
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
print__constant__utf8_string(class_name_constant);
}
void print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant)
{
print__constant__utf8_string(name_constant);
printc(' ');
print__constant__utf8_string(descriptor_constant);
}
void print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info)
{
struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_info->name_index - 1];
struct constant * method_descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1];
print__constant__method_name(method_name_constant, method_descriptor_constant);
}

View File

@ -3,7 +3,13 @@
#include "class_file.h"
#include "class_resolver.h"
void debug_print__string(const uint8_t * bytes, int length);
void debug_print__constant__utf8_string(struct constant * constant);
void debug_print__class_entry__class_name(struct class_entry * class_entry);
void debug_print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info);
void debug_print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant);
void debug_print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info);
void print__constant__utf8_string(struct constant * constant);
void print__class_entry__class_name(struct class_entry * class_entry);
void print__constant__method_name(struct constant * name_constant, struct constant * descriptor_constant);
void print__method_info__method_name(struct class_entry * class_entry, struct method_info * method_info);

View File

@ -7,284 +7,322 @@
#include "debug_class_file.h"
#include "printf.h"
#include "string.h"
#include "debug.h"
void print_utf8_string(struct constant * constant)
{
for (int i = 0; i < constant->utf8.length; i++) {
debugc(constant->utf8.bytes[i]);
}
}
static void print_attribute(const char * indent, struct attribute_info * attribute, struct constant * constant_pool);
void print_constant(struct constant * constant)
static void print_constant(struct constant * constant)
{
switch (constant->tag) {
case CONSTANT_Class:
debugf("CONSTANT_Class name_index=%d\n",
printf("CONSTANT_Class name_index=%d\n",
constant->class.name_index);
break;
case CONSTANT_Fieldref:
debugf("CONSTANT_Fieldref class_index=%d name_and_type_index=%d\n",
printf("CONSTANT_Fieldref class_index=%d name_and_type_index=%d\n",
constant->fieldref.class_index,
constant->fieldref.name_and_type_index);
break;
case CONSTANT_Methodref:
debugf("CONSTANT_Methodref class_index=%d name_and_type_index=%d\n",
printf("CONSTANT_Methodref class_index=%d name_and_type_index=%d\n",
constant->methodref.class_index,
constant->methodref.name_and_type_index);
break;
case CONSTANT_InterfaceMethodref:
debugf("CONSTANT_InterfaceMethodref class_index=%d name_and_type_index=%d\n",
printf("CONSTANT_InterfaceMethodref class_index=%d name_and_type_index=%d\n",
constant->interfacemethodref.class_index,
constant->interfacemethodref.name_and_type_index);
break;
case CONSTANT_String:
debugf("CONSTANT_String string_index=%d\n",
printf("CONSTANT_String string_index=%d\n",
constant->string.string_index);
break;
case CONSTANT_Integer:
debugf("CONSTANT_Integer bytes=%d\n",
printf("CONSTANT_Integer bytes=%d\n",
constant->integer.bytes);
break;
case CONSTANT_Float:
debugf("CONSTANT_Float bytes=%f\n",
printf("CONSTANT_Float bytes=%f\n",
*(float *)(&constant->_float.bytes));
break;
case CONSTANT_Long:
debugf("CONSTANT_Long bytes=%l\n",
printf("CONSTANT_Long bytes=%l\n",
constant->_long.bytes);
break;
case CONSTANT_Double:
debugf("CONSTANT_Double bytes=%f\n",
printf("CONSTANT_Double bytes=%f\n",
*(double *)(&constant->_double.bytes));
break;
case CONSTANT_NameAndType:
debugf("CONSTANT_NameAndType %d %d\n",
printf("CONSTANT_NameAndType name_index=%d descriptor_index=%d\n",
constant->nameandtype.name_index,
constant->nameandtype.descriptor_index);
break;
case CONSTANT_Utf8:
debugf("CONSTANT_Utf8 length=%d bytes=",
printf("CONSTANT_Utf8 length=%d bytes=",
constant->utf8.length);
print_utf8_string(constant);
debugf("\n");
print__constant__utf8_string(constant);
printf("\n");
break;
case CONSTANT_MethodHandle:
debugf("CONSTANT_MethodHandle reference_kind=%d reference_index=%d\n",
printf("CONSTANT_MethodHandle reference_kind=%d reference_index=%d\n",
constant->methodhandle.reference_kind,
constant->methodhandle.reference_index);
break;
case CONSTANT_MethodType:
debugf("CONSTANT_MethodType descriptor_index=%d\n",
printf("CONSTANT_MethodType descriptor_index=%d\n",
constant->methodtype.descriptor_index);
break;
case CONSTANT_Dynamic:
debugf("CONSTANT_Dynamic bootstrap_method_attr_index=%d name_and_type_index=%d\n",
printf("CONSTANT_Dynamic bootstrap_method_attr_index=%d name_and_type_index=%d\n",
constant->dynamic.bootstrap_method_attr_index,
constant->dynamic.name_and_type_index);
break;
case CONSTANT_InvokeDynamic:
debugf("CONSTANT_InvokeDynamic bootstrap_method_attr_index=%d name_and_type_index=%d\n",
printf("CONSTANT_InvokeDynamic bootstrap_method_attr_index=%d name_and_type_index=%d\n",
constant->invokedynamic.bootstrap_method_attr_index,
constant->invokedynamic.name_and_type_index);
break;
case CONSTANT_Module:
debugf("CONSTANT_Module name_index=%d\n",
printf("CONSTANT_Module name_index=%d\n",
constant->module.name_index);
break;
case CONSTANT_Package:
debugf("CONSTANT_Package name_index=%d\n",
printf("CONSTANT_Package name_index=%d\n",
constant->package.name_index);
break;
}
}
void print_attribute(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
static void print_bootstrap_methods(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
{
debugs(indent);
debugf("attribute_name_index: %d\n", attribute->attribute_name_index);
struct constant * attribute_name = &constant_pool[attribute->attribute_name_index - 1];
debugs(indent);
debugs(" ");
print_constant(attribute_name);
prints(indent);
printf("num_bootstrap_methods: %d\n", attribute->bootstrap_methods->num_bootstrap_methods);
prints(indent);
printf("bootstrap methods:\n");
for (int i = 0; i < attribute->bootstrap_methods->num_bootstrap_methods; i++) {
prints(indent);
printf(" bootstrap_method %d:\n", i);
prints(indent);
printf(" bootstrap_method_ref: %d\n", attribute->bootstrap_methods->bootstrap_methods[i].bootstrap_method_ref);
prints(indent);
printf(" num_bootstrap_arguments: %d\n", attribute->bootstrap_methods->bootstrap_methods[i].num_bootstrap_arguments);
prints(indent);
printf(" bootstrap_arguments:\n");
for (int j = 0; j < attribute->bootstrap_methods->bootstrap_methods[i].num_bootstrap_arguments; j++) {
prints(indent);
printf(" bootstrap_argument %d: %d\n", j, attribute->bootstrap_methods->bootstrap_methods[i].bootstrap_arguments[j]);
}
}
}
if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "ConstantValue")) {
debugs(indent);
debugf("constantvalue_index %d\n", attribute->constantvalue->constantvalue_index);
static void print_nestmembers(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
{
prints(indent);
printf("number_of_classes: %d\n", attribute->nestmembers->number_of_classes);
prints(indent);
printf("classes:\n");
for (int i = 0; i < attribute->nestmembers->number_of_classes; i++) {
prints(indent);
printf(" class %d:\n", i);
prints(indent);
prints(" ");
print_constant(&constant_pool[attribute->nestmembers->classes[i] - 1]);
int ix = constant_pool[attribute->nestmembers->classes[i] - 1].class.name_index;
prints(indent);
prints(" ");
print_constant(&constant_pool[ix - 1]);
}
}
static void print_nesthost(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
{
prints(indent);
printf("host_class_index: %d\n", attribute->nesthost->host_class_index);
}
static void print_constantvalue(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
{
prints(indent);
printf("constantvalue_index %d\n", attribute->constantvalue->constantvalue_index);
struct constant * value = &constant_pool[attribute->constantvalue->constantvalue_index - 1];
debugs(indent);
debugs(" ");
prints(indent);
prints(" ");
print_constant(value);
if (value->tag == CONSTANT_String) {
debugs(indent);
debugs(" ");
prints(indent);
prints(" ");
print_constant(&constant_pool[value->string.string_index - 1]);
}
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "Code")) {
}
static void print_code(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
{
// print code
debugs(indent);
debugf("max_stack %d\n", attribute->code->max_stack);
debugs(indent);
debugf("max_locals %d\n", attribute->code->max_locals);
debugs(indent);
debugf("code_length %d\n", attribute->code->code_length);
prints(indent);
printf("max_stack %d\n", attribute->code->max_stack);
prints(indent);
printf("max_locals %d\n", attribute->code->max_locals);
prints(indent);
printf("code_length %d\n", attribute->code->code_length);
// dump code
debugs(indent);
debugf("code:\n");
prints(indent);
printf("code:\n");
uint32_t pc = 0;
while (pc < attribute->code->code_length) {
debugs(indent);
debugs(" ");
prints(indent);
prints(" ");
pc = decode_print_instruction(attribute->code->code, pc);
}
debugs(indent);
debugf("exception_table_length: %d\n", attribute->code->exception_table_length);
debugs(indent);
debugf("exceptions:\n");
prints(indent);
printf("exception_table_length: %d\n", attribute->code->exception_table_length);
prints(indent);
printf("exceptions:\n");
for (int i = 0; i < attribute->code->exception_table_length; i++) {
debugs(indent);
debugf(" exception %d:\n", i);
debugs(indent);
debugf(" start_pc: %d\n", attribute->code->exception_table[i].start_pc);
debugs(indent);
debugf(" end_pc: %d\n", attribute->code->exception_table[i].end_pc);
debugs(indent);
debugf(" handler_pc: %d\n", attribute->code->exception_table[i].handler_pc);
debugs(indent);
debugf(" catch_type: %d\n", attribute->code->exception_table[i].catch_type);
prints(indent);
printf(" exception %d:\n", i);
prints(indent);
printf(" start_pc: %d\n", attribute->code->exception_table[i].start_pc);
prints(indent);
printf(" end_pc: %d\n", attribute->code->exception_table[i].end_pc);
prints(indent);
printf(" handler_pc: %d\n", attribute->code->exception_table[i].handler_pc);
prints(indent);
printf(" catch_type: %d\n", attribute->code->exception_table[i].catch_type);
}
debugs(indent);
debugf("attributes_count: %d\n", attribute->code->attributes_count);
debugs(indent);
debugf("attributes:\n");
prints(indent);
printf("attributes_count: %d\n", attribute->code->attributes_count);
prints(indent);
printf("attributes:\n");
for (int i = 0; i < attribute->code->attributes_count; i++) {
char indent2[string_length(indent) + 2 + 1];
string_copy(indent2, indent);
string_copy(indent2 + string_length(indent), " ");
debugs(indent);
debugf(" attribute %d:\n", i);
prints(indent);
printf(" attribute %d:\n", i);
print_attribute(indent2, &attribute->code->attributes[i], constant_pool);
}
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "BootstrapMethods")) {
debugs(indent);
debugf("num_bootstrap_methods: %d\n", attribute->bootstrapmethods->num_bootstrap_methods);
debugs(indent);
debugf("bootstrap methods:\n");
for (int i = 0; i < attribute->bootstrapmethods->num_bootstrap_methods; i++) {
debugs(indent);
debugf(" bootstrap_method %d:\n", i);
debugs(indent);
debugf(" bootstrap_method_ref: %d\n", attribute->bootstrapmethods->bootstrap_methods[i].bootstrap_method_ref);
debugs(indent);
debugf(" num_bootstrap_arguments: %d\n", attribute->bootstrapmethods->bootstrap_methods[i].num_bootstrap_arguments);
debugs(indent);
debugf(" bootstrap_arguments:\n");
for (int j = 0; j < attribute->bootstrapmethods->bootstrap_methods[i].num_bootstrap_arguments; j++) {
debugs(indent);
debugf(" bootstrap_argument %d: %d\n", j, attribute->bootstrapmethods->bootstrap_methods[i].bootstrap_arguments[j]);
}
}
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "NestHost")) {
debugs(indent);
debugf("host_class_index: %d\n", attribute->nesthost->host_class_index);
} else if (bytes_equal(attribute_name->utf8.length, attribute_name->utf8.bytes, "NestMembers")) {
debugs(indent);
debugf("number_of_classes: %d\n", attribute->nestmembers->number_of_classes);
debugs(indent);
debugf("classes:\n");
for (int i = 0; i < attribute->nestmembers->number_of_classes; i++) {
debugs(indent);
debugf(" class %d:\n", i);
debugs(indent);
debugs(" ");
print_constant(&constant_pool[attribute->nestmembers->classes[i] - 1]);
int ix = constant_pool[attribute->nestmembers->classes[i] - 1].class.name_index;
debugs(indent);
debugs(" ");
print_constant(&constant_pool[ix - 1]);
}
static void print_line_number_table(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
{
prints(indent);
printf("line_number_table_length: %d\n", attribute->line_number_table->line_number_table_length);
prints(indent);
printf("line_number_table:\n");
for (int i = 0; i < attribute->line_number_table->line_number_table_length; i++) {
prints(indent);
printf(" start_pc=%d line_number=%d\n",
attribute->line_number_table->line_number_table[i].start_pc,
attribute->line_number_table->line_number_table[i].line_number);
}
}
static void print_attribute(const char * indent, struct attribute_info * attribute, struct constant * constant_pool)
{
prints(indent);
printf("attribute_name_index: %d\n", attribute->attribute_name_index);
struct constant * attribute_name = &constant_pool[attribute->attribute_name_index - 1];
prints(indent);
prints(" ");
print_constant(attribute_name);
if (constant_equal(attribute_name, "ConstantValue")) {
print_constantvalue(indent, attribute, constant_pool);
} else if (constant_equal(attribute_name, "Code")) {
print_code(indent, attribute, constant_pool);
} else if (constant_equal(attribute_name, "BootstrapMethods")) {
print_bootstrap_methods(indent, attribute, constant_pool);
} else if (constant_equal(attribute_name, "NestHost")) {
print_nesthost(indent, attribute, constant_pool);
} else if (constant_equal(attribute_name, "NestMembers")) {
print_nestmembers(indent, attribute, constant_pool);
} else if (constant_equal(attribute_name, "LineNumberTable")) {
print_line_number_table(indent, attribute, constant_pool);
}
}
void print_class_file(struct class_file * class_file)
{
debugf("magic %08x\n", class_file->magic);
debugf("minor_version %d\n", class_file->minor_version);
debugf("major_version %d\n", class_file->major_version);
debugf("constant_pool_count %d\n", class_file->constant_pool_count);
printf("magic %08x\n", class_file->magic);
printf("minor_version %d\n", class_file->minor_version);
printf("major_version %d\n", class_file->major_version);
printf("constant_pool_count %d\n", class_file->constant_pool_count);
debugf("constants:\n");
printf("constants:\n");
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
if (class_file->constant_pool[i].tag != 0) {
debugf("%4d: ", i + 1);
printf("%4d: ", i + 1);
print_constant(&class_file->constant_pool[i]);
}
}
debugf("access_flags %04x\n", class_file->access_flags);
debugf("this_class %d\n", class_file->this_class);
debugf("super_class %d\n", class_file->super_class);
debugf("interfaces_count %d\n", class_file->interfaces_count);
printf("access_flags %04x\n", class_file->access_flags);
printf("this_class %d\n", class_file->this_class);
printf("super_class %d\n", class_file->super_class);
printf("interfaces_count %d\n", class_file->interfaces_count);
debugf("interfaces:\n");
printf("interfaces:\n");
for (int i = 0; i < class_file->interfaces_count; i++) {
debugf(" interface %3d:\n", i);
printf(" interface %3d:\n", i);
int interface_index = class_file->interfaces[i];
debugs(" ");
prints(" ");
struct constant * class_constant = &class_file->constant_pool[interface_index - 1];
print_constant(class_constant);
debugs(" ");
prints(" ");
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:\n");
printf("fields_count %d\n", class_file->fields_count);
printf("fields:\n");
for (int i = 0; i < class_file->fields_count; i++) {
debugf(" field %d:\n", i);
debugf(" access_flags %d\n", class_file->fields[i].access_flags);
debugf(" name_index %d\n", class_file->fields[i].name_index);
debugf(" ");
printf(" field %d:\n", i);
printf(" access_flags %d\n", class_file->fields[i].access_flags);
printf(" name_index %d\n", class_file->fields[i].name_index);
printf(" ");
print_constant(&class_file->constant_pool[class_file->fields[i].name_index - 1]);
debugf(" descriptor_index %d\n", class_file->fields[i].descriptor_index);
debugf(" ");
printf(" descriptor_index %d\n", class_file->fields[i].descriptor_index);
printf(" ");
print_constant(&class_file->constant_pool[class_file->fields[i].descriptor_index - 1]);
debugf(" attributes_count %d\n", class_file->fields[i].attributes_count);
debugf(" attributes:\n");
printf(" attributes_count %d\n", class_file->fields[i].attributes_count);
printf(" attributes:\n");
for (int j = 0; j < class_file->fields[i].attributes_count; j++) {
debugf(" attribute %d:\n", j);
printf(" attribute %d:\n", j);
print_attribute(" ", &class_file->fields[i].attributes[j], class_file->constant_pool);
}
}
debugf("methods_count %d\n", class_file->methods_count);
debugf("methods:\n");
printf("methods_count %d\n", class_file->methods_count);
printf("methods:\n");
for (int i = 0; i < class_file->methods_count; i++) {
debugf(" method %d:\n", i);
debugf(" access_flags %04x\n", class_file->methods[i].access_flags);
debugf(" name_index %d\n", class_file->methods[i].name_index);
debugf(" ");
printf(" method %d:\n", i);
printf(" access_flags %04x\n", class_file->methods[i].access_flags);
printf(" name_index %d\n", class_file->methods[i].name_index);
printf(" ");
print_constant(&class_file->constant_pool[class_file->methods[i].name_index - 1]);
debugf(" descriptor_index %d\n", class_file->methods[i].descriptor_index);
debugf(" ");
printf(" descriptor_index %d\n", class_file->methods[i].descriptor_index);
printf(" ");
print_constant(&class_file->constant_pool[class_file->methods[i].descriptor_index - 1]);
debugf(" attributes_count %d\n", class_file->methods[i].attributes_count);
debugf(" attributes:\n");
printf(" attributes_count %d\n", class_file->methods[i].attributes_count);
printf(" attributes:\n");
for (int j = 0; j < class_file->methods[i].attributes_count; j++) {
debugf(" attribute %d:\n", j);
printf(" attribute %d:\n", j);
print_attribute(" ", &class_file->methods[i].attributes[j], class_file->constant_pool);
}
}
debugf("attributes_count %d\n", class_file->attributes_count);
debugf("attributes:\n");
printf("attributes_count %d\n", class_file->attributes_count);
printf("attributes:\n");
for (int i = 0; i < class_file->attributes_count; i++) {
debugf(" attribute %d:\n", i);
printf(" attribute %d:\n", i);
print_attribute(" ", &class_file->attributes[i], class_file->constant_pool);
}
}

View File

@ -2,7 +2,4 @@
#include "class_file.h"
void print_utf8_string(struct constant * constant);
void print_constant(struct constant * constant);
void print_attribute(const char * indent, struct attribute_info * attribute, struct constant * constant_pool);
void print_class_file(struct class_file * class_file);

View File

@ -7,6 +7,7 @@
#include "field_size.h"
#include "debug.h"
#include "parse_type.h"
#include "backtrace.h"
void op_aaload(struct vm * vm)
{
@ -125,6 +126,7 @@ void op_astore_3(struct vm * vm)
void op_athrow(struct vm * vm)
{
backtrace_print(vm);
assert(!"op_athrow");
}
@ -224,7 +226,7 @@ void op_checkcast(struct vm * vm, uint32_t index)
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
print_utf8_string(class_name_constant);
debug_print__constant__utf8_string(class_name_constant);
debugf("\n");
// superclass lookup
@ -1193,7 +1195,7 @@ void op_instanceof(struct vm * vm, uint32_t index)
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
print_utf8_string(class_name_constant);
debug_print__constant__utf8_string(class_name_constant);
debugf("\n");
// superclass lookup
@ -1223,7 +1225,7 @@ void op_invokeinterface(struct vm * vm, uint32_t index, uint32_t count)
class_entry,
vm->current_frame->class_entry);
vm_special_method_call(vm, method_entry.class_entry, method_entry.method_info);
vm_special_method_call(vm, method_entry.class_entry, &method_entry);
}
void op_invokespecial(struct vm * vm, uint32_t index)
@ -1234,7 +1236,7 @@ void op_invokespecial(struct vm * vm, uint32_t index)
index,
vm->current_frame->class_entry);
vm_special_method_call(vm, method_entry->class_entry, method_entry->method_info);
vm_special_method_call(vm, method_entry->class_entry, method_entry);
}
void op_invokestatic(struct vm * vm, uint32_t index)
@ -1249,7 +1251,7 @@ void op_invokestatic(struct vm * vm, uint32_t index)
declared the resolved method is initialized if that class or interface has
not already been initialized (§5.5). */
vm_static_method_call(vm, method_entry->class_entry, method_entry->method_info);
vm_static_method_call(vm, method_entry->class_entry, method_entry);
}
#include "debug.h"
@ -1283,7 +1285,7 @@ void op_invokevirtual(struct vm * vm, uint32_t index)
class_entry,
vm->current_frame->class_entry);
vm_special_method_call(vm, method_entry.class_entry, method_entry.method_info);
vm_special_method_call(vm, method_entry.class_entry, &method_entry);
}
void op_ior(struct vm * vm)

View File

@ -1,5 +1,3 @@
#include "debug_class_file.h"
static inline void class_entry_field_entry_from_constant_index(struct vm * vm,
int32_t index,
struct class_entry ** class_entry,

55
c/find_attribute.c Normal file
View File

@ -0,0 +1,55 @@
#include "assert.h"
#include "class_file.h"
#include "bytes.h"
#include "debug.h"
#include "printf.h"
int find_code_name_index(struct class_file * class_file)
{
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
struct constant * constant = &class_file->constant_pool[i];
if (constant->tag == CONSTANT_Utf8) {
if (constant_equal(constant, "Code")) {
return i + 1;
}
}
}
return 0;
}
int find_constantvalue_name_index(struct class_file * class_file)
{
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
struct constant * constant = &class_file->constant_pool[i];
if (constant->tag == CONSTANT_Utf8) {
if (constant_equal(constant, "ConstantValue")) {
return i + 1;
}
}
}
return 0;
}
int find_linenumbertable_name_index(struct class_file * class_file)
{
for (int i = 0; i < class_file->constant_pool_count - 1; i++) {
struct constant * constant = &class_file->constant_pool[i];
if (constant->tag == CONSTANT_Utf8) {
if (constant_equal(constant, "LineNumberTable")) {
return i + 1;
}
}
}
return 0;
}
struct attribute_info * find_attribute(int name_index,
int attributes_count,
struct attribute_info * attributes)
{
for (int i = 0; i < attributes_count; i++) {
if (attributes[i].attribute_name_index == name_index)
return &attributes[i];
}
return nullptr;
}

10
c/find_attribute.h Normal file
View File

@ -0,0 +1,10 @@
#pragma once
#include "class_file.h"
int find_code_name_index(struct class_file * class_file);
int find_constantvalue_name_index(struct class_file * class_file);
int find_linenumbertable_name_index(struct class_file * class_file);
struct attribute_info * find_attribute(int name_index,
int attributes_count,
struct attribute_info * attributes);

162
c/frame.c
View File

@ -2,7 +2,6 @@
#include "assert.h"
#include "class_file.h"
#include "debug_class_file.h"
#include "bytes.h"
#include "decode.h"
#include "frame.h"
@ -11,43 +10,8 @@
#include "string.h"
#include "native.h"
#include "fatal.h"
struct Code_attribute * get_code_attribute(int code_name_index,
int attributes_count,
struct attribute_info * attributes)
{
for (int i = 0; i < attributes_count; i++) {
if (attributes[i].attribute_name_index == code_name_index)
return attributes[i].code;
}
return nullptr;
}
int find_code_name_index(struct class_file * class_file)
{
for (int i = 0; i < class_file->constant_pool_count; i++) {
struct constant * constant = &class_file->constant_pool[i];
if (constant->tag == CONSTANT_Utf8) {
if (bytes_equal(constant->utf8.length, constant->utf8.bytes, "Code")) {
return i + 1;
}
}
}
return 0;
}
int find_constantvalue_name_index(struct class_file * class_file)
{
for (int i = 0; i < class_file->constant_pool_count; i++) {
struct constant * constant = &class_file->constant_pool[i];
if (constant->tag == CONSTANT_Utf8) {
if (bytes_equal(constant->utf8.length, constant->utf8.bytes, "ConstantValue")) {
return i + 1;
}
}
}
return 0;
}
#include "debug.h"
#include "find_attribute.h"
int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type)
{
@ -56,7 +20,7 @@ int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_typ
assert(descriptor_constant->utf8.bytes[0] == '(');
debugf("method descriptor: ");
print_utf8_string(descriptor_constant);
debug_print__constant__utf8_string(descriptor_constant);
debugf("\n");
int i = 1;
@ -107,7 +71,7 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
#ifdef DEBUG
assert(class_name_constant->tag == CONSTANT_Utf8);
#endif
print_constant(class_name_constant);
debug_print__constant__utf8_string(class_name_constant);
debugf("\n");
if (class_entry->initialization_state == CLASS_INITIALIZED)
@ -164,27 +128,25 @@ 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_name_length = 8;
int method_name_length = string_length((const char *)method_name);
const uint8_t * method_descriptor = (const uint8_t *)"()V";
int method_descriptor_length = 3;
int method_descriptor_length = string_length((const char *)method_descriptor);
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,
struct method_entry method_entry =
class_resolver_lookup_method_from_method_name_method_descriptor(class_entry,
method_name,
method_name_length,
method_descriptor,
method_descriptor_length);
if (method_info != nullptr) {
assert((method_info->access_flags & METHOD_ACC_STATIC) != 0);
if (method_entry.method_info != nullptr) {
assert((method_entry.method_info->access_flags & METHOD_ACC_STATIC) != 0);
debugf("<clinit>\n");
// tamper with next_pc
vm->current_frame->next_pc = vm->current_frame->pc;
vm_static_method_call(vm, class_entry, method_info);
vm_static_method_call(vm, class_entry, &method_entry);
vm->current_frame->initialization_frame = 1;
return false;
@ -196,9 +158,9 @@ bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry)
return true;
}
void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info, int nargs, uint8_t return_type)
void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry, int nargs, uint8_t return_type)
{
debugf("vm_static_native_method_call: nargs %d\n", nargs);
debugf("vm_native_method_call: nargs %d\n", nargs);
uint32_t args[nargs];
for (int i = 0; i < nargs; i++) {
@ -210,10 +172,10 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str
debugf("native:\n ");
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1];
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
print_constant(class_name_constant);
debug_print__constant__utf8_string(class_name_constant);
debugf(" ");
struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_info->name_index - 1];
print_constant(method_name_constant);
struct constant * method_name_constant = &class_entry->class_file->constant_pool[method_entry->method_info->name_index - 1];
debug_print__constant__utf8_string(method_name_constant);
int java_lang_math_length = 14;
@ -360,22 +322,15 @@ void vm_native_method_call(struct vm * vm, struct class_entry * class_entry, str
assert(false);
}
void vm_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info, int nargs, uint8_t return_type)
void vm_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry, int nargs, uint8_t return_type)
{
int code_name_index = find_code_name_index(class_entry->class_file);
assert(code_name_index > 0);
struct Code_attribute * code = get_code_attribute(code_name_index,
method_info->attributes_count,
method_info->attributes);
assert(code != nullptr);
assert(method_entry->code_attribute != nullptr);
struct frame * old_frame = vm->current_frame;
vm->current_frame = stack_push_frame(&vm->frame_stack, 1);
vm->current_frame->code = code;
vm->current_frame->local_variable = stack_push_data(&vm->data_stack, code->max_locals);
vm->current_frame->operand_stack = stack_push_data(&vm->data_stack, code->max_stack);
vm->current_frame->local_variable = stack_push_data(&vm->data_stack, method_entry->code_attribute->max_locals);
vm->current_frame->operand_stack = stack_push_data(&vm->data_stack, method_entry->code_attribute->max_stack);
vm->current_frame->operand_stack_ix = 0;
vm->current_frame->initialization_frame = 0;
vm->current_frame->return_type = return_type;
@ -389,12 +344,13 @@ void vm_method_call(struct vm * vm, struct class_entry * class_entry, struct met
vm->current_frame->pc = 0;
vm->current_frame->next_pc = 0;
vm->current_frame->class_entry = class_entry;
vm->current_frame->method = method_info;
vm->current_frame->method_info = method_entry->method_info;
vm->current_frame->code_attribute = method_entry->code_attribute;
debugf("operand_stack_ix: %d\n", vm->current_frame->operand_stack_ix);
}
void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info)
void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry)
{
/* If the method is not native, the nargs argument values are popped from the
operand stack. A new frame is created on the Java Virtual Machine stack for
@ -407,19 +363,19 @@ void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, st
*/
uint8_t return_type;
struct constant * descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1];
struct constant * descriptor_constant = &class_entry->class_file->constant_pool[method_entry->method_info->descriptor_index - 1];
int nargs = descriptor_nargs(descriptor_constant, &return_type);
nargs += 1;
debugf("nargs+1: %d\n", nargs);
if (method_info->access_flags & METHOD_ACC_NATIVE) {
vm_native_method_call(vm, class_entry, method_info, nargs, return_type);
if (method_entry->method_info->access_flags & METHOD_ACC_NATIVE) {
vm_native_method_call(vm, class_entry, method_entry, nargs, return_type);
} else {
vm_method_call(vm, class_entry, method_info, nargs, return_type);
vm_method_call(vm, class_entry, method_entry, nargs, return_type);
}
}
void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info)
void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry)
{
/* If the method is not native, the nargs argument values are popped from the
operand stack. A new frame is created on the Java Virtual Machine stack for
@ -432,14 +388,14 @@ void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, str
*/
uint8_t return_type;
struct constant * descriptor_constant = &class_entry->class_file->constant_pool[method_info->descriptor_index - 1];
struct constant * descriptor_constant = &class_entry->class_file->constant_pool[method_entry->method_info->descriptor_index - 1];
int nargs = descriptor_nargs(descriptor_constant, &return_type);
debugf("nargs %d\n", nargs);
if (method_info->access_flags & METHOD_ACC_NATIVE) {
vm_native_method_call(vm, class_entry, method_info, nargs, return_type);
if (method_entry->method_info->access_flags & METHOD_ACC_NATIVE) {
vm_native_method_call(vm, class_entry, method_entry, nargs, return_type);
} else {
vm_method_call(vm, class_entry, method_info, nargs, return_type);
vm_method_call(vm, class_entry, method_entry, nargs, return_type);
}
}
@ -453,8 +409,8 @@ void vm_method_return(struct vm * vm)
struct frame * old_frame = vm->current_frame;
stack_pop_data(&vm->data_stack, old_frame->code->max_locals);
stack_pop_data(&vm->data_stack, old_frame->code->max_stack);
stack_pop_data(&vm->data_stack, old_frame->code_attribute->max_locals);
stack_pop_data(&vm->data_stack, old_frame->code_attribute->max_stack);
vm->current_frame = stack_pop_frame(&vm->frame_stack, 1);
assert(vm->current_frame != old_frame);
@ -537,22 +493,14 @@ static void print_vm_stack(struct vm * vm)
void vm_execute(struct vm * vm)
{
while (true) {
assert(vm->current_frame->pc < vm->current_frame->code->code_length);
assert(vm->current_frame->pc < vm->current_frame->code_attribute->code_length);
print_vm_stack(vm);
decode_print_instruction(vm->current_frame->code->code, vm->current_frame->pc);
//uint32_t old_pc = vm->current_frame->pc;
//struct method_info * old_method = vm->current_frame->method;
decode_execute_instruction(vm, vm->current_frame->code->code, vm->current_frame->pc);
if (vm->frame_stack.ix == 1) {
decode_print_instruction(vm->current_frame->code_attribute->code, vm->current_frame->pc);
decode_execute_instruction(vm, vm->current_frame->code_attribute->code, vm->current_frame->pc);
if (vm->frame_stack.ix == 0) {
debugf("terminate\n");
break;
}
/*
if (vm->current_frame->method == old_method && vm->current_frame->pc == old_pc) {
// if the instruction did not branch, increment pc
vm->current_frame->pc = vm->current_frame->next_pc;
}
*/
vm->current_frame->pc = vm->current_frame->next_pc;
}
}
@ -567,21 +515,18 @@ struct vm * vm_start(int class_hash_table_length,
main_class_name,
main_class_name_length);
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);
const uint8_t * method_name = (const uint8_t *)"main";
int method_name_length = string_length((const char *)method_name);
const uint8_t * method_descriptor = (const uint8_t *)"()V";
int method_descriptor_length = string_length((const char *)method_descriptor);
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,
struct method_entry method_entry =
class_resolver_lookup_method_from_method_name_method_descriptor(class_entry,
method_name,
method_name_length,
(const uint8_t *)method_descriptor,
method_descriptor,
method_descriptor_length);
assert(method_info != nullptr);
assert(method_entry.method_info != nullptr);
static struct vm vm;
vm.class_hash_table.entry = class_hash_table;
@ -597,16 +542,7 @@ struct vm * vm_start(int class_hash_table_length,
uint32_t data[vm.data_stack.capacity];
vm.data_stack.data = data;
struct frame * entry_frame = stack_push_frame(&vm.frame_stack, 1);
struct Code_attribute code;
code.max_locals = 0;
code.max_stack = 0;
entry_frame->code = &code;
entry_frame->local_variable = 0;
entry_frame->operand_stack = 0;
entry_frame->operand_stack_ix = 0;
vm_static_method_call(&vm, class_entry, method_info);
vm_static_method_call(&vm, class_entry, &method_entry);
return &vm;
}

View File

@ -6,8 +6,8 @@
struct frame {
struct class_entry * class_entry;
struct method_info * method;
struct Code_attribute * code;
struct method_info * method_info;
struct Code_attribute * code_attribute;
uint32_t * local_variable;
uint32_t * operand_stack;
uint32_t pc;
@ -156,8 +156,8 @@ static inline double operand_stack_pop_f64(struct frame * frame)
}
bool vm_initialize_class(struct vm * vm, struct class_entry * class_entry);
void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info);
void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_info * method_info);
void vm_special_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry);
void vm_static_method_call(struct vm * vm, struct class_entry * class_entry, struct method_entry * method_entry);
void vm_method_return(struct vm * vm);
void vm_execute(struct vm * vm);
struct vm * vm_start(int class_hash_table_length,

View File

@ -8,6 +8,7 @@
#include "file.h"
#include "malloc.h"
#include "memory_allocator.h"
#include "backtrace.h"
static struct hash_table_entry * load_from_filenames(const char * filenames[], int length, int * hash_table_length)
{
@ -53,5 +54,8 @@ int main(int argc, const char * argv[])
class_hash_table,
main_class,
main_class_length);
backtrace_print(vm);
vm_execute(vm);
}

View File

@ -20,7 +20,9 @@ OBJ = \
c/native.o \
c/debug.o \
c/fatal.o \
c/parse_type.o
c/parse_type.o \
c/backtrace.o \
c/find_attribute.o
MAIN_DREAMCAST_OBJ = \
c/main_dreamcast.o \

20
java/lang/Exception.java Normal file
View File

@ -0,0 +1,20 @@
package java.lang;
public class Exception extends Throwable {
public Exception() {
super();
}
public Exception(String message) {
super(message);
}
public Exception(String message, Throwable cause) {
super(message, cause);
}
public Exception(Throwable cause) {
super(cause);
}
}

23
java/lang/Throwable.java Normal file
View File

@ -0,0 +1,23 @@
package java.lang;
public class Throwable {
private String message;
private Throwable cause = this;
public Throwable() {
}
public Throwable(String message) {
this.message = message;
}
public Throwable(String message, Throwable cause) {
this.message = message;
this.cause = cause;
}
public Throwable(Throwable cause) {
this.cause = cause;
}
}

11
p/TestException.java Normal file
View File

@ -0,0 +1,11 @@
package p;
class TestException {
static void test() throws Exception {
throw new Exception("asdf");
}
public static void main() throws Exception {
test();
}
}