From 49cc665f76bd507780d832aab400609f7c8a5209 Mon Sep 17 00:00:00 2001 From: Zack Buhman Date: Mon, 30 Dec 2024 10:54:28 -0600 Subject: [PATCH] implement checkcast --- c/execute.c | 87 +++++++++++++++++++++++++++++++------------- p/CheckCastTest.java | 26 +++++++++++++ 2 files changed, 88 insertions(+), 25 deletions(-) create mode 100644 p/CheckCastTest.java diff --git a/c/execute.c b/c/execute.c index 83be34e..0748fb7 100644 --- a/c/execute.c +++ b/c/execute.c @@ -179,7 +179,41 @@ void op_castore(struct vm * vm) void op_checkcast(struct vm * vm, uint32_t index) { - assert(!"op_checkcast"); + int32_t * objectref = (int32_t *)operand_stack_peek_u32(vm->current_frame, 1); + if (objectref == nullptr) { + return; + } + + struct class_entry * index_class_entry = + class_resolver_lookup_class_from_class_index(vm->class_hash_table.length, + vm->class_hash_table.entry, + vm->current_frame->class_entry, + index); + + struct class_entry * class_entry = (struct class_entry *)objectref[0]; + while (true) { + assert(class_entry != nullptr); + if (class_entry == index_class_entry) { + return; + } + 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); + } + assert(!"ClassCastException"); } void op_d2f(struct vm * vm) @@ -1102,32 +1136,35 @@ void op_instanceof(struct vm * vm, uint32_t index) assert(index_class_entry != nullptr); int32_t * objectref = (int32_t *)operand_stack_pop_u32(vm->current_frame); + if (objectref == nullptr) { + operand_stack_push_u32(vm->current_frame, (uint32_t)false); + return; + } + bool value = false; - if (objectref != nullptr) { - struct class_entry * class_entry = (struct class_entry *)objectref[0]; - while (true) { - 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); + struct class_entry * class_entry = (struct class_entry *)objectref[0]; + while (true) { + 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); } diff --git a/p/CheckCastTest.java b/p/CheckCastTest.java new file mode 100644 index 0000000..661cee8 --- /dev/null +++ b/p/CheckCastTest.java @@ -0,0 +1,26 @@ +package p; + +class Animal { +} + +class Cat extends Animal { +} + +class Dog extends Animal { +} + +class CheckCastTest { + public static boolean test() { + Dog d = new Dog(); + Cat c = new Cat(); + Animal da = d; + Animal ca = c; + Cat cc = (Cat)da; + //Cat cc = (Cat)ca; + return cc instanceof Cat; + } + + public static void main() { + test(); + } +}