diff --git a/compiler.cc b/compiler.cc index 9fb4c20..fdefb35 100644 --- a/compiler.cc +++ b/compiler.cc @@ -122,7 +122,7 @@ ClosureInvoke Compiler::Context::compile() FPM.run(*F); MPM.run(*M); - // If you want to see the LLVM IR before optimisation, uncomment the + // If you want to see the LLVM IR after optimisation, uncomment the // following line: //M->dump(); diff --git a/compiler.hh b/compiler.hh index 65b2eee..68a3869 100644 --- a/compiler.hh +++ b/compiler.hh @@ -81,4 +81,4 @@ namespace Compiler */ MysoreScript::ClosureInvoke compile(); }; -}; +} diff --git a/interpreter.cc b/interpreter.cc index e329839..1c5afd0 100644 --- a/interpreter.cc +++ b/interpreter.cc @@ -22,250 +22,96 @@ Interpreter::Context *currentContext; using MysoreScript::Closure; /** - * 0-argument trampoline for jumping back into the interpreter when a closure + * Trampolines for jumping back into the interpreter when a closure * that has not yet been compiled is executed. */ -Obj closureTrampoline0(Closure *C) +template +Obj closureTrampolineVar(Closure *C, Cls... objs) { - return C->AST->interpretClosure(*currentContext, C, nullptr); -} -/** - * 1-argument trampoline for jumping back into the interpreter when a closure - * that has not yet been compiled is executed. - */ -Obj closureTrampoline1(Closure *C, Obj o0) -{ - Obj args[] = { o0 }; - return C->AST->interpretClosure(*currentContext, C, args); -} -/** - * 2-argument trampoline for jumping back into the interpreter when a closure - * that has not yet been compiled is executed. - */ -Obj closureTrampoline2(Closure *C, Obj o0, Obj o1) -{ - Obj args[] = { o0, o1 }; - return C->AST->interpretClosure(*currentContext, C, args); -} -/** - * 3-argument trampoline for jumping back into the interpreter when a closure - * that has not yet been compiled is executed. - */ -Obj closureTrampoline3(Closure *C, Obj o0, Obj o1, Obj o2) -{ - Obj args[] = { o0, o1, o2 }; - return C->AST->interpretClosure(*currentContext, C, args); -} -/** - * 4-argument trampoline for jumping back into the interpreter when a closure - * that has not yet been compiled is executed. - */ -Obj closureTrampoline4(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3) -{ - Obj args[] = { o0, o1, o2, o3 }; - return C->AST->interpretClosure(*currentContext, C, args); -} -/** - * 5-argument trampoline for jumping back into the interpreter when a closure - * that has not yet been compiled is executed. - */ -Obj closureTrampoline5(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4) -{ - Obj args[] = { o0, o1, o2, o3, o4 }; - return C->AST->interpretClosure(*currentContext, C, args); -} -/** - * 6-argument trampoline for jumping back into the interpreter when a closure - * that has not yet been compiled is executed. - */ -Obj closureTrampoline6(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, - Obj o5) -{ - Obj args[] = { o0, o1, o2, o3, o4, o5 }; - return C->AST->interpretClosure(*currentContext, C, args); -} -/** - * 7-argument trampoline for jumping back into the interpreter when a closure - * that has not yet been compiled is executed. - */ -Obj closureTrampoline7(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, - Obj o5, Obj o6) -{ - Obj args[] = { o0, o1, o2, o3, o4, o5, o6 }; - return C->AST->interpretClosure(*currentContext, C, args); -} -/** - * 8-argument trampoline for jumping back into the interpreter when a closure - * that has not yet been compiled is executed. - */ -Obj closureTrampoline8(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, - Obj o5, Obj o6, Obj o7) -{ - Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7 }; - return C->AST->interpretClosure(*currentContext, C, args); -} -/** - * 9-argument trampoline for jumping back into the interpreter when a closure - * that has not yet been compiled is executed. - */ -Obj closureTrampoline9(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, - Obj o5, Obj o6, Obj o7, Obj o8) -{ - Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7, o8 }; - return C->AST->interpretClosure(*currentContext, C, args); -} -/** - * 10-argument trampoline for jumping back into the interpreter when a closure - * that has not yet been compiled is executed. - */ -Obj closureTrampoline10(Closure *C, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, - Obj o5, Obj o6, Obj o7, Obj o8, Obj o9) -{ - Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7, o8, o9 }; + Obj args[] = { objs... }; return C->AST->interpretClosure(*currentContext, C, args); } -/** - * 0-argument trampoline for jumping back into the interpreter when a method - * that has not yet been compiled is executed. - */ -Obj methodTrampoline0(Obj self, Selector cmd) -{ - Class *cls = isInteger(self) ? &SmallIntClass : self->isa; - Method *mth = methodForSelector(cls, cmd); - return mth->AST->interpretMethod(*currentContext, mth, self, cmd, nullptr); -} -/** - * 1-argument trampoline for jumping back into the interpreter when a method - * that has not yet been compiled is executed. - */ -Obj methodTrampoline1(Obj self, Selector cmd, Obj o0) +template <> +Obj closureTrampolineVar(Closure *C) { - Obj args[] = { o0 }; - Class *cls = isInteger(self) ? &SmallIntClass : self->isa; - Method *mth = methodForSelector(cls, cmd); - return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args); -} -/** - * 2-argument trampoline for jumping back into the interpreter when a method - * that has not yet been compiled is executed. - */ -Obj methodTrampoline2(Obj self, Selector cmd, Obj o0, Obj o1) -{ - Obj args[] = { o0, o1 }; - Class *cls = isInteger(self) ? &SmallIntClass : self->isa; - Method *mth = methodForSelector(cls, cmd); - return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args); -} -/** - * 3-argument trampoline for jumping back into the interpreter when a method - * that has not yet been compiled is executed. - */ -Obj methodTrampoline3(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2) -{ - Obj args[] = { o0, o1, o2 }; - Class *cls = isInteger(self) ? &SmallIntClass : self->isa; - Method *mth = methodForSelector(cls, cmd); - return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args); -} -/** - * 4-argument trampoline for jumping back into the interpreter when a method - * that has not yet been compiled is executed. - */ -Obj methodTrampoline4(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3) -{ - Obj args[] = { o0, o1, o2, o3 }; - Class *cls = isInteger(self) ? &SmallIntClass : self->isa; - Method *mth = methodForSelector(cls, cmd); - return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args); + return C->AST->interpretClosure(*currentContext, C, nullptr); } + /** - * 5-argument trampoline for jumping back into the interpreter when a method + * Trampolines for jumping back into the interpreter when a method * that has not yet been compiled is executed. */ -Obj methodTrampoline5(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, - Obj o4) +template +Obj methodTrampolineVar(Obj self, Selector cmd, Cls... objs) { - Obj args[] = { o0, o1, o2, o3, o4 }; + Obj args[] = { objs... }; Class *cls = isInteger(self) ? &SmallIntClass : self->isa; Method *mth = methodForSelector(cls, cmd); return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args); } -/** - * 6-argument trampoline for jumping back into the interpreter when a method - * that has not yet been compiled is executed. - */ -Obj methodTrampoline6(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, - Obj o4, Obj o5) + +template <> +Obj methodTrampolineVar(Obj self, Selector cmd) { - Obj args[] = { o0, o1, o2, o3, o4, o5 }; Class *cls = isInteger(self) ? &SmallIntClass : self->isa; Method *mth = methodForSelector(cls, cmd); - return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args); + return mth->AST->interpretMethod(*currentContext, mth, self, cmd, nullptr); } -/** - * 7-argument trampoline for jumping back into the interpreter when a method - * that has not yet been compiled is executed. - */ -Obj methodTrampoline7(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, - Obj o4, Obj o5, Obj o6) + +template +struct seq { }; + +template +struct gens : gens { }; + +template +struct gens<0, S...> { + typedef seq type; +}; + + +template +ClosureInvoke getClosureTrampolineNImpl(seq) { - Obj args[] = { o0, o1, o2, o3, o4, o5, o6 }; - Class *cls = isInteger(self) ? &SmallIntClass : self->isa; - Method *mth = methodForSelector(cls, cmd); - return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args); + static auto unused = [](size_t v) { return v; }; + return reinterpret_cast(closureTrampolineVar); } -/** - * 8-argument trampoline for jumping back into the interpreter when a method - * that has not yet been compiled is executed. - */ -Obj methodTrampoline8(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, Obj o4, - Obj o5, Obj o6, Obj o7) + +template +ClosureInvoke getClosureTrampolineN() { - Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7 }; - Class *cls = isInteger(self) ? &SmallIntClass : self->isa; - Method *mth = methodForSelector(cls, cmd); - return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args); + return getClosureTrampolineNImpl(typename gens::type{}); } -/** - * 9-argument trampoline for jumping back into the interpreter when a method - * that has not yet been compiled is executed. - */ -Obj methodTrampoline9(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, - Obj o4, Obj o5, Obj o6, Obj o7, Obj o8) + +template +CompiledMethod getMethodTrampolineNImpl(seq) { - Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7, o8 }; - Class *cls = isInteger(self) ? &SmallIntClass : self->isa; - Method *mth = methodForSelector(cls, cmd); - return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args); + static auto unused = [](size_t v) { return v; }; + return reinterpret_cast(methodTrampolineVar); } -/** - * 10-argument trampoline for jumping back into the interpreter when a method - * that has not yet been compiled is executed. - */ -Obj methodTrampoline10(Obj self, Selector cmd, Obj o0, Obj o1, Obj o2, Obj o3, - Obj o4, Obj o5, Obj o6, Obj o7, Obj o8, Obj o9) + +template +CompiledMethod getMethodTrampolineN() { - Obj args[] = { o0, o1, o2, o3, o4, o5, o6, o7, o8, o9 }; - Class *cls = isInteger(self) ? &SmallIntClass : self->isa; - Method *mth = methodForSelector(cls, cmd); - return mth->AST->interpretMethod(*currentContext, mth, self, cmd, args); + return getMethodTrampolineNImpl(typename gens::type{}); } + /** * Array of trampolines, indexed by number or arguments. */ CompiledMethod methodTrampolines[] = { - reinterpret_cast(methodTrampoline0), - reinterpret_cast(methodTrampoline1), - reinterpret_cast(methodTrampoline2), - reinterpret_cast(methodTrampoline3), - reinterpret_cast(methodTrampoline4), - reinterpret_cast(methodTrampoline5), - reinterpret_cast(methodTrampoline6), - reinterpret_cast(methodTrampoline7), - reinterpret_cast(methodTrampoline8), - reinterpret_cast(methodTrampoline9), - reinterpret_cast(methodTrampoline10) + getMethodTrampolineN<0>(), + getMethodTrampolineN<1>(), + getMethodTrampolineN<2>(), + getMethodTrampolineN<3>(), + getMethodTrampolineN<4>(), + getMethodTrampolineN<5>(), + getMethodTrampolineN<6>(), + getMethodTrampolineN<7>(), + getMethodTrampolineN<8>(), + getMethodTrampolineN<9>(), + getMethodTrampolineN<10>() }; } // end anonymous namespace @@ -275,18 +121,19 @@ namespace Interpreter * Array of trampolines, indexed by number or arguments. */ ClosureInvoke closureTrampolines[] = { - reinterpret_cast(closureTrampoline0), - reinterpret_cast(closureTrampoline1), - reinterpret_cast(closureTrampoline2), - reinterpret_cast(closureTrampoline3), - reinterpret_cast(closureTrampoline4), - reinterpret_cast(closureTrampoline5), - reinterpret_cast(closureTrampoline6), - reinterpret_cast(closureTrampoline7), - reinterpret_cast(closureTrampoline8), - reinterpret_cast(closureTrampoline9), - reinterpret_cast(closureTrampoline10) + getClosureTrampolineN<0>(), + getClosureTrampolineN<1>(), + getClosureTrampolineN<2>(), + getClosureTrampolineN<3>(), + getClosureTrampolineN<4>(), + getClosureTrampolineN<5>(), + getClosureTrampolineN<6>(), + getClosureTrampolineN<7>(), + getClosureTrampolineN<8>(), + getClosureTrampolineN<9>(), + getClosureTrampolineN<10>() }; + void Value::set(Obj o) { if (needsGC(object) && !needsGC(o)) diff --git a/interpreter.hh b/interpreter.hh index db7037f..f47b6ee 100644 --- a/interpreter.hh +++ b/interpreter.hh @@ -157,4 +157,4 @@ namespace Interpreter * Array of trampolines, indexed by number or arguments. */ extern MysoreScript::ClosureInvoke closureTrampolines[]; -}; +} diff --git a/main.cc b/main.cc index 0767810..3a27978 100644 --- a/main.cc +++ b/main.cc @@ -51,7 +51,7 @@ static void logTimeSince(clock_t c1, const char *msg) clock_t c2 = clock(); struct rusage r; getrusage(RUSAGE_SELF, &r); - auto oldLocale = std::cerr.imbue(std::locale("en_GB.UTF-8")); + auto oldLocale = std::cerr.imbue(std::locale("C")); std::cerr << msg << " took " << (static_cast(c2) - static_cast(c1)) / static_cast(CLOCKS_PER_SEC) << " seconds. Peak used " << r.ru_maxrss/1024 << "KB." << std::endl; @@ -205,7 +205,7 @@ int main(int argc, char **argv) // Print some memory usage stats, if requested. if (memstats) { - std::cerr.imbue(std::locale("en_GB.UTF-8")); + std::cerr.imbue(std::locale("C")); std::cerr << "Allocated a total of " << GC_get_total_bytes() << " bytes during execution." << std::endl; std::cerr << "GC heap size: " << GC_get_heap_size() << " bytes."