partial support for checkcast and instanceof on object arrays

This commit is contained in:
Zack Buhman 2024-12-30 11:49:52 -06:00
parent 49cc665f76
commit e22f2e87e8
7 changed files with 109 additions and 13 deletions

View File

@ -12,6 +12,7 @@
#include "field_size.h" #include "field_size.h"
#include "debug.h" #include "debug.h"
#include "fatal.h" #include "fatal.h"
#include "parse_type.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)
{ {
@ -290,18 +291,18 @@ struct class_entry * class_resolver_lookup_class_from_class_index(int class_hash
} }
struct constant * class_constant = &class_entry->class_file->constant_pool[class_index - 1]; struct constant * class_constant = &class_entry->class_file->constant_pool[class_index - 1];
#ifdef DEBUG
assert(class_constant->tag == CONSTANT_Class); assert(class_constant->tag == CONSTANT_Class);
#endif
struct constant * class_name_constant = &class_entry->class_file->constant_pool[class_constant->class.name_index - 1]; 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); assert(class_name_constant->tag == CONSTANT_Utf8);
#endif
struct parse_type_ret parse_type_ret = parse_type(class_name_constant->utf8.bytes,
class_name_constant->utf8.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,
class_name_constant->utf8.bytes, parse_type_ret.bytes,
class_name_constant->utf8.length); parse_type_ret.length);
if (_class_entry != nullptr) { 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;

View File

@ -38,11 +38,6 @@ struct class_entry {
int32_t * static_fields; int32_t * static_fields;
int32_t instance_fields_count; int32_t instance_fields_count;
struct {
int length;
struct hash_table_entry * entry;
} interfaces;
struct { struct {
int length; int length;
struct hash_table_entry * entry; struct hash_table_entry * entry;

View File

@ -5,6 +5,8 @@
#include "execute_helper.h" #include "execute_helper.h"
#include "printf.h" #include "printf.h"
#include "field_size.h" #include "field_size.h"
#include "debug.h"
#include "parse_type.h"
void op_aaload(struct vm * vm) void op_aaload(struct vm * vm)
{ {
@ -190,7 +192,25 @@ void op_checkcast(struct vm * vm, uint32_t index)
vm->current_frame->class_entry, vm->current_frame->class_entry,
index); index);
struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1];
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
int depth = parse_type_array_depth(class_name_constant->utf8.bytes, class_name_constant->utf8.length);
while (depth-- > 0) {
if (objectref == nullptr || objectref[0] == 0)
assert(!"checkcast on null or zero-length array not implemented");
objectref = (int32_t *)objectref[1];
}
if (objectref == nullptr) {
assert(!"checkcast on array with null elements not implemented");
}
struct class_entry * class_entry = (struct class_entry *)objectref[0]; struct class_entry * class_entry = (struct class_entry *)objectref[0];
debug_print__class_entry__class_name(index_class_entry);
debug_print__class_entry__class_name(class_entry);
while (true) { while (true) {
assert(class_entry != nullptr); assert(class_entry != nullptr);
if (class_entry == index_class_entry) { if (class_entry == index_class_entry) {
@ -1141,6 +1161,22 @@ void op_instanceof(struct vm * vm, uint32_t index)
return; return;
} }
struct constant * class_constant = &vm->current_frame->class_entry->class_file->constant_pool[index - 1];
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &vm->current_frame->class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
int depth = parse_type_array_depth(class_name_constant->utf8.bytes, class_name_constant->utf8.length);
printf("depth: %d\n", depth);
while (depth-- > 0) {
if (objectref == nullptr || objectref[0] == 0)
assert(!"instanceof on null or zero-length array not implemented");
objectref = (int32_t *)objectref[1];
}
if (objectref == nullptr) {
assert(!"instanceof on array with null elements not implemented");
}
bool value = false; bool value = false;
struct class_entry * class_entry = (struct class_entry *)objectref[0]; struct class_entry * class_entry = (struct class_entry *)objectref[0];
while (true) { while (true) {

34
c/parse_type.c Normal file
View File

@ -0,0 +1,34 @@
#include "assert.h"
#include "parse_type.h"
struct parse_type_ret parse_type(uint8_t * bytes, uint32_t length)
{
if (bytes[length - 1] != ';') {
assert(bytes[0] != '[');
return (struct parse_type_ret){ bytes, length };
}
int ix = 0;
while (bytes[ix] == '[') {
ix += 1;
}
assert(bytes[ix] == 'L');
ix += 1;
return (struct parse_type_ret){ &bytes[ix], length - ix - 1 };
}
int parse_type_array_depth(uint8_t * bytes, uint32_t length)
{
if (bytes[length - 1] != ';') {
assert(bytes[0] != '[');
return 0;
}
int ix = 0;
while (bytes[ix] == '[') {
ix += 1;
}
assert(bytes[ix] == 'L');
return ix;
}

11
c/parse_type.h Normal file
View File

@ -0,0 +1,11 @@
#pragma once
#include <stdint.h>
struct parse_type_ret {
uint8_t * bytes;
uint32_t length;
};
struct parse_type_ret parse_type(uint8_t * bytes, uint32_t length);
int parse_type_array_depth(uint8_t * bytes, uint32_t length);

View File

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

View File

@ -20,7 +20,25 @@ class CheckCastTest {
return cc instanceof Cat; return cc instanceof Cat;
} }
public static boolean arrayTest() {
Dog[][] d = new Dog[1][1];
Cat[][] c = new Cat[1][1];
Animal[][] da = d;
Animal[][] ca = c;
//Cat[][] cc = (Cat[][])da;
Cat[][] cc = (Cat[][])ca;
return cc instanceof Cat[][];
}
public static boolean arrayTest2() {
Cat[] c = new Cat[1];
c[0] = new Cat();
return c instanceof Cat[];
}
public static void main() { public static void main() {
test(); //test();
arrayTest2();
//System.out.println(arrayTest());
} }
} }