implement instanceof superclass behavior
This commit is contained in:
parent
aa09b6d916
commit
867a10ac2b
2
Makefile
2
Makefile
@ -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
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
53
c/execute.c
53
c/execute.c
@ -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
11
c/fatal.c
Normal 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
5
c/fatal.h
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
void fatal_print__class_lookup_failed__from_string(const uint8_t * name, int length);
|
11
c/frame.c
11
c/frame.c
@ -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);
|
||||||
|
@ -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);
|
||||||
|
3
java.mk
3
java.mk
@ -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
11
p/TestInstanceof.java
Normal 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());
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user