diff --git a/src/Library/Builtin.cpp b/src/Library/Builtin.cpp index 54163e6..2da815d 100644 --- a/src/Library/Builtin.cpp +++ b/src/Library/Builtin.cpp @@ -30,6 +30,7 @@ #include "sun/misc/Unsafe.h" #include "sun/misc/VM.h" #include "sun/reflect/Reflection.h" +#include "sun/reflect/NativeConstructorAccessorImpl.h" #include "vigur/lang/System.h" void registerBuiltinRegisterNatives() @@ -61,4 +62,5 @@ void registerBuiltinRegisterNatives() // Reflection API registerNative("sun/reflect/Reflection/getCallerClass", "()Ljava/lang/Class;", lib_sun_reflect_Reflection_getCallerClass); registerNative("sun/reflect/Reflection/getClassAccessFlags", "(Ljava/lang/Class;)I", lib_sun_reflect_Reflection_getClassAccessFlags); + registerNative("sun/reflect/NativeConstructorAccessorImpl/newInstance0", "(Ljava/lang/reflect/Constructor;[Ljava/lang/Object;)Ljava/lang/Object;", lib_sun_reflect_NativeConstructorAccessorImpl_newInstance0); } diff --git a/src/Library/CMakeLists.txt b/src/Library/CMakeLists.txt index ebfdc27..c793de3 100644 --- a/src/Library/CMakeLists.txt +++ b/src/Library/CMakeLists.txt @@ -30,6 +30,8 @@ add_library(Library sun/misc/VM.cpp sun/reflect/Reflection.h sun/reflect/Reflection.cpp + sun/reflect/NativeConstructorAccessorImpl.h + sun/reflect/NativeConstructorAccessorImpl.cpp java/security/AccessController.h java/security/AccessController.cpp vigur/lang/System.h diff --git a/src/Library/java/lang/Class.cpp b/src/Library/java/lang/Class.cpp index 6311777..9815402 100644 --- a/src/Library/java/lang/Class.cpp +++ b/src/Library/java/lang/Class.cpp @@ -53,6 +53,9 @@ JCALL void lib_java_lang_Class_registerNatives(const NativeArgs& args) registerNative("java/lang/Class/isPrimitive", "()Z", lib_java_lang_Class_isPrimitive); registerNative("java/lang/Class/isAssignableFrom", "(Ljava/lang/Class;)Z", lib_java_lang_Class_isAssignableFrom); registerNative("java/lang/Class/isInterface", "()Z", lib_java_lang_Class_isInterface); + registerNative("java/lang/Class/getDeclaredConstructors0", "(Z)[Ljava/lang/reflect/Constructor;", lib_java_lang_Class_getDeclaredConstructors0); + registerNative("java/lang/Class/getModifiers", "()I", lib_java_lang_Class_getModifiers); + registerNative("java/lang/Class/getSuperclass", "()Ljava/lang/Class;", lib_java_lang_Class_getSuperClass); } JCALL void lib_java_lang_Class_getPrimitiveClass(const NativeArgs& args) @@ -110,9 +113,10 @@ JCALL void lib_java_lang_Class_forName0(const NativeArgs& args) const StackFrame* currentFrame = args.thread->m_currentFrame; const Variable var = currentFrame->localVariables[0]; args.vm->checkType(var, VariableType_REFERENCE, args.thread); + // TODO: Allocate this string on the memory collected heap const std::string_view className = args.heap->getStringContent(var.data); - std::string canonicalClassName = std::string(className.data(), className.size()); - std::replace(canonicalClassName.begin(), canonicalClassName.end(), + std::string *canonicalClassName = new std::string(className.data(), className.size()); + std::replace(canonicalClassName->begin(), canonicalClassName->end(), '.', '/'); // TODO: Check initialize bool @@ -131,8 +135,8 @@ JCALL void lib_java_lang_Class_forName0(const NativeArgs& args) args.thread->internalError("Use of custom classloader not implemented yet"); } - ClassInfo* classInfo = args.vm->getClass(canonicalClassName, args.thread); - const u4 classObjectRef = args.heap->createClassObject(classInfo, args.vm, canonicalClassName); + ClassInfo* classInfo = args.vm->getClass(*canonicalClassName, args.thread); + const u4 classObjectRef = args.heap->createClassObject(classInfo, args.vm, *canonicalClassName); args.thread->returnVar(Variable{VariableType_REFERENCE, classObjectRef}); } @@ -259,3 +263,71 @@ JCALL void lib_java_lang_Class_isInterface(const NativeArgs& args) } args.thread->returnVar(Variable{VariableType_INT, result}); } + +JCALL void lib_java_lang_Class_getDeclaredConstructors0(const NativeArgs& args) +{ + const ClassObject* classObject = getThisClassObjectReference(args.thread, args.heap, args.vm); + const StackFrame* currentFrame = args.thread->m_currentFrame; + // TODO: Use publicOnlyBooleanVar + [[maybe_unused]] const Variable publicOnlyBooleanVar = currentFrame->localVariables[1]; + const u4 arraySize = classObject->classClassInfo->methods.size(); + const u4 arrayObject = args.heap->createArray(AT_REFERENCE, 1); + + const Array* constructorsArray = args.heap->getArray(arrayObject); + + ClassInfo* constructorClass = args.vm->getClass("java/lang/reflect/Constructor", args.thread); + + for (u4 currentMethod = 0; currentMethod < arraySize; ++currentMethod) + { + const u4 constructorObjectRef = args.heap->createObject(constructorClass, args.vm); + const Object* constructorObject = args.heap->getObject(constructorObjectRef); + const MethodInfo* methodInfo = classObject->classClassInfo->methods[currentMethod]; + + // Set the slot field + FieldData* slotField = constructorObject->getField("slot", "I", args.heap); + slotField->data->data = currentMethod; + + // Set the class field + FieldData* classField = constructorObject->getField("clazz", "Ljava/lang/Class;", args.heap); + classField->data->data = currentFrame->localVariables[0].data; + + // Set the modifiers field + FieldData* modifiersField = constructorObject->getField("modifiers", "I", args.heap); + modifiersField->data->data = methodInfo->accessFlags; + + // Set the parameterTypes field + FieldData* parameterTypes = constructorObject->getField("parameterTypes", "[Ljava/lang/Class;", args.heap); + const u4 argsArray = args.heap->createArray(AT_REFERENCE, 0); + parameterTypes->data->data = argsArray; + + u4* array = reinterpret_cast(constructorsArray->data); + array[currentMethod] = constructorObjectRef; + } + + args.thread->returnVar(Variable{VariableType_REFERENCE, arrayObject}); + printf(""); +} + +JCALL void lib_java_lang_Class_getModifiers(const NativeArgs& args) +{ + const ClassObject* classObject = getThisClassObjectReference(args.thread, args.heap, args.vm); + args.thread->returnVar(Variable{VariableType_INT, classObject->classClassInfo->accessFlags}); + printf(""); +} + +JCALL void lib_java_lang_Class_getSuperClass(const NativeArgs& args) +{ + const ClassObject* classObject = getThisClassObjectReference(args.thread, args.heap, args.vm); + if (classObject->classClassInfo->superClass != 0) + { + const CPClassInfo* classInfoConstant = classObject->classClassInfo->constantPool->getClassInfo(classObject->classClassInfo->superClass); + const std::string_view className = classObject->classClassInfo->constantPool->getString(classInfoConstant->nameIndex); + ClassInfo* classInfo = args.vm->getClass(className, args.thread); + const u4 superClassObject = args.heap->createClassObject(classInfo,args.vm, className); + args.thread->returnVar(Variable{VariableType_REFERENCE, superClassObject}); + } else + { + args.thread->returnVar(Variable{VariableType_REFERENCE, 0}); + } + printf(""); +} diff --git a/src/Library/java/lang/Class.h b/src/Library/java/lang/Class.h index c445074..26b1002 100644 --- a/src/Library/java/lang/Class.h +++ b/src/Library/java/lang/Class.h @@ -10,4 +10,7 @@ JCALL void lib_java_lang_Class_forName0(const NativeArgs& args); JCALL void lib_java_lang_Class_getDeclaredFields0(const NativeArgs& args); JCALL void lib_java_lang_Class_isPrimitive(const NativeArgs& args); JCALL void lib_java_lang_Class_isAssignableFrom(const NativeArgs& args); -JCALL void lib_java_lang_Class_isInterface(const NativeArgs& args); \ No newline at end of file +JCALL void lib_java_lang_Class_isInterface(const NativeArgs& args); +JCALL void lib_java_lang_Class_getDeclaredConstructors0(const NativeArgs& args); +JCALL void lib_java_lang_Class_getModifiers(const NativeArgs& args); +JCALL void lib_java_lang_Class_getSuperClass(const NativeArgs& args); \ No newline at end of file diff --git a/src/Library/java/lang/Object.cpp b/src/Library/java/lang/Object.cpp index 9eb2b40..952ec96 100644 --- a/src/Library/java/lang/Object.cpp +++ b/src/Library/java/lang/Object.cpp @@ -19,6 +19,7 @@ JCALL void lib_java_lang_Object_registerNatives(const NativeArgs& args) { registerNative("java/lang/Object/hashCode", "()I", lib_java_lang_Object_hashCode); registerNative("java/lang/Object/getClass", "()Ljava/lang/Class;", lib_java_lang_Object_getClass); + registerNative("java/lang/Object/clone", "()Ljava/lang/Object;", lib_java_lang_Object_clone); } JCALL void lib_java_lang_Object_hashCode(const NativeArgs& args) @@ -35,3 +36,19 @@ JCALL void lib_java_lang_Object_getClass(const NativeArgs& args) const u4 classObject = args.heap->createClassObject(object->classInfo, args.vm, object->classInfo->getName()); args.thread->returnVar(Variable{VariableType_REFERENCE, classObject}); } + +JCALL void lib_java_lang_Object_clone(const NativeArgs& args) +{ + const Reference* reference = args.heap->getReference(args.thread->m_currentFrame->localVariables[0].data); + if (reference->type == ARRAY) + { + const Array* array = reference->getArray(); + const u4 cloneRef = args.heap->createArray(array->arrayType, array->length); + const Array* clone = args.heap->getArray(cloneRef); + // TODO: Do the copy of the data + args.thread->returnVar(Variable{VariableType_REFERENCE, cloneRef}); + printf(""); + } else if (reference->type == CLASSOBJECT || reference->type == OBJECT) { + args.thread->internalError("Not implemented yet"); + } +} diff --git a/src/Library/java/lang/Object.h b/src/Library/java/lang/Object.h index bcea16a..b5b8cdd 100644 --- a/src/Library/java/lang/Object.h +++ b/src/Library/java/lang/Object.h @@ -4,4 +4,5 @@ JCALL void lib_java_lang_Object_registerNatives(const NativeArgs& args); JCALL void lib_java_lang_Object_hashCode(const NativeArgs& args); -JCALL void lib_java_lang_Object_getClass(const NativeArgs& args); \ No newline at end of file +JCALL void lib_java_lang_Object_getClass(const NativeArgs& args); +JCALL void lib_java_lang_Object_clone(const NativeArgs& args); \ No newline at end of file diff --git a/src/Library/sun/misc/Unsafe.cpp b/src/Library/sun/misc/Unsafe.cpp index fa11744..7abd46c 100644 --- a/src/Library/sun/misc/Unsafe.cpp +++ b/src/Library/sun/misc/Unsafe.cpp @@ -27,6 +27,7 @@ JCALL void lib_sun_misc_Unsafe_registerNatives([[maybe_unused]]const NativeArgs& registerNative("sun/misc/Unsafe/compareAndSwapObject", "(Ljava/lang/Object;JLjava/lang/Object;Ljava/lang/Object;)Z", lib_sun_misc_Unsafe_compareAndSwapObject); registerNative("sun/misc/Unsafe/compareAndSwapInt", "(Ljava/lang/Object;JII)Z", lib_sun_misc_Unsafe_compareAndSwapInt); registerNative("sun/misc/Unsafe/getIntVolatile", "(Ljava/lang/Object;J)I", lib_sun_misc_Unsafe_getIntVolatile); + registerNative("sun/misc/Unsafe/allocateMemory", "(J)J", lib_sun_misc_Unsafe_allocateMemory); } JCALL void lib_sun_misc_Unsafe_arrayBaseOffset(const NativeArgs& args) @@ -139,3 +140,12 @@ JCALL void lib_sun_misc_Unsafe_getIntVolatile(const NativeArgs& args) args.thread->returnVar(Variable{VariableType_INT, fieldData.data->data}); } + +JCALL void lib_sun_misc_Unsafe_allocateMemory(const NativeArgs& args) +{ + const u8 size = ((static_cast(args.thread->m_currentFrame->localVariables[1].data) << 32) | static_cast(args.thread->m_currentFrame->localVariables[2].data)); + const u8 address = reinterpret_cast (malloc(size)); + const auto parts = reinterpret_cast(&address); + args.thread->returnVar(Variable{VariableType_LONG, parts[1]}, + Variable{VariableType_LONG, parts[0]}); +} diff --git a/src/Library/sun/misc/Unsafe.h b/src/Library/sun/misc/Unsafe.h index c4ca893..f78bd51 100644 --- a/src/Library/sun/misc/Unsafe.h +++ b/src/Library/sun/misc/Unsafe.h @@ -9,4 +9,5 @@ JCALL void lib_sun_misc_Unsafe_addressSize(const NativeArgs& args); JCALL void lib_sun_misc_Unsafe_objectFieldOffset(const NativeArgs& args); JCALL void lib_sun_misc_Unsafe_compareAndSwapObject(const NativeArgs& args); JCALL void lib_sun_misc_Unsafe_compareAndSwapInt(const NativeArgs& args); -JCALL void lib_sun_misc_Unsafe_getIntVolatile(const NativeArgs& args); \ No newline at end of file +JCALL void lib_sun_misc_Unsafe_getIntVolatile(const NativeArgs& args); +JCALL void lib_sun_misc_Unsafe_allocateMemory(const NativeArgs& args); \ No newline at end of file diff --git a/src/Library/sun/reflect/NativeConstructorAccessorImpl.cpp b/src/Library/sun/reflect/NativeConstructorAccessorImpl.cpp new file mode 100644 index 0000000..5425013 --- /dev/null +++ b/src/Library/sun/reflect/NativeConstructorAccessorImpl.cpp @@ -0,0 +1,50 @@ +/* +* Copyright (c) 2023-2024 Sebastiaan Fernandez. + * + * This file is part of VigurVM. + * + * VigurVM is free software: you can redistribute it and/or modify it under the terms of the + * GNU General Public License as published by the Free Software Foundation, + * either version 3 of the License, or (at your option) any later version. + * VigurVM is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; + * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU General Public License for more details. + * You should have received a copy of the GNU General Public License along with Foobar. + * If not, see . + */ + +#include "NativeConstructorAccessorImpl.h" + +JCALL void lib_sun_reflect_NativeConstructorAccessorImpl_newInstance0(const NativeArgs& args) +{ + const Object* constructor = args.heap->getObject(args.thread->m_currentFrame->localVariables[0].data); + + const FieldData* slotField = constructor->getField("slot", "I", args.heap); + + // Set the class field + const FieldData* classField = constructor->getField("clazz", "Ljava/lang/Class;", args.heap); + const ClassObject* classObject = args.heap->getClassObject(classField->data->data); + + // Set the modifiers field + const FieldData* modifiersField = constructor->getField("modifiers", "I", args.heap); + + // Set the parameterTypes field + const FieldData* parameterTypes = constructor->getField("parameterTypes", "[Ljava/lang/Class;", args.heap); + + + const MethodInfo* constructorMethod = classObject->classClassInfo->methods[slotField->data->data]; + + + const u4 objectRef = args.heap->createObject(classObject->classClassInfo, args.vm); + + args.thread->pushStackFrameWithoutParams(classObject->classClassInfo, constructorMethod); + args.thread->m_currentFrame->localVariables[0] = Variable{VariableType_REFERENCE, objectRef}; + // TODO: Implement passing of n arguments to constructor + + args.vm->executeLoop(args.thread); + + args.thread->returnVar(Variable{VariableType_REFERENCE, objectRef}); + + + printf(""); +} diff --git a/src/Library/sun/reflect/NativeConstructorAccessorImpl.h b/src/Library/sun/reflect/NativeConstructorAccessorImpl.h new file mode 100644 index 0000000..70c7c19 --- /dev/null +++ b/src/Library/sun/reflect/NativeConstructorAccessorImpl.h @@ -0,0 +1,5 @@ +#pragma once + +#include "Library/NativeDefs.h" + +JCALL void lib_sun_reflect_NativeConstructorAccessorImpl_newInstance0(const NativeArgs& args); \ No newline at end of file diff --git a/src/VM/Instructions/ConstantInstructions.cpp b/src/VM/Instructions/ConstantInstructions.cpp index ae714de..d8f2e72 100644 --- a/src/VM/Instructions/ConstantInstructions.cpp +++ b/src/VM/Instructions/ConstantInstructions.cpp @@ -112,11 +112,7 @@ void loadConstant(VMThread* thread, const u4 index, JavaHeap* heap, VM* VM) const auto* classInfo = static_cast(cpItem); std::string_view className = thread->m_currentClass->constantPool->getString(classInfo->nameIndex); ClassInfo* classInfoPtr{nullptr}; - // TODO: Improve Array class support - if (!className.starts_with("[")) - { - classInfoPtr = VM->getClass(className.data(), thread); - } + classInfoPtr = VM->getClass(className.data(), thread); const u4 classObjectRef = heap->createClassObject(classInfoPtr, VM, className); const Variable classObjectVar{VariableType_REFERENCE, classObjectRef}; thread->m_currentFrame->operands.push_back(classObjectVar); diff --git a/src/VM/Instructions/LoadInstructions.cpp b/src/VM/Instructions/LoadInstructions.cpp index 1f2429f..4b82b50 100644 --- a/src/VM/Instructions/LoadInstructions.cpp +++ b/src/VM/Instructions/LoadInstructions.cpp @@ -114,6 +114,20 @@ void aaload(const InstructionInput& input) input.thread->m_currentFrame->operands.push_back(dataVar); } +void baload(const InstructionInput& input) +{ + const Variable index = input.thread->m_currentFrame->popOperand(); + const Variable arrayRef = input.thread->m_currentFrame->popOperand(); + + const Array* array = input.heap->getArray(arrayRef.data); + const i4* intArray = (i4*) array->data; + + const i4 data = intArray[index.data]; + + const Variable dataVar{VariableType_INT, std::bit_cast(data)}; + input.thread->m_currentFrame->operands.push_back(dataVar); +} + void caload(const InstructionInput& input) { const Variable index = input.thread->m_currentFrame->popOperand(); diff --git a/src/VM/Instructions/LoadInstructions.h b/src/VM/Instructions/LoadInstructions.h index efc8c02..0cc02b3 100644 --- a/src/VM/Instructions/LoadInstructions.h +++ b/src/VM/Instructions/LoadInstructions.h @@ -11,4 +11,5 @@ void lload_i(const InstructionInput& input); void fload_i(const InstructionInput& input); void iaload(const InstructionInput& input); void aaload(const InstructionInput& input); +void baload(const InstructionInput& input); void caload(const InstructionInput& input); diff --git a/src/VM/Instructions/ReferenceInstructions.cpp b/src/VM/Instructions/ReferenceInstructions.cpp index 8386808..9bedf4b 100644 --- a/src/VM/Instructions/ReferenceInstructions.cpp +++ b/src/VM/Instructions/ReferenceInstructions.cpp @@ -194,38 +194,47 @@ static void invokeVirtual(ClassInfo* classInfo, MethodInfo* methodInfo, VMThread } // Look for method based on the object - const Object* object = heap->getObject(ref.data); - targetClass = object->classInfo; - MethodInfo* foundMethod = targetClass->findMethodWithNameAndDescriptor(methodInfo->name.data(), - classInfo->constantPool->getString(methodInfo->descriptorIndex).data()); - if (foundMethod != nullptr) - { - targetMethod = foundMethod; - } else - { - - ClassInfo* currentClass = targetClass; - while (currentClass->superClass != 0) { - CPClassInfo* ci = currentClass->constantPool->getClassInfo(currentClass->superClass); - [[maybe_unused]] const std::string_view superClass = currentClass->constantPool->getString(ci->nameIndex); - currentClass = VM->getClass(superClass.data(), thread); - if (currentClass != nullptr) { - foundMethod = currentClass->findMethodWithNameAndDescriptor(methodInfo->name.data(), + const Reference* reference = heap->getReference(ref.data); + if (reference->type == OBJECT || reference->type == CLASSOBJECT) { + const Object* object = reference->getObject(); + targetClass = object->classInfo; + MethodInfo* foundMethod = targetClass->findMethodWithNameAndDescriptor(methodInfo->name.data(), classInfo->constantPool->getString(methodInfo->descriptorIndex).data()); - if (foundMethod != nullptr) { - targetClass = currentClass; - targetMethod = foundMethod; + if (foundMethod != nullptr) + { + targetMethod = foundMethod; + } else + { + + ClassInfo* currentClass = targetClass; + while (currentClass->superClass != 0) { + CPClassInfo* ci = currentClass->constantPool->getClassInfo(currentClass->superClass); + [[maybe_unused]] const std::string_view superClass = currentClass->constantPool->getString(ci->nameIndex); + currentClass = VM->getClass(superClass.data(), thread); + if (currentClass != nullptr) { + foundMethod = currentClass->findMethodWithNameAndDescriptor(methodInfo->name.data(), + classInfo->constantPool->getString(methodInfo->descriptorIndex).data()); + if (foundMethod != nullptr) { + targetClass = currentClass; + targetMethod = foundMethod; + break; + } + } else { break; } - } else { - break; } - } - if (foundMethod == nullptr) { - thread->internalError("Failed to get the correct method on the object.\n" - " Searching on superclass and generic search is not implemented yet."); + if (foundMethod == nullptr) { + thread->internalError("Failed to get the correct method on the object.\n" + " Searching on superclass and generic search is not implemented yet."); + } } + } else + { + // Execute java.lang.Object method on array + targetClass = classInfo; + targetMethod = methodInfo; + printf(""); } } @@ -260,11 +269,25 @@ void invokevirtual(const InstructionInput& input) const std::string_view methodName = topFrame->constantPool->getString(nameAndTypeInfo->nameIndex); const std::string_view methodDescriptor = topFrame->constantPool->getString(nameAndTypeInfo->descriptorIndex); const std::string_view className = topFrame->constantPool->getString(cpClassInfo->nameIndex); - ClassInfo* targetClassInfo = input.vm->getClass(className.data(), input.thread); + ClassInfo* targetClassInfo = nullptr; + if (className.starts_with("[")) + { + targetClassInfo = input.vm->getClass("java/lang/Object", input.thread); + + } else { + targetClassInfo = input.vm->getClass(className.data(), input.thread); + } + if (targetClassInfo == nullptr) + { + printf("Class not found"); + } MethodInfo* foundMethod = targetClassInfo->findMethodWithNameAndDescriptor(methodName.data(), methodDescriptor.data()); MethodInfo* targetMethod = nullptr; + + + // BEGIN BROL if (foundMethod != nullptr) { diff --git a/src/VM/Instructions/StoreInstructions.cpp b/src/VM/Instructions/StoreInstructions.cpp index 3af1555..b6db455 100644 --- a/src/VM/Instructions/StoreInstructions.cpp +++ b/src/VM/Instructions/StoreInstructions.cpp @@ -79,6 +79,17 @@ void aastore(const InstructionInput& input) arrData[index.data] = value.data; } +void bastore(const InstructionInput& input) +{ + Variable value = input.thread->m_currentFrame->popOperand(); + const Variable index = input.thread->m_currentFrame->popOperand(); + const Variable arrayref = input.thread->m_currentFrame->popOperand(); + + const Array* array = input.heap->getArray(arrayref.data); + i4* intArray = reinterpret_cast(array->data); + intArray[index.data] = *reinterpret_cast(&value.data); +} + void castore(const InstructionInput& input) { StackFrame* currentFrame = input.thread->m_currentFrame; diff --git a/src/VM/Instructions/StoreInstructions.h b/src/VM/Instructions/StoreInstructions.h index 53da23c..81cfeac 100644 --- a/src/VM/Instructions/StoreInstructions.h +++ b/src/VM/Instructions/StoreInstructions.h @@ -8,4 +8,5 @@ void istore_i(const InstructionInput& input); void astore_i(const InstructionInput& input); void iastore(const InstructionInput& input); void aastore(const InstructionInput& input); +void bastore(const InstructionInput& input); void castore(const InstructionInput& input); diff --git a/src/VM/VM.cpp b/src/VM/VM.cpp index 1c1301d..fd663f3 100644 --- a/src/VM/VM.cpp +++ b/src/VM/VM.cpp @@ -47,6 +47,8 @@ void VM::start(std::string_view commandLineName) getClass("java/lang/ThreadGroup", &m_mainThread); getClass("java/lang/reflect/Field", &m_mainThread); getClass("java/lang/reflect/AccessibleObject", &m_mainThread); + getClass("java/lang/reflect/Executable", &m_mainThread); + getClass("java/lang/reflect/Constructor", &m_mainThread); getClass("java/io/PrintStream", &m_mainThread); getClass("java/io/FilterOutputStream", &m_mainThread); getClass("java/io/OutputStream", &m_mainThread); @@ -150,6 +152,10 @@ std::vector VM::createVariableForDescriptor(std::string_view descripto } else if (descriptor[0] == 'F') { constexpr Variable variable{VariableType_FLOAT}; variables.push_back(variable); + } else if (descriptor[0] == 'C') + { + constexpr Variable variable{VariableType_CHAR}; + variables.push_back(variable); } else { @@ -171,7 +177,6 @@ u1 VM::getDescriptorVarCategory(std::string_view descriptor) noexcept void VM::initStaticFields(ClassInfo* class_info, [[maybe_unused]] VMThread* thread) { - // TODO: Do it for superclasses as well? u2 staticFieldsCount = 0; for (u2 currentField = 0; currentField < class_info->fieldsCount; ++currentField) { @@ -324,6 +329,10 @@ void VM::runStaticInitializer(ClassInfo* classInfo, VMThread* thread) ClassInfo* VM::getClass(std::string_view className, VMThread* thread) { + if (className.starts_with("[")) + { + return nullptr; + } ClassInfo* classInfo = m_heap.getClassByName(className); if (classInfo == nullptr) { Memory *memory = new Memory(MIB(1), MIB(30)); diff --git a/src/VM/VM.h b/src/VM/VM.h index 82e6b30..bc8b7aa 100644 --- a/src/VM/VM.h +++ b/src/VM/VM.h @@ -60,7 +60,7 @@ class VM { FieldInfo* findField(ClassInfo* classInfo, const char* name, const char* descriptor, VMThread* thread); private: void initSystemClass(ClassInfo* class_info, VMThread* vm_thread); - static constexpr std::array m_instructions{{ + static constexpr std::array m_instructions{{ // Constants {i_nop, 0, "nop", 0, nop}, {i_aconst_null, 0, "aconst_null", 0, aconst_null}, @@ -105,6 +105,7 @@ class VM { {i_aload_3, 0, "aload_3", 3, aload_i}, {i_iaload, 0, "iaload", 0, iaload}, {i_aaload, 0, "aaload", 0, aaload}, + {i_baload, 0, "baload", 0, baload}, {i_caload, 0, "caload", 0, caload}, // Stores {i_istore, 1, "istore", 0, istore}, @@ -119,6 +120,7 @@ class VM { {i_astore_3, 0, "astore_3", 3, astore_i}, {i_iastore, 0, "iastore", 0, iastore}, {i_aastore, 0, "aastore", 0, aastore}, + {i_bastore, 0, "bastore", 0, bastore}, {i_castore, 0, "castore", 0, castore}, // Stack {i_pop, 0, "pop", 0, pop},