Compare commits

...

2 Commits

Author SHA1 Message Date
9fd801b0d8 frame: add support for public static void main(String args[])
I'm not certain whether I like this, so it's ifdef'ed behind MAIN_STRING_ARRAY
2025-01-19 04:34:43 -06:00
072550042c CLDC 8: add Enum 2025-01-19 04:34:43 -06:00
8 changed files with 152 additions and 10 deletions

View File

@ -14,6 +14,7 @@
#include "find_attribute.h" #include "find_attribute.h"
#include "backtrace.h" #include "backtrace.h"
#include "native_types.h" #include "native_types.h"
#include "native_types_allocate.h"
int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type) int descriptor_nargs(struct constant * descriptor_constant, uint8_t * return_type)
{ {
@ -347,7 +348,11 @@ void vm_method_return(struct vm * vm)
break; break;
} }
assert(old_frame->operand_stack_ix == 0); assert(old_frame->operand_stack_ix == 0);
#ifdef MAIN_STRING_ARRAY
if (vm->frame_stack.ix > 1) {
#else
if (vm->frame_stack.ix > 0) { if (vm->frame_stack.ix > 0) {
#endif
debugs("vm_method_return\n"); debugs("vm_method_return\n");
debugs("current_frame:\n class: "); debugs("current_frame:\n class: ");
debug_print__class_file__class_name(vm->current_frame->class_entry->class_file); debug_print__class_file__class_name(vm->current_frame->class_entry->class_file);
@ -443,7 +448,11 @@ void vm_execute(struct vm * vm)
decode_print_instruction(vm->current_frame->code_attribute->code, vm->current_frame->pc); decode_print_instruction(vm->current_frame->code_attribute->code, vm->current_frame->pc);
#endif #endif
decode_execute_instruction(vm, vm->current_frame->code_attribute->code, vm->current_frame->pc); decode_execute_instruction(vm, vm->current_frame->code_attribute->code, vm->current_frame->pc);
#ifdef MAIN_STRING_ARRAY
if (vm->frame_stack.ix == 1) {
#else
if (vm->frame_stack.ix == 0) { if (vm->frame_stack.ix == 0) {
#endif
debugf("terminate\n"); debugf("terminate\n");
break; break;
} }
@ -465,7 +474,11 @@ struct vm * vm_start(int class_hash_table_length,
const uint8_t * method_name = (const uint8_t *)"main"; const uint8_t * method_name = (const uint8_t *)"main";
int method_name_length = string_length((const char *)method_name); int method_name_length = string_length((const char *)method_name);
#ifdef MAIN_STRING_ARRAY
const uint8_t * method_descriptor = (const uint8_t *)"([Ljava/lang/String;)V";
#else
const uint8_t * method_descriptor = (const uint8_t *)"()V"; const uint8_t * method_descriptor = (const uint8_t *)"()V";
#endif
int method_descriptor_length = string_length((const char *)method_descriptor); int method_descriptor_length = string_length((const char *)method_descriptor);
struct method_entry method_entry = struct method_entry method_entry =
@ -492,6 +505,28 @@ struct vm * vm_start(int class_hash_table_length,
uint32_t data[vm.data_stack.capacity]; uint32_t data[vm.data_stack.capacity];
vm.data_stack.data = data; vm.data_stack.data = data;
#ifdef MAIN_STRING_ARRAY
{
vm.current_frame = stack_push_frame(&vm.frame_stack, 1);
vm.current_frame->operand_stack = stack_push_data(&vm.data_stack, 1);
vm.current_frame->operand_stack_ix = 0;
vm.current_frame->initialization_frame = 0;
vm.current_frame->return_type = 0;
// create empty arrayref
struct arrayref * arrayref = ref_array_allocate(&vm, 0);
assert(arrayref != nullptr);
struct class_entry * string_class_entry = class_resolver_lookup_class(vm.class_hash_table.length,
vm.class_hash_table.entry,
(const uint8_t *)"java/lang/String",
16);
assert(class_entry != nullptr);
arrayref->class_entry = string_class_entry;
operand_stack_push_ref(vm.current_frame, arrayref);
}
#endif // MAIN_STRING_ARRAY
vm_static_method_call(&vm, class_entry, &method_entry); vm_static_method_call(&vm, class_entry, &method_entry);
return &vm; return &vm;

View File

@ -121,9 +121,15 @@ const static struct native_method native_method[] = {
{ {
.class_name = "java/lang/Class", .class_name = "java/lang/Class",
.method_name = "_getName", .method_name = "_getName",
.method_descriptor = "()Ljava/lang/String;", .method_descriptor = "(Ljava/lang/Object;)Ljava/lang/String;",
.func = native_java_lang_class_getname_1, .func = native_java_lang_class_getname_1,
}, },
{
.class_name = "java/lang/Class",
.method_name = "_getSuperclass",
.method_descriptor = "(Ljava/lang/Object;)Ljava/lang/String;",
.func = native_java_lang_class_getsuperclass_1,
},
{ {
.class_name = "java/lang/Object", .class_name = "java/lang/Object",
.method_name = "_getClass", .method_name = "_getClass",

View File

@ -6,18 +6,39 @@ void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args)
{ {
struct objectref * objectref = (struct objectref *)args[0]; struct objectref * objectref = (struct objectref *)args[0];
assert(objectref != nullptr); assert(objectref != nullptr);
assert(objectref->oref[0] != nullptr); assert(objectref->oref[0] != nullptr);
assert(objectref->oref[0]->class_entry != nullptr);
struct class_file * class_file = objectref->oref[0]->class_entry->class_file;
struct constant * class_constant = &class_file->constant_pool[class_file->this_class - 1]; struct class_entry * class_entry = (struct class_entry *)objectref->oref[0];
struct constant * class_constant = &class_entry->class_file->constant_pool[class_entry->class_file->this_class - 1];
assert(class_constant->tag == CONSTANT_Class); assert(class_constant->tag == CONSTANT_Class);
struct constant * class_name_constant = &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];
assert(class_name_constant->tag == CONSTANT_Utf8); assert(class_name_constant->tag == CONSTANT_Utf8);
struct objectref * string_objectref = vm_instance_string_from_constant(vm, class_name_constant); struct objectref * string_objectref = vm_instance_string_from_constant(vm, class_name_constant);
operand_stack_push_ref(vm->current_frame, string_objectref); operand_stack_push_ref(vm->current_frame, string_objectref);
} }
void native_java_lang_class_getsuperclass_1(struct vm * vm, uint32_t * args)
{
struct objectref * objectref = (struct objectref *)args[0];
assert(objectref != nullptr);
assert(objectref->oref[0] != nullptr);
struct class_entry * class_entry = (struct class_entry *)objectref->oref[0];
struct class_entry * super_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 objectref * class_objectref = vm_instance_create(vm, "java/lang/Class");
assert(class_objectref != nullptr);
assert(class_objectref->class_entry->instance_fields_count >= 1);
class_objectref->oref[0] = (struct objectref *)super_class_entry;
operand_stack_push_ref(vm->current_frame, class_objectref);
}

View File

@ -5,3 +5,4 @@
#include "frame.h" #include "frame.h"
void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args); void native_java_lang_class_getname_1(struct vm * vm, uint32_t * args);
void native_java_lang_class_getsuperclass_1(struct vm * vm, uint32_t * args);

View File

@ -10,7 +10,7 @@ void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args)
assert(class_objectref != nullptr); assert(class_objectref != nullptr);
assert(class_objectref->class_entry->instance_fields_count >= 1); assert(class_objectref->class_entry->instance_fields_count >= 1);
class_objectref->oref[0] = objectref; class_objectref->oref[0] = (struct objectref *)objectref->class_entry;
operand_stack_push_ref(vm->current_frame, class_objectref); operand_stack_push_ref(vm->current_frame, class_objectref);
} }

View File

@ -1,18 +1,24 @@
package java.lang; package java.lang;
public final class Class<T> { public final class Class<T> {
private Object object; private Object klass; // struct class_entry *
private String name; private String name;
private Class() { private Class() {
} }
private native String _getName(); private static native String _getName(Object o);
public String getName() { public String getName() {
if (this.name == null) { if (this.name == null) {
this.name = _getName(); this.name = _getName(this);
} }
return this.name; return this.name;
} }
private static native Class<?> _getSuperclass(Class<?> c);
public Class<? super T> getSuperclass() {
return (Class<? super T>)(_getSuperclass(this));
}
} }

View File

@ -0,0 +1,58 @@
package java.lang;
public abstract class Enum<E extends Enum<E>>
implements Comparable<E> {
final String name;
final int ordinal;
protected Enum(String name,
int ordinal) {
this.name = name;
this.ordinal = ordinal;
}
protected final Object clone()
throws CloneNotSupportedException {
throw new CloneNotSupportedException();
}
public final int compareTo(E o) {
if (getDeclaringClass() != o.getDeclaringClass())
throw new ClassCastException();
return ordinal - o.ordinal;
}
public final boolean equals(Object other) {
return this == other;
}
public final Class<E> getDeclaringClass() {
Class c = getClass();
if (c.getSuperclass() != Enum.class)
c = c.getSuperclass();
return c;
}
public final int hashCode() {
return ordinal;
}
public final String name() {
return name;
}
public final int ordinal() {
return ordinal;
}
public String toString() {
return name;
}
public static <T extends Enum<T>> T valueOf(Class<T> enumType,
String name) {
return null;
}
}

View File

@ -0,0 +1,15 @@
package test;
public class TestEnum {
enum Level {
LOW,
MEDIUM,
HIGH
}
public static void main() {
System.out.println(args.length);
Level level = Level.MEDIUM;
System.out.println(level);
}
}