implement checkcast
This commit is contained in:
parent
40ab3ddfd3
commit
49cc665f76
87
c/execute.c
87
c/execute.c
@ -179,7 +179,41 @@ void op_castore(struct vm * vm)
|
|||||||
|
|
||||||
void op_checkcast(struct vm * vm, uint32_t index)
|
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)
|
void op_d2f(struct vm * vm)
|
||||||
@ -1102,32 +1136,35 @@ void op_instanceof(struct vm * vm, uint32_t index)
|
|||||||
assert(index_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) {
|
||||||
|
operand_stack_push_u32(vm->current_frame, (uint32_t)false);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
bool value = false;
|
bool value = false;
|
||||||
if (objectref != nullptr) {
|
struct class_entry * class_entry = (struct class_entry *)objectref[0];
|
||||||
struct class_entry * class_entry = (struct class_entry *)objectref[0];
|
while (true) {
|
||||||
while (true) {
|
assert(class_entry != nullptr);
|
||||||
assert(class_entry != nullptr);
|
if (class_entry == index_class_entry) {
|
||||||
if (class_entry == index_class_entry) {
|
value = true;
|
||||||
value = true;
|
break;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
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);
|
operand_stack_push_u32(vm->current_frame, (uint32_t)value);
|
||||||
}
|
}
|
||||||
|
26
p/CheckCastTest.java
Normal file
26
p/CheckCastTest.java
Normal file
@ -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();
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user