Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion compiler.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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();

Expand Down
2 changes: 1 addition & 1 deletion compiler.hh
Original file line number Diff line number Diff line change
Expand Up @@ -81,4 +81,4 @@ namespace Compiler
*/
MysoreScript::ClosureInvoke compile();
};
};
}
293 changes: 70 additions & 223 deletions interpreter.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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 <class... Cls>
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 <class... Cls>
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<size_t ...>
struct seq { };

template<size_t N, size_t ...S>
struct gens : gens<N-1, N-1, S...> { };

template<size_t ...S>
struct gens<0, S...> {
typedef seq<S...> type;
};


template <size_t ...I>
ClosureInvoke getClosureTrampolineNImpl(seq<I...>)
{
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<ClosureInvoke>(closureTrampolineVar<decltype((unused(I),Obj{}))...>);
}
/**
* 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 <size_t N>
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<N>::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 <size_t ...I>
CompiledMethod getMethodTrampolineNImpl(seq<I...>)
{
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<CompiledMethod>(methodTrampolineVar<decltype((unused(I),Obj{}))...>);
}
/**
* 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 <size_t N>
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<N>::type{});
}

/**
* Array of trampolines, indexed by number or arguments.
*/
CompiledMethod methodTrampolines[] = {
reinterpret_cast<CompiledMethod>(methodTrampoline0),
reinterpret_cast<CompiledMethod>(methodTrampoline1),
reinterpret_cast<CompiledMethod>(methodTrampoline2),
reinterpret_cast<CompiledMethod>(methodTrampoline3),
reinterpret_cast<CompiledMethod>(methodTrampoline4),
reinterpret_cast<CompiledMethod>(methodTrampoline5),
reinterpret_cast<CompiledMethod>(methodTrampoline6),
reinterpret_cast<CompiledMethod>(methodTrampoline7),
reinterpret_cast<CompiledMethod>(methodTrampoline8),
reinterpret_cast<CompiledMethod>(methodTrampoline9),
reinterpret_cast<CompiledMethod>(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

Expand All @@ -275,18 +121,19 @@ namespace Interpreter
* Array of trampolines, indexed by number or arguments.
*/
ClosureInvoke closureTrampolines[] = {
reinterpret_cast<ClosureInvoke>(closureTrampoline0),
reinterpret_cast<ClosureInvoke>(closureTrampoline1),
reinterpret_cast<ClosureInvoke>(closureTrampoline2),
reinterpret_cast<ClosureInvoke>(closureTrampoline3),
reinterpret_cast<ClosureInvoke>(closureTrampoline4),
reinterpret_cast<ClosureInvoke>(closureTrampoline5),
reinterpret_cast<ClosureInvoke>(closureTrampoline6),
reinterpret_cast<ClosureInvoke>(closureTrampoline7),
reinterpret_cast<ClosureInvoke>(closureTrampoline8),
reinterpret_cast<ClosureInvoke>(closureTrampoline9),
reinterpret_cast<ClosureInvoke>(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))
Expand Down
2 changes: 1 addition & 1 deletion interpreter.hh
Original file line number Diff line number Diff line change
Expand Up @@ -157,4 +157,4 @@ namespace Interpreter
* Array of trampolines, indexed by number or arguments.
*/
extern MysoreScript::ClosureInvoke closureTrampolines[];
};
}
4 changes: 2 additions & 2 deletions main.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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<double>(c2) - static_cast<double>(c1)) / static_cast<double>(CLOCKS_PER_SEC)
<< " seconds. Peak used " << r.ru_maxrss/1024 << "KB." << std::endl;
Expand Down Expand Up @@ -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."
Expand Down