Skip to content

Commit

Permalink
Implement java.lang.Class.getName0 native method and private native m…
Browse files Browse the repository at this point in the history
…ethod execution
  • Loading branch information
fernandezseb committed Jan 30, 2024
1 parent 631b096 commit b7ef5f2
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 18 deletions.
56 changes: 45 additions & 11 deletions src/Library/java/lang/Class.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,39 +15,65 @@

#include "Class.h"

JCALL void lib_java_lang_Class_registerNatives(NATIVE_ARGS)
[[nodiscard]] static const Object* getThisObjectReference(
VMThread* thread,
const JavaHeap* heap,
const VM* VM)
{
registerNative("java/lang/Class/getPrimitiveClass", "(Ljava/lang/String;)Ljava/lang/Class;", lib_java_lang_Class_getPrimitiveClass);
registerNative("java/lang/Class/desiredAssertionStatus0", "(Ljava/lang/Class;)Z", lib_java_lang_Class_desiredAssertionStatus0);
const StackFrame* currentFrame = thread->m_currentFrame;
const Variable var = currentFrame->localVariables[0];
VM->checkType(var, VariableType_REFERENCE, thread);
return heap->getObject(var.data);
}

JCALL void lib_java_lang_Class_getPrimitiveClass(NATIVE_ARGS)
[[nodiscard]] static const ClassObject* getThisClassObjectReference(
VMThread* thread,
const JavaHeap* heap,
const VM* VM)
{
const StackFrame* currentFrame = thread->m_currentFrame;
const Variable var = currentFrame->localVariables[0];
VM->checkType(var, VariableType_REFERENCE, thread);
const Object* strObject = heap->getObject(var.data);
u4 arrayRefId = strObject->fields[0].data->data;
return heap->getClassObject(var.data);
}

JCALL void lib_java_lang_Class_registerNatives(NATIVE_ARGS)
{
registerNative("java/lang/Class/getPrimitiveClass", "(Ljava/lang/String;)Ljava/lang/Class;",
lib_java_lang_Class_getPrimitiveClass);
registerNative("java/lang/Class/desiredAssertionStatus0", "(Ljava/lang/Class;)Z",
lib_java_lang_Class_desiredAssertionStatus0);
registerNative("java/lang/Class/getName0", "()Ljava/lang/String;", lib_java_lang_Class_getName0);
}

JCALL void lib_java_lang_Class_getPrimitiveClass(NATIVE_ARGS)
{
const Object* strObject = getThisObjectReference(thread, heap, VM);
const u4 arrayRefId = strObject->fields[0].data->data;
const Array* array = heap->getArray(arrayRefId);
auto typeString = std::string_view{reinterpret_cast<char*>(array->data), array->length};
const auto typeString = std::string_view{reinterpret_cast<char*>(array->data), array->length};
u4 classRef = 0;
if (typeString == "float")
{
ClassInfo* classInfo = VM->getClass("java/lang/Float", thread);
classRef = heap->createClassObject(classInfo, VM, "java/lang/Float");
} else if (typeString == "int")
}
else if (typeString == "int")
{
ClassInfo* classInfo = VM->getClass("java/lang/Integer", thread);
classRef = heap->createClassObject(classInfo, VM, "java/lang/Integer");
} else if (typeString == "double")
}
else if (typeString == "double")
{
ClassInfo* classInfo = VM->getClass("java/lang/Double", thread);
classRef = heap->createClassObject(classInfo, VM, "java/lang/Double");
} else if (typeString == "char")
}
else if (typeString == "char")
{
ClassInfo* classInfo = VM->getClass("java/lang/Character", thread);
classRef = heap->createClassObject(classInfo, VM, "java/lang/Character");
} else if (typeString == "boolean")
}
else if (typeString == "boolean")
{
ClassInfo* classInfo = VM->getClass("java/lang/Boolean", thread);
classRef = heap->createClassObject(classInfo, VM, "java/lang/Boolean");
Expand All @@ -63,3 +89,11 @@ JCALL void lib_java_lang_Class_desiredAssertionStatus0(NATIVE_ARGS)
{
thread->returnVar(Variable{VariableType_INT, 0});
}

JCALL void lib_java_lang_Class_getName0(NATIVE_ARGS)
{
const ClassObject* classObject = getThisClassObjectReference(thread, heap, VM);
const std::string_view name = classObject->name;
const u4 stringObject = heap->createString(name.data(), VM);
thread->returnVar(Variable{VariableType_REFERENCE, stringObject});
}
3 changes: 2 additions & 1 deletion src/Library/java/lang/Class.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,4 +4,5 @@

JCALL void lib_java_lang_Class_registerNatives(NATIVE_ARGS);
JCALL void lib_java_lang_Class_getPrimitiveClass(NATIVE_ARGS);
JCALL void lib_java_lang_Class_desiredAssertionStatus0(NATIVE_ARGS);
JCALL void lib_java_lang_Class_desiredAssertionStatus0(NATIVE_ARGS);
JCALL void lib_java_lang_Class_getName0(NATIVE_ARGS);
17 changes: 12 additions & 5 deletions src/VM/Instructions/ReferenceInstructions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -261,20 +261,27 @@ void invokevirtual(INSTRUCTION_ARGS)
void invokespecial(INSTRUCTION_ARGS)
{
StackFrame* topFrame = thread->m_currentFrame;
uint16_t index = readShort(thread);
CPMethodRef* methodRef = topFrame->constantPool->getMethodRef(index);
CPClassInfo* cpClassInfo = topFrame->constantPool->getClassInfo(methodRef->classIndex);
CPNameAndTypeInfo* nameAndTypeInfo = topFrame->constantPool->getNameAndTypeInfo(methodRef->nameAndTypeIndex);
const uint16_t index = readShort(thread);
const CPMethodRef* methodRef = topFrame->constantPool->getMethodRef(index);
const CPClassInfo* cpClassInfo = topFrame->constantPool->getClassInfo(methodRef->classIndex);
const CPNameAndTypeInfo* nameAndTypeInfo = topFrame->constantPool->getNameAndTypeInfo(methodRef->nameAndTypeIndex);
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 = VM->getClass(className.data(), thread);
MethodInfo* methodInfo = targetClassInfo->findMethodWithNameAndDescriptor(methodName.data(), methodDescriptor.data());
const MethodInfo* methodInfo = targetClassInfo->findMethodWithNameAndDescriptor(methodName.data(), methodDescriptor.data());
// TODO: Implement argument passing (including subclass argument)
// TODO: Check correct parsing of descriptors with subclasses

// TODO: Check argument types
thread->pushStackFrameSpecial(targetClassInfo, methodInfo, topFrame, heap);

if (methodInfo->isNative())
{
VM->executeNativeMethod(targetClassInfo, methodInfo, heap, thread);
thread->popFrame();
}

printf("> Created new stack frame for method call %s on: %s\n", thread->m_currentFrame->methodName.data(), thread->m_currentFrame->className.data());
}

Expand Down
7 changes: 6 additions & 1 deletion src/VM/VMThread.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,12 @@ void VMThread::pushStackFrameSpecial(ClassInfo* classInfo, const MethodInfo* met
}
}

pushStackFrameWithoutParams(classInfo, methodInfo);
if (methodInfo->isNative()) {
pushNativeStackFrame(classInfo, methodInfo, arguments.size());
} else {
pushStackFrameWithoutParams(classInfo, methodInfo);
}

if (!arguments.empty())
{
for (int i = 0; i < arguments.size(); ++i)
Expand Down

0 comments on commit b7ef5f2

Please sign in to comment.