Skip to content

Commit

Permalink
Add more class library features
Browse files Browse the repository at this point in the history
  • Loading branch information
fernandezseb committed Mar 24, 2024
1 parent c101e90 commit 7137d6d
Show file tree
Hide file tree
Showing 18 changed files with 261 additions and 41 deletions.
2 changes: 2 additions & 0 deletions src/Library/Builtin.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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()
Expand Down Expand Up @@ -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);
}
2 changes: 2 additions & 0 deletions src/Library/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
80 changes: 76 additions & 4 deletions src/Library/java/lang/Class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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
Expand All @@ -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});
}

Expand Down Expand Up @@ -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<u4*>(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("");
}
5 changes: 4 additions & 1 deletion src/Library/java/lang/Class.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
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);
17 changes: 17 additions & 0 deletions src/Library/java/lang/Object.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand All @@ -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");
}
}
3 changes: 2 additions & 1 deletion src/Library/java/lang/Object.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
JCALL void lib_java_lang_Object_getClass(const NativeArgs& args);
JCALL void lib_java_lang_Object_clone(const NativeArgs& args);
10 changes: 10 additions & 0 deletions src/Library/sun/misc/Unsafe.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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<u8>(args.thread->m_currentFrame->localVariables[1].data) << 32) | static_cast<u8>(args.thread->m_currentFrame->localVariables[2].data));
const u8 address = reinterpret_cast<const u8> (malloc(size));
const auto parts = reinterpret_cast<const u4*>(&address);
args.thread->returnVar(Variable{VariableType_LONG, parts[1]},
Variable{VariableType_LONG, parts[0]});
}
3 changes: 2 additions & 1 deletion src/Library/sun/misc/Unsafe.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
JCALL void lib_sun_misc_Unsafe_getIntVolatile(const NativeArgs& args);
JCALL void lib_sun_misc_Unsafe_allocateMemory(const NativeArgs& args);
50 changes: 50 additions & 0 deletions src/Library/sun/reflect/NativeConstructorAccessorImpl.cpp
Original file line number Diff line number Diff line change
@@ -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 <https://www.gnu.org/licenses/>.
*/

#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("");
}
5 changes: 5 additions & 0 deletions src/Library/sun/reflect/NativeConstructorAccessorImpl.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
#pragma once

#include "Library/NativeDefs.h"

JCALL void lib_sun_reflect_NativeConstructorAccessorImpl_newInstance0(const NativeArgs& args);
6 changes: 1 addition & 5 deletions src/VM/Instructions/ConstantInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -112,11 +112,7 @@ void loadConstant(VMThread* thread, const u4 index, JavaHeap* heap, VM* VM)
const auto* classInfo = static_cast<const CPClassInfo*>(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);
Expand Down
14 changes: 14 additions & 0 deletions src/VM/Instructions/LoadInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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<u4>(data)};
input.thread->m_currentFrame->operands.push_back(dataVar);
}

void caload(const InstructionInput& input)
{
const Variable index = input.thread->m_currentFrame->popOperand();
Expand Down
1 change: 1 addition & 0 deletions src/VM/Instructions/LoadInstructions.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Loading

0 comments on commit 7137d6d

Please sign in to comment.