implement java.lang.Class.getName
This commit is contained in:
parent
aaa55a4f9d
commit
008690543d
@ -441,14 +441,22 @@ struct method_entry class_resolver_lookup_method_from_interfacemethodref_index(i
|
|||||||
struct attribute_info * attribute = find_attribute(code_index,
|
struct attribute_info * attribute = find_attribute(code_index,
|
||||||
method_info->attributes_count,
|
method_info->attributes_count,
|
||||||
method_info->attributes);
|
method_info->attributes);
|
||||||
assert(attribute != nullptr);
|
|
||||||
|
|
||||||
|
if ((method_info->access_flags & METHOD_ACC_NATIVE) != 0) {
|
||||||
|
return (struct method_entry){
|
||||||
|
.class_entry = class_entry,
|
||||||
|
.method_info = method_info,
|
||||||
|
.code_attribute = nullptr,
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
assert(attribute != nullptr);
|
||||||
return (struct method_entry){
|
return (struct method_entry){
|
||||||
.class_entry = class_entry,
|
.class_entry = class_entry,
|
||||||
.method_info = method_info,
|
.method_info = method_info,
|
||||||
.code_attribute = attribute->code,
|
.code_attribute = attribute->code,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (class_entry->class_file->super_class == 0)
|
if (class_entry->class_file->super_class == 0)
|
||||||
break;
|
break;
|
||||||
@ -606,24 +614,12 @@ struct objectref * class_resolver_lookup_string(struct vm * vm,
|
|||||||
struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_constant->string.string_index - 1];
|
struct constant * utf8_constant = &class_entry->class_file->constant_pool[string_constant->string.string_index - 1];
|
||||||
assert(utf8_constant->tag == CONSTANT_Utf8);
|
assert(utf8_constant->tag == CONSTANT_Utf8);
|
||||||
|
|
||||||
int32_t count = utf8_constant->utf8.length;
|
struct objectref * string_objectref = vm_instance_string_from_constant(vm, utf8_constant);
|
||||||
struct arrayref * arrayref = prim_array_allocate(vm, 1, count);
|
|
||||||
assert(arrayref != nullptr);
|
|
||||||
arrayref->class_entry = nullptr; // byte[]
|
|
||||||
arrayref->length = utf8_constant->utf8.length;
|
|
||||||
for (int i = 0; i < utf8_constant->utf8.length; i++) {
|
|
||||||
arrayref->u8[i] = utf8_constant->utf8.bytes[i];
|
|
||||||
}
|
|
||||||
|
|
||||||
struct objectref * objectref = vm_instance_create(vm, "java/lang/String");
|
|
||||||
assert(objectref != nullptr);
|
|
||||||
assert(objectref->class_entry->instance_fields_count >= 1);
|
|
||||||
objectref->aref[0] = arrayref;
|
|
||||||
|
|
||||||
// cache the result
|
// cache the result
|
||||||
class_entry->attribute_entry[string_index - 1].string_objectref = objectref;
|
class_entry->attribute_entry[string_index - 1].string_objectref = string_objectref;
|
||||||
|
|
||||||
return objectref;
|
return string_objectref;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool class_resolver_instanceof(int class_hash_table_length,
|
bool class_resolver_instanceof(int class_hash_table_length,
|
||||||
|
22
c/native.c
22
c/native.c
@ -3,10 +3,12 @@
|
|||||||
#include "string.h"
|
#include "string.h"
|
||||||
#include "printf.h"
|
#include "printf.h"
|
||||||
#include "native.h"
|
#include "native.h"
|
||||||
|
#include "native/class.h"
|
||||||
|
#include "native/loader.h"
|
||||||
#include "native/math.h"
|
#include "native/math.h"
|
||||||
#include "native/memory.h"
|
#include "native/memory.h"
|
||||||
|
#include "native/object.h"
|
||||||
#include "native/printstream.h"
|
#include "native/printstream.h"
|
||||||
#include "native/loader.h"
|
|
||||||
|
|
||||||
typedef void (* native_func_t)(struct vm * vm, uint32_t * args);
|
typedef void (* native_func_t)(struct vm * vm, uint32_t * args);
|
||||||
|
|
||||||
@ -102,6 +104,24 @@ const static struct native_method native_method[] = {
|
|||||||
.method_descriptor = "()I",
|
.method_descriptor = "()I",
|
||||||
.func = native_jvm_internal_loader_getbuffer_0,
|
.func = native_jvm_internal_loader_getbuffer_0,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
.class_name = "java/lang/Class",
|
||||||
|
.method_name = "getClassName",
|
||||||
|
.method_descriptor = "()Ljava/lang/String;",
|
||||||
|
.func = native_java_lang_class_getclassname_1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.class_name = "java/lang/Object",
|
||||||
|
.method_name = "getClass",
|
||||||
|
.method_descriptor = "()Ljava/lang/Class;",
|
||||||
|
.func = native_java_lang_object_getclass_1,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.class_name = "java/lang/Object",
|
||||||
|
.method_name = "hashCode",
|
||||||
|
.method_descriptor = "()I",
|
||||||
|
.func = native_java_lang_object_hashcode_1,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
struct hash_table_entry * native_init_hash_table(int * hash_table_length)
|
struct hash_table_entry * native_init_hash_table(int * hash_table_length)
|
||||||
|
23
c/native/class.c
Normal file
23
c/native/class.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "class.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "vm_instance.h"
|
||||||
|
|
||||||
|
void native_java_lang_class_getclassname_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
struct objectref * objectref = (struct objectref *)args[0];
|
||||||
|
assert(objectref != 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];
|
||||||
|
assert(class_constant->tag == CONSTANT_Class);
|
||||||
|
|
||||||
|
struct constant * class_name_constant = &class_file->constant_pool[class_constant->class.name_index - 1];
|
||||||
|
assert(class_name_constant->tag == CONSTANT_Utf8);
|
||||||
|
|
||||||
|
struct objectref * string_objectref = vm_instance_string_from_constant(vm, class_name_constant);
|
||||||
|
|
||||||
|
operand_stack_push_ref(vm->current_frame, string_objectref);
|
||||||
|
}
|
7
c/native/class.h
Normal file
7
c/native/class.h
Normal file
@ -0,0 +1,7 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
|
void native_java_lang_class_getclassname_1(struct vm * vm, uint32_t * args);
|
23
c/native/object.c
Normal file
23
c/native/object.c
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
#include "object.h"
|
||||||
|
#include "printf.h"
|
||||||
|
#include "vm_instance.h"
|
||||||
|
|
||||||
|
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
struct objectref * objectref = (struct objectref *)args[0];
|
||||||
|
assert(objectref != nullptr);
|
||||||
|
|
||||||
|
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] = objectref;
|
||||||
|
|
||||||
|
operand_stack_push_ref(vm->current_frame, class_objectref);
|
||||||
|
}
|
||||||
|
|
||||||
|
void native_java_lang_object_hashcode_1(struct vm * vm, uint32_t * args)
|
||||||
|
{
|
||||||
|
struct objectref * objectref = (struct objectref *)args[0];
|
||||||
|
operand_stack_push_u32(vm->current_frame, (uint32_t)objectref); // objectref as integer
|
||||||
|
}
|
9
c/native/object.h
Normal file
9
c/native/object.h
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include "frame.h"
|
||||||
|
|
||||||
|
void native_java_lang_object_getclass_1(struct vm * vm, uint32_t * args);
|
||||||
|
|
||||||
|
void native_java_lang_object_hashcode_1(struct vm * vm, uint32_t * args);
|
@ -21,3 +21,22 @@ struct objectref * vm_instance_create(struct vm * vm, const char * class_name)
|
|||||||
|
|
||||||
return objectref;
|
return objectref;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct objectref * vm_instance_string_from_constant(struct vm * vm, struct constant * constant)
|
||||||
|
{
|
||||||
|
int32_t count = constant->utf8.length;
|
||||||
|
struct arrayref * arrayref = prim_array_allocate(vm, 1, count);
|
||||||
|
assert(arrayref != nullptr);
|
||||||
|
arrayref->class_entry = nullptr; // byte[]
|
||||||
|
arrayref->length = constant->utf8.length;
|
||||||
|
for (int i = 0; i < constant->utf8.length; i++) {
|
||||||
|
arrayref->u8[i] = constant->utf8.bytes[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
struct objectref * objectref = vm_instance_create(vm, "java/lang/String");
|
||||||
|
assert(objectref != nullptr);
|
||||||
|
assert(objectref->class_entry->instance_fields_count >= 1);
|
||||||
|
objectref->aref[0] = arrayref;
|
||||||
|
|
||||||
|
return objectref;
|
||||||
|
}
|
||||||
|
@ -3,3 +3,4 @@
|
|||||||
#include "frame.h"
|
#include "frame.h"
|
||||||
|
|
||||||
struct objectref * vm_instance_create(struct vm * vm, const char * class_name);
|
struct objectref * vm_instance_create(struct vm * vm, const char * class_name);
|
||||||
|
struct objectref * vm_instance_string_from_constant(struct vm * vm, struct constant * constant);
|
||||||
|
8
classes/test/TestClass.java
Normal file
8
classes/test/TestClass.java
Normal file
@ -0,0 +1,8 @@
|
|||||||
|
package test;
|
||||||
|
|
||||||
|
class TestClass {
|
||||||
|
public static void main() {
|
||||||
|
TestClass obj = new TestClass();
|
||||||
|
System.out.println(obj.getClass().getName());
|
||||||
|
}
|
||||||
|
}
|
2
java.mk
2
java.mk
@ -21,9 +21,11 @@ OBJ = \
|
|||||||
c/malloc.o \
|
c/malloc.o \
|
||||||
c/memory_allocator.o \
|
c/memory_allocator.o \
|
||||||
c/native.o \
|
c/native.o \
|
||||||
|
c/native/class.o \
|
||||||
c/native/loader.o \
|
c/native/loader.o \
|
||||||
c/native/math.o \
|
c/native/math.o \
|
||||||
c/native/memory.o \
|
c/native/memory.o \
|
||||||
|
c/native/object.o \
|
||||||
c/native/printstream.o \
|
c/native/printstream.o \
|
||||||
c/parse.o \
|
c/parse.o \
|
||||||
c/parse_type.o \
|
c/parse_type.o \
|
||||||
|
Loading…
x
Reference in New Issue
Block a user