Skip to content

Commit

Permalink
Add more instructions and fix control flow with method calls
Browse files Browse the repository at this point in the history
  • Loading branch information
fernandezseb committed Dec 12, 2023
1 parent 862afe5 commit aa876ee
Show file tree
Hide file tree
Showing 3 changed files with 100 additions and 6 deletions.
13 changes: 13 additions & 0 deletions src/Data/Class.h
Original file line number Diff line number Diff line change
Expand Up @@ -84,6 +84,7 @@ class ClassInfo {
return ((accessFlags & ACC_PUBLIC) != 0);
}

// TODO: Remove
MethodInfo* findMethodWithName(const char* name) const
{
for (uint16_t currentMethod = 0; currentMethod < methodCount; ++currentMethod) {
Expand All @@ -95,6 +96,18 @@ class ClassInfo {
return nullptr;
}

MethodInfo* findMethodWithNameAndDescriptor(const char* name, const char* descriptor) const
{
for (uint16_t currentMethod = 0; currentMethod < methodCount; ++currentMethod) {
if (strcmp(methods[currentMethod]->name, name) == 0
&& strcmp(constantPool->getString(methods[currentMethod]->descriptorIndex), descriptor) == 0)
{
return methods[currentMethod];
}
}
return nullptr;
}

[[nodiscard]] char* getName() const
{
CPClassInfo* classInfo = constantPool->getClassInfo(thisClass);
Expand Down
90 changes: 84 additions & 6 deletions src/VM/VM.cpp
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
#include "VM.h"

#include <stack>
#include <variant>

#include "Configuration.h"
Expand Down Expand Up @@ -265,6 +266,13 @@ void VM::executeLoop()
topFrame->operands.push_back(variable);
break;
}
case 0x2a: // aload_0
{
// TODO: Check if it is OK type and such
Variable var = topFrame->localVariables[0];
topFrame->operands.push_back(var);
break;
}
case 0xb3: // putstatic
{
uint8_t indexByte1 = code[thread.pc++];
Expand All @@ -282,7 +290,14 @@ void VM::executeLoop()
case 0xb1: // return
{
thread.pc = topFrame->previousPc;
thread.currentClass = topFrame->previousClass;
thread.currentMethod = topFrame->previousMethod;
thread.stack.frames.pop_back();
if (thread.stack.frames.size() > 0)
{
StackFrame* previousStackFrame = &thread.stack.frames[thread.stack.frames.size()-1];
thread.currentFrame = previousStackFrame;
}
break;
}
case 0x59: // dup
Expand All @@ -292,6 +307,66 @@ void VM::executeLoop()
copy.type = top.type;
copy.data = top.data;
topFrame->operands.push_back(copy);
break;
}
case 0xb7: // Invoke special
{
uint8_t indexByte1 = code[thread.pc++];
uint8_t indexByte2 = code[thread.pc++];
uint16_t index = (indexByte1 << 8) | indexByte2;
CPMethodRef* methodRef = (CPMethodRef*) topFrame->constantPool->constants[index-1];
CPClassInfo* cpClassInfo = topFrame->constantPool->getClassInfo(methodRef->classIndex);
CPNameAndTypeInfo* nameAndTypeInfo = (CPNameAndTypeInfo*) topFrame->constantPool->constants[methodRef->nameAndTypeIndex-1];
const char* methodName = topFrame->constantPool->getString(nameAndTypeInfo->nameIndex);
const char* methodDescriptor = topFrame->constantPool->getString(nameAndTypeInfo->descriptorIndex);
const char* className = topFrame->constantPool->getString(cpClassInfo->nameIndex);
ClassInfo* targetClassInfo = getClass(className);
MethodInfo* methodInfo = targetClassInfo->findMethodWithNameAndDescriptor(methodName, methodDescriptor);
// TODO: Implement argument passing (including subclass argument)
// TODO: Check correct parsing of descriptors with subclasses

if (strcmp(methodName, "<init>") ==0)
{
// TODO: Check argument types

StackFrame* previousFrame = topFrame;
StackFrame stackFrame;
stackFrame.localVariables.reserve(methodInfo->code->maxLocals);
stackFrame.operands.reserve(methodInfo->code->maxStack);
stackFrame.constantPool = targetClassInfo->constantPool;
stackFrame.previousPc = thread.pc;
stackFrame.previousClass = thread.currentClass;
stackFrame.previousMethod = thread.currentMethod;

thread.pc = 0;
thread.currentClass = targetClassInfo;
thread.currentMethod = methodInfo;

thread.stack.frames.push_back(stackFrame);
thread.currentFrame = &thread.stack.frames[thread.stack.frames.size()-1];

for (int i = 0; i <= methodInfo->argsCount; ++i)
{
Variable var;
var.data = 0;
var.type = VariableType_UNDEFINED;
thread.currentFrame->localVariables.push_back(var);
}

for (int i = methodInfo->argsCount; i > 0; --i) {
thread.currentFrame->localVariables[i] = previousFrame->operands.back();
previousFrame->operands.pop_back();
}

thread.currentFrame->localVariables[0] = previousFrame->operands.back();
previousFrame->operands.pop_back();
printf(">Created new stack frame for constructor call on: %s\n", className);
} else
{
fprintf(stderr, "Error: Invokespecial not implemented for other cases than constructors\n");
Platform::exitProgram(-30);
}

break;
}
case 0xb8: // invoke static
Expand Down Expand Up @@ -386,18 +461,21 @@ void VM::runStaticInitializer(ClassInfo* classInfo)
return;
}

thread.pc = 0;
thread.currentClass = classInfo;
thread.currentMethod = entryPoint;

StackFrame stackFrame;
stackFrame.localVariables.reserve(entryPoint->code->maxLocals);
stackFrame.operands.reserve(entryPoint->code->maxStack);
stackFrame.constantPool = classInfo->constantPool;
stackFrame.previousPc = 0;
stackFrame.previousPc = thread.pc;
stackFrame.previousClass = thread.currentClass;
stackFrame.previousMethod = thread.currentMethod;


thread.pc = 0;
thread.currentClass = classInfo;
thread.currentMethod = entryPoint;

thread.stack.frames.push_back(stackFrame);
thread.currentFrame = &thread.stack.frames[0];
thread.currentFrame = &thread.stack.frames[thread.stack.frames.size()-1];

printf("Executing static initializers...\n");
executeLoop();
Expand Down
3 changes: 3 additions & 0 deletions src/VM/VM.h
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,9 @@ struct StackFrame {
// used to restore the state of the invoker,
// pc of the invoker
u4 previousPc;

ClassInfo* previousClass;
MethodInfo* previousMethod;
};

class JavaStack {
Expand Down

0 comments on commit aa876ee

Please sign in to comment.