Skip to content

Commit

Permalink
Make Universe and Interpreter static (#49)
Browse files Browse the repository at this point in the history
This is intended to simplify the code but also to avoid unnecessary
memory accesses and virtual dispatches.

It has some performance benefit:
median -4% (min. -23%, max. 25%)

https://rebench.dev/SOMpp/compare/64a86da76aaa57d8b794260bce9f8396e7ecc072..ede98d3b1d401e170e4ebe3ac6e50f31c4be2065
  • Loading branch information
smarr authored Aug 9, 2024
2 parents 64a86da + ede98d3 commit ed7f335
Show file tree
Hide file tree
Showing 50 changed files with 361 additions and 420 deletions.
25 changes: 11 additions & 14 deletions src/compiler/ClassGenerationContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -99,39 +99,36 @@ VMClass* ClassGenerationContext::Assemble() {
std::string ccname = string(name->GetStdString()) + " class";

// Load the super class
VMClass* superClass = GetUniverse()->LoadClass(superName);
VMClass* superClass = Universe::LoadClass(superName);

// Allocate the class of the resulting class
VMClass* resultClass = GetUniverse()->NewClass(load_ptr(metaClassClass));
VMClass* resultClass = Universe::NewClass(load_ptr(metaClassClass));

// Initialize the class of the resulting class
resultClass->SetInstanceFields(GetUniverse()->NewArrayList(classFields));
resultClass->SetInstanceInvokables(
GetUniverse()->NewArrayList(classMethods));
resultClass->SetInstanceFields(Universe::NewArrayList(classFields));
resultClass->SetInstanceInvokables(Universe::NewArrayList(classMethods));
resultClass->SetName(SymbolFor(ccname));

VMClass* superMClass = superClass->GetClass();
resultClass->SetSuperClass(superMClass);

// Allocate the resulting class
VMClass* result = GetUniverse()->NewClass(resultClass);
VMClass* result = Universe::NewClass(resultClass);

// Initialize the resulting class
result->SetInstanceFields(GetUniverse()->NewArrayList(instanceFields));
result->SetInstanceInvokables(GetUniverse()->NewArrayList(instanceMethods));
result->SetInstanceFields(Universe::NewArrayList(instanceFields));
result->SetInstanceInvokables(Universe::NewArrayList(instanceMethods));
result->SetName(name);
result->SetSuperClass(superClass);

return result;
}

void ClassGenerationContext::AssembleSystemClass(VMClass* systemClass) {
systemClass->SetInstanceInvokables(
GetUniverse()->NewArrayList(instanceMethods));
systemClass->SetInstanceFields(GetUniverse()->NewArrayList(instanceFields));
systemClass->SetInstanceInvokables(Universe::NewArrayList(instanceMethods));
systemClass->SetInstanceFields(Universe::NewArrayList(instanceFields));
// class-bound == class-instance-bound
VMClass* superMClass = systemClass->GetClass();
superMClass->SetInstanceInvokables(
GetUniverse()->NewArrayList(classMethods));
superMClass->SetInstanceFields(GetUniverse()->NewArrayList(classFields));
superMClass->SetInstanceInvokables(Universe::NewArrayList(classMethods));
superMClass->SetInstanceFields(Universe::NewArrayList(classFields));
}
4 changes: 2 additions & 2 deletions src/compiler/Disassembler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,7 @@ void Disassembler::dispatch(vm_oop_t o) {
DebugPrint("{System Class object}");
} else if (o == load_ptr(blockClass)) {
DebugPrint("{Block Class object}");
} else if (o == GetUniverse()->GetGlobal(SymbolFor("system"))) {
} else if (o == Universe::GetGlobal(SymbolFor("system"))) {
DebugPrint("{System}");
} else {
VMClass* c = CLASS_OF(o);
Expand Down Expand Up @@ -489,7 +489,7 @@ void Disassembler::DumpBytecode(VMFrame* frame, VMMethod* method, long bc_idx) {
case BC_PUSH_GLOBAL: {
VMSymbol* name =
static_cast<VMSymbol*>(method->GetConstant(bc_idx));
vm_oop_t o = GetUniverse()->GetGlobal(name);
vm_oop_t o = Universe::GetGlobal(name);
VMSymbol* cname;

const char* c_cname;
Expand Down
6 changes: 3 additions & 3 deletions src/compiler/MethodGenerationContext.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -70,9 +70,9 @@ VMInvokable* MethodGenerationContext::Assemble() {
// create a method instance with the given number of bytecodes and literals
size_t numLiterals = literals.size();
size_t numLocals = locals.size();
VMMethod* meth = GetUniverse()->NewMethod(
signature, bytecode.size(), numLiterals, numLocals, maxStackDepth,
lexicalScope, inlinedLoops);
VMMethod* meth =
Universe::NewMethod(signature, bytecode.size(), numLiterals, numLocals,
maxStackDepth, lexicalScope, inlinedLoops);

// copy literals into the method
for (size_t i = 0; i < numLiterals; i++) {
Expand Down
8 changes: 4 additions & 4 deletions src/compiler/Parser.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -247,7 +247,7 @@ void Parser::superclass(ClassGenerationContext& cgenc) {

// Load the super class, if it is not nil (break the dependency cycle)
if (superName != SymbolFor("nil")) {
VMClass* superClass = GetUniverse()->LoadClass(superName);
VMClass* superClass = Universe::LoadClass(superName);
cgenc.SetInstanceFieldsOfSuper(superClass->GetInstanceFields());
cgenc.SetClassFieldsOfSuper(
superClass->GetClass()->GetInstanceFields());
Expand All @@ -260,7 +260,7 @@ void Parser::superclass(ClassGenerationContext& cgenc) {
vector<StdString> fieldNamesOfClass{"class", "name", "instanceFields",
"instanceInvokables", "superClass"};
VMArray* fieldNames =
GetUniverse()->NewArrayOfSymbolsFromStrings(fieldNamesOfClass);
Universe::NewArrayOfSymbolsFromStrings(fieldNamesOfClass);
cgenc.SetClassFieldsOfSuper(fieldNames);
}
}
Expand Down Expand Up @@ -748,7 +748,7 @@ vm_oop_t Parser::literalDouble(bool negateValue) {
d = 0 - d;
}
expect(Double);
return GetUniverse()->NewDouble(d);
return Universe::NewDouble(d);
}

void Parser::literalSymbol(MethodGenerationContext& mgenc) {
Expand Down Expand Up @@ -801,7 +801,7 @@ void Parser::literalArray(MethodGenerationContext& mgenc) {
void Parser::literalString(MethodGenerationContext& mgenc) {
StdString s = _string();

VMString* str = GetUniverse()->NewString(s);
VMString* str = Universe::NewString(s);
EmitPUSHCONSTANT(mgenc, str);
}

Expand Down
64 changes: 33 additions & 31 deletions src/interpreter/Interpreter.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,9 +56,13 @@ const std::string Interpreter::doesNotUnderstand =
"doesNotUnderstand:arguments:";
const std::string Interpreter::escapedBlock = "escapedBlock:";

Interpreter::Interpreter() : frame(nullptr) {}
VMFrame* Interpreter::frame = nullptr;
VMMethod* Interpreter::method = nullptr;

Interpreter::~Interpreter() {}
// The following three variables are used to cache main parts of the
// current execution context
long Interpreter::bytecodeIndexGlobal;
uint8_t* Interpreter::currentBytecodes;

vm_oop_t Interpreter::StartAndPrintBytecodes() {
#define PROLOGUE(bc_count) \
Expand All @@ -81,24 +85,24 @@ vm_oop_t Interpreter::Start() {
}

VMFrame* Interpreter::PushNewFrame(VMMethod* method) {
SetFrame(GetUniverse()->NewFrame(GetFrame(), method));
SetFrame(Universe::NewFrame(GetFrame(), method));
return GetFrame();
}

void Interpreter::SetFrame(VMFrame* frame) {
if (this->frame != nullptr) {
this->frame->SetBytecodeIndex(bytecodeIndexGlobal);
void Interpreter::SetFrame(VMFrame* frm) {
if (frame != nullptr) {
frame->SetBytecodeIndex(bytecodeIndexGlobal);
}

this->frame = frame;
frame = frm;

// update cached values
method = frame->GetMethod();
bytecodeIndexGlobal = frame->GetBytecodeIndex();
method = frm->GetMethod();
bytecodeIndexGlobal = frm->GetBytecodeIndex();
currentBytecodes = method->GetBytecodes();
}

vm_oop_t Interpreter::GetSelf() const {
vm_oop_t Interpreter::GetSelf() {
VMFrame* context = GetFrame()->GetOuterContext();
return context->GetArgumentInCurrentContext(0);
}
Expand Down Expand Up @@ -135,19 +139,18 @@ void Interpreter::send(VMSymbol* signature, VMClass* receiverClass) {
if (invokable != nullptr) {
#ifdef LOG_RECEIVER_TYPES
std::string name = receiverClass->GetName()->GetStdString();
if (GetUniverse()->callStats.find(name) ==
GetUniverse()->callStats.end()) {
GetUniverse()->callStats[name] = {0, 0};
if (Universe::callStats.find(name) == Universe::callStats.end()) {
Universe::callStats[name] = {0, 0};
}
GetUniverse()->callStats[name].noCalls++;
Universe::callStats[name].noCalls++;
if (invokable->IsPrimitive()) {
GetUniverse()->callStats[name].noPrimitiveCalls++;
Universe::callStats[name].noPrimitiveCalls++;
}
#endif
// since an invokable is able to change/use the frame, we have to write
// cached values before, and read cached values after calling
GetFrame()->SetBytecodeIndex(bytecodeIndexGlobal);
invokable->Invoke(this, GetFrame());
invokable->Invoke(GetFrame());
bytecodeIndexGlobal = GetFrame()->GetBytecodeIndex();
} else {
triggerDoesNotUnderstand(signature);
Expand All @@ -160,7 +163,7 @@ void Interpreter::triggerDoesNotUnderstand(VMSymbol* signature) {
vm_oop_t receiver = GetFrame()->GetStackElement(numberOfArgs - 1);

VMArray* argumentsArray =
GetUniverse()->NewArray(numberOfArgs - 1); // without receiver
Universe::NewArray(numberOfArgs - 1); // without receiver

// the receiver should not go into the argumentsArray
// so, numberOfArgs - 2
Expand All @@ -182,7 +185,7 @@ void Interpreter::triggerDoesNotUnderstand(VMSymbol* signature) {
SetFrame(VMFrame::EmergencyFrameFrom(GetFrame(), additionalStackSlots));
}

AS_OBJ(receiver)->Send(this, doesNotUnderstand, arguments, 2);
AS_OBJ(receiver)->Send(doesNotUnderstand, arguments, 2);
}

void Interpreter::doDup() {
Expand Down Expand Up @@ -266,14 +269,13 @@ void Interpreter::doPushBlock(long bytecodeIndex) {

long numOfArgs = blockMethod->GetNumberOfArguments();

GetFrame()->Push(
GetUniverse()->NewBlock(blockMethod, GetFrame(), numOfArgs));
GetFrame()->Push(Universe::NewBlock(blockMethod, GetFrame(), numOfArgs));
}

void Interpreter::doPushGlobal(long bytecodeIndex) {
VMSymbol* globalName =
static_cast<VMSymbol*>(method->GetConstant(bytecodeIndex));
vm_oop_t global = GetUniverse()->GetGlobal(globalName);
vm_oop_t global = Universe::GetGlobal(globalName);

if (global != nullptr) {
GetFrame()->Push(global);
Expand All @@ -296,7 +298,7 @@ void Interpreter::SendUnknownGlobal(VMSymbol* globalName) {
SetFrame(VMFrame::EmergencyFrameFrom(GetFrame(), additionalStackSlots));
}

AS_OBJ(self)->Send(this, unknownGlobal, arguments, 1);
AS_OBJ(self)->Send(unknownGlobal, arguments, 1);
}

void Interpreter::doPop() {
Expand Down Expand Up @@ -358,7 +360,7 @@ void Interpreter::doSend(long bytecodeIndex) {
assert(IsValidObject(receiverClass));

#ifdef LOG_RECEIVER_TYPES
GetUniverse()->receiverTypes[receiverClass->GetName()->GetStdString()]++;
Universe::receiverTypes[receiverClass->GetName()->GetStdString()]++;
#endif

send(signature, receiverClass);
Expand All @@ -377,19 +379,19 @@ void Interpreter::doSuperSend(long bytecodeIndex) {
static_cast<VMInvokable*>(super->LookupInvokable(signature));

if (invokable != nullptr) {
invokable->Invoke(this, GetFrame());
invokable->Invoke(GetFrame());
} else {
long numOfArgs = Signature::GetNumberOfArguments(signature);
vm_oop_t receiver = GetFrame()->GetStackElement(numOfArgs - 1);
VMArray* argumentsArray = GetUniverse()->NewArray(numOfArgs);
VMArray* argumentsArray = Universe::NewArray(numOfArgs);

for (long i = numOfArgs - 1; i >= 0; --i) {
vm_oop_t o = GetFrame()->Pop();
argumentsArray->SetIndexableField(i, o);
}
vm_oop_t arguments[] = {signature, argumentsArray};

AS_OBJ(receiver)->Send(this, doesNotUnderstand, arguments, 2);
AS_OBJ(receiver)->Send(doesNotUnderstand, arguments, 2);
}
}

Expand Down Expand Up @@ -430,7 +432,7 @@ void Interpreter::doReturnNonLocal() {
VMFrame::EmergencyFrameFrom(GetFrame(), additionalStackSlots));
}

AS_OBJ(sender)->Send(this, escapedBlock, arguments, 1);
AS_OBJ(sender)->Send(escapedBlock, arguments, 1);
return;
}

Expand All @@ -449,7 +451,7 @@ void Interpreter::doInc() {
val = NEW_INT(result);
} else if (CLASS_OF(val) == load_ptr(doubleClass)) {
double d = static_cast<VMDouble*>(val)->GetEmbeddedDouble();
val = GetUniverse()->NewDouble(d + 1.0);
val = Universe::NewDouble(d + 1.0);
} else {
ErrorExit("unsupported");
}
Expand Down Expand Up @@ -489,14 +491,14 @@ void Interpreter::startGC() {
currentBytecodes = method->GetBytecodes();
}

VMMethod* Interpreter::GetMethod() const {
VMMethod* Interpreter::GetMethod() {
return GetFrame()->GetMethod();
}

uint8_t* Interpreter::GetBytecodes() const {
uint8_t* Interpreter::GetBytecodes() {
return method->GetBytecodes();
}

void Interpreter::disassembleMethod() const {
void Interpreter::disassembleMethod() {
Disassembler::DumpBytecode(GetFrame(), GetMethod(), bytecodeIndexGlobal);
}
Loading

0 comments on commit ed7f335

Please sign in to comment.