implement instanceof superclass behavior

This commit is contained in:
Zack Buhman 2024-12-30 09:04:12 -06:00
parent aa09b6d916
commit 867a10ac2b
9 changed files with 79 additions and 34 deletions

View File

@ -7,7 +7,7 @@ CC ?= gcc
ARCH = -m32 ARCH = -m32
CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protector -std=c2x -g CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protector -std=c2x -g
CFLAGS += -DDEBUG CFLAGS += -DDEBUG
CFLAGS += -DDEBUG_PRINT #CFLAGS += -DDEBUG_PRINT
LDFLAGS = -lm LDFLAGS = -lm
OPT ?= -O0 OPT ?= -O0
DEPFLAGS = -MMD -MP DEPFLAGS = -MMD -MP

View File

@ -11,6 +11,7 @@
#include "printf.h" #include "printf.h"
#include "field_size.h" #include "field_size.h"
#include "debug.h" #include "debug.h"
#include "fatal.h"
static int field_info_field_size(struct class_file * class_file, struct field_info * field_info) static int field_info_field_size(struct class_file * class_file, struct field_info * field_info)
{ {
@ -270,7 +271,10 @@ struct class_entry * class_resolver_lookup_class(int class_hash_table_length,
class_hash_table, class_hash_table,
class_name, class_name,
class_name_length); class_name_length);
assert(e != nullptr); if (e == nullptr) {
fatal_print__class_lookup_failed__from_string(class_name, class_name_length);
assert(e != nullptr);
}
return (struct class_entry *)e->value; return (struct class_entry *)e->value;
} }
@ -298,9 +302,10 @@ struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash
class_hash_table, class_hash_table,
class_name_constant->utf8.bytes, class_name_constant->utf8.bytes,
class_name_constant->utf8.length); class_name_constant->utf8.length);
if (_class_entry != nullptr) {
// cache the result // cache the result
class_entry->attribute_entry[class_index - 1].class_entry = _class_entry; class_entry->attribute_entry[class_index - 1].class_entry = _class_entry;
}
return _class_entry; return _class_entry;
} }

View File

@ -1094,20 +1094,42 @@ void op_ineg(struct vm * vm)
void op_instanceof(struct vm * vm, uint32_t index) void op_instanceof(struct vm * vm, uint32_t index)
{ {
struct class_entry * class_entry = struct class_entry * index_class_entry =
class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, class_resolver_lookup_class_from_class_index(vm->class_hash_table.length,
vm->class_hash_table.entry, vm->class_hash_table.entry,
vm->current_frame->class_entry, vm->current_frame->class_entry,
index); index);
assert(class_entry != nullptr); assert(index_class_entry != nullptr);
int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame);
if (objectref == nullptr) { bool value = false;
operand_stack_push_u32(vm->current_frame, 0); if (objectref != nullptr) {
} else { struct class_entry * class_entry = (struct class_entry *)objectref[0];
int32_t value = objectref[0] == (int32_t)class_entry; while (true) {
operand_stack_push_u32(vm->current_frame, value); assert(class_entry != nullptr);
if (class_entry == index_class_entry) {
value = true;
break;
}
if (class_entry->class_file->super_class == 0) {
break;
}
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->super_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);
print_utf8_string(class_name_constant);
debugf("\n");
// superclass lookup
class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length,
vm->class_hash_table.entry,
class_entry,
class_entry->class_file->super_class);
}
} }
operand_stack_push_u32(vm->current_frame, (uint32_t)value);
} }
void op_invokedynamic(struct vm * vm, uint32_t index) void op_invokedynamic(struct vm * vm, uint32_t index)
@ -1688,19 +1710,10 @@ void op_multianewarray(struct vm * vm, uint32_t index, uint32_t dimensions)
void op_new(struct vm * vm, uint32_t index) void op_new(struct vm * vm, uint32_t index)
{ {
struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1]; struct class_entry * class_entry = class_resolver_lookup_class_from_class_index(vm->class_hash_table.length,
#ifdef DEBUG vm->class_hash_table.entry,
assert(class_constant->tag == CONSTANT_Class); vm->current_frame->class_entry,
#endif index);
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 class_entry * 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); assert(class_entry != nullptr);
/* On successful resolution of the class, it is initialized if it has not /* On successful resolution of the class, it is initialized if it has not

11
c/fatal.c Normal file
View File

@ -0,0 +1,11 @@
#include "printf.h"
#include "fatal.h"
void fatal_print__class_lookup_failed__from_string(const uint8_t * name, int length)
{
printf("class lookup failed: ");
for (int i = 0; i < length; i++) {
printc(name[i]);
}
printc('\n');
}

5
c/fatal.h Normal file
View File

@ -0,0 +1,5 @@
#pragma once
#include <stdint.h>
void fatal_print__class_lookup_failed__from_string(const uint8_t * name, int length);

View File

@ -10,6 +10,7 @@
#include "printf.h" #include "printf.h"
#include "string.h" #include "string.h"
#include "native.h" #include "native.h"
#include "fatal.h"
struct Code_attribute * get_code_attribute(int code_name_index, struct Code_attribute * get_code_attribute(int code_name_index,
int attributes_count, int attributes_count,
@ -525,15 +526,13 @@ void vm_execute(struct vm * vm)
void vm_start(int class_hash_table_length, void vm_start(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
const uint8_t * main_class, const uint8_t * main_class_name,
int main_class_length) int main_class_name_length)
{ {
struct class_entry * class_entry = class_resolver_lookup_class(class_hash_table_length, struct class_entry * class_entry = class_resolver_lookup_class(class_hash_table_length,
class_hash_table, class_hash_table,
main_class, main_class_name,
main_class_length); main_class_name_length);
assert(class_entry != nullptr);
const char * method_name = "main"; const char * method_name = "main";
int method_name_length = string_length(method_name); int method_name_length = string_length(method_name);

View File

@ -162,6 +162,6 @@ void vm_method_return(struct vm * vm);
void vm_execute(struct vm * vm); void vm_execute(struct vm * vm);
void vm_start(int class_hash_table_length, void vm_start(int class_hash_table_length,
struct hash_table_entry * class_hash_table, struct hash_table_entry * class_hash_table,
const uint8_t * main_class, const uint8_t * main_class_name,
int main_class_length); int main_class_name_length);
int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type); int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type);

View File

@ -18,7 +18,8 @@ OBJ = \
c/parse.o \ c/parse.o \
c/unparse.o \ c/unparse.o \
c/native.o \ c/native.o \
c/debug.o c/debug.o \
c/fatal.o
MAIN_DREAMCAST_OBJ = \ MAIN_DREAMCAST_OBJ = \
c/sh7091_scif.o \ c/sh7091_scif.o \

11
p/TestInstanceof.java Normal file
View File

@ -0,0 +1,11 @@
package p;
class TestInstanceof {
public static boolean test() {
TestInstanceof t = new TestInstanceof();
return t instanceof Object;
}
public static void main() {
System.out.println(test());
}
}