execute: implement instanceof for arrays of references

This commit is contained in:
Zack Buhman 2025-01-11 01:46:42 -06:00
parent 48d8db8e9e
commit ec525bbfbc
4 changed files with 73 additions and 5 deletions

View File

@ -10,7 +10,7 @@ CFLAGS += -Wall -Werror -Wfatal-errors -Wno-error=unused-variable -fstack-protec
CFLAGS += -I$(MAKEFILE_PATH)/
CFLAGS += -I$(MAKEFILE_PATH)/c
CFLAGS += -DDEBUG
#CFLAGS += -DDEBUG_PRINT
CFLAGS += -DDEBUG_PRINT
LDFLAGS = -lm
OPT ?= -O0
DEPFLAGS = -MMD -MP

View File

@ -628,6 +628,13 @@ bool class_resolver_instanceof(int class_hash_table_length,
const int class_index,
struct objectref * objectref)
{
struct constant * class_constant = &origin_class_entry->class_file->constant_pool[class_index - 1];
assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &origin_class_entry->class_file->constant_pool[class_constant->class.name_index - 1];
assert(class_name_constant->tag == CONSTANT_Utf8);
int class_name_ix = 0;
struct class_entry * index_class_entry =
class_resolver_lookup_class_from_class_index(class_hash_table_length,
class_hash_table,
@ -636,7 +643,38 @@ bool class_resolver_instanceof(int class_hash_table_length,
assert(index_class_entry != nullptr);
assert(objectref != nullptr);
struct class_entry * class_entry = objectref->class_entry;
struct class_entry * class_entry;
while (true) {
struct tag * tag = (struct tag *)objectref;
if (tag->type == TAG_TYPE_REF_ARRAY || tag->type == TAG_TYPE_PRIM_ARRAY) {
if (class_name_constant->utf8.bytes[class_name_ix] != '[')
return false;
class_name_ix += 1;
struct arrayref * arrayref = (struct arrayref *)objectref;
if (arrayref->class_entry != nullptr) {
class_entry = arrayref->class_entry;
break;
} else {
// FIXME: instanceof is allowed on zero-length arrays
assert(arrayref->length > 0);
objectref = arrayref->oref[0];
}
} else if (tag->type == TAG_TYPE_OBJECT) {
class_entry = objectref->class_entry;
break;
} else {
assert(!"invalid tag type");
}
}
assert(class_entry != nullptr);
if (class_name_constant->utf8.bytes[class_name_ix] == '[')
return false;
while (true) {
debugf("class_entry: %p\n", class_entry);

View File

@ -1745,15 +1745,34 @@ static struct arrayref * _multiarray(struct vm * vm, int32_t * dims, int num_dim
int32_t count = dims[level];
struct arrayref * arrayref;
int32_t element_size;
if (*type == 'L' || *type == '[') {
if (*type == '[') {
element_size = (sizeof (void *));
arrayref = ref_array_allocate(vm, count);
assert(arrayref != nullptr);
arrayref->class_entry = nullptr;
} else if (*type == 'L') {
element_size = (sizeof (void *));
arrayref = ref_array_allocate(vm, count);
assert(arrayref != nullptr);
int type_length = type_end - type;
struct parse_type_ret parse_type_ret = parse_type(type,
type_length);
struct class_entry * class_entry = class_resolver_lookup_class(vm->class_hash_table.length,
vm->class_hash_table.entry,
parse_type_ret.bytes,
parse_type_ret.length);
assert(class_entry != nullptr);
arrayref->class_entry = class_entry;
} else {
element_size = field_size_array(*type);
arrayref = prim_array_allocate(vm, element_size, count);
}
assert(arrayref != nullptr);
arrayref->class_entry = nullptr;
}
int32_t array_element_size = count * element_size; // bytes
int32_t u32_count = (array_element_size + 3) / 4; // u32 units

View File

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