From 8da203b91a7cec4201aac343c06d1bf6a76164be Mon Sep 17 00:00:00 2001 From: Sebastian Ullrich Date: Mon, 9 Sep 2019 16:59:45 +0200 Subject: [PATCH] perf(compiler/ir_interpreter): do not allocate temp closure for saturated partial applications --- script/apply.lean | 9 +++--- src/library/compiler/ir_interpreter.cpp | 5 +--- src/runtime/apply.cpp | 37 +++++++++++++------------ src/runtime/apply.h | 2 +- 4 files changed, 26 insertions(+), 27 deletions(-) diff --git a/script/apply.lean b/script/apply.lean index 2662914747..328c59ba0b 100644 --- a/script/apply.lean +++ b/script/apply.lean @@ -97,15 +97,16 @@ do emit $ sformat! "obj* apply_{n}(obj* f, {arg_decls}) {{\n", emit "}\n" def mk_curry (max : nat) : m unit := -do emit "static obj* curry(obj* f, unsigned n, obj** as) {\n", +do emit "static obj* curry(void* f, unsigned n, obj** as) {\n", emit "switch (n) {\n", emit "case 0: lean_unreachable();\n", max.mrepeat $ λ i, let as := mk_as_args (i+1) in - emit $ sformat! "case {i+1}: return FN{i+1}(f)({as});\n", - emit "default: return FNN(f)(as);\n", + emit $ sformat! "case {i+1}: return reinterpret_cast(f)({as});\n", + emit "default: return reinterpret_cast(f)(as);\n", emit "}\n", - emit "}\n" + emit "}\n", + emit "static obj* curry(obj* f, unsigned n, obj** as) { return curry(closure_fun(f), n, as); }\n" def mk_apply_n (max : nat) : m unit := do emit "obj* apply_n(obj* f, unsigned n, obj** as) {\n", diff --git a/src/library/compiler/ir_interpreter.cpp b/src/library/compiler/ir_interpreter.cpp index 2dacf35e78..9925d80aea 100644 --- a/src/library/compiler/ir_interpreter.cpp +++ b/src/library/compiler/ir_interpreter.cpp @@ -661,10 +661,7 @@ class interpreter { } } } - // HACK: `curry` wants a closure object instead of just a function pointer - object * cls = alloc_closure(e.m_addr, 2, 1); - r = curry(cls, args.size(), &m_arg_stack[old_size]); - free_heap_obj(cls); + r = curry(e.m_addr, args.size(), &m_arg_stack[old_size]); } else { if (decl_tag(d) == decl_kind::Extern) { throw exception(sstream() << "unexpected external declaration '" << fn << "'"); diff --git a/src/runtime/apply.cpp b/src/runtime/apply.cpp index dc18c6de44..4c948a4079 100644 --- a/src/runtime/apply.cpp +++ b/src/runtime/apply.cpp @@ -74,28 +74,29 @@ typedef obj* (*fn16)(obj*, obj*, obj*, obj*, obj*, obj*, obj*, obj*, obj*, obj*, #define FN16(f) reinterpret_cast(lean_closure_fun(f)) typedef obj* (*fnn)(obj**); // NOLINT #define FNN(f) reinterpret_cast(lean_closure_fun(f)) -obj* curry(obj* f, unsigned n, obj** as) { +obj* curry(void* f, unsigned n, obj** as) { switch (n) { case 0: lean_unreachable(); -case 1: return FN1(f)(as[0]); -case 2: return FN2(f)(as[0], as[1]); -case 3: return FN3(f)(as[0], as[1], as[2]); -case 4: return FN4(f)(as[0], as[1], as[2], as[3]); -case 5: return FN5(f)(as[0], as[1], as[2], as[3], as[4]); -case 6: return FN6(f)(as[0], as[1], as[2], as[3], as[4], as[5]); -case 7: return FN7(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6]); -case 8: return FN8(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7]); -case 9: return FN9(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8]); -case 10: return FN10(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9]); -case 11: return FN11(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10]); -case 12: return FN12(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10], as[11]); -case 13: return FN13(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10], as[11], as[12]); -case 14: return FN14(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10], as[11], as[12], as[13]); -case 15: return FN15(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10], as[11], as[12], as[13], as[14]); -case 16: return FN16(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10], as[11], as[12], as[13], as[14], as[15]); -default: return FNN(f)(as); +case 1: return reinterpret_cast(f)(as[0]); +case 2: return reinterpret_cast(f)(as[0], as[1]); +case 3: return reinterpret_cast(f)(as[0], as[1], as[2]); +case 4: return reinterpret_cast(f)(as[0], as[1], as[2], as[3]); +case 5: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4]); +case 6: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5]); +case 7: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6]); +case 8: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7]); +case 9: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8]); +case 10: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9]); +case 11: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10]); +case 12: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10], as[11]); +case 13: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10], as[11], as[12]); +case 14: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10], as[11], as[12], as[13]); +case 15: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10], as[11], as[12], as[13], as[14]); +case 16: return reinterpret_cast(f)(as[0], as[1], as[2], as[3], as[4], as[5], as[6], as[7], as[8], as[9], as[10], as[11], as[12], as[13], as[14], as[15]); +default: return reinterpret_cast(f)(as); } } +static obj* curry(obj* f, unsigned n, obj** as) { return curry(lean_closure_fun(f), n, as); } extern "C" obj* lean_apply_n(obj*, unsigned, obj**); extern "C" obj* lean_apply_1(obj* f, obj* a1) { unsigned arity = lean_closure_arity(f); diff --git a/src/runtime/apply.h b/src/runtime/apply.h index 391f599570..7a08d58d1c 100644 --- a/src/runtime/apply.h +++ b/src/runtime/apply.h @@ -7,5 +7,5 @@ Author: Leonardo de Moura #pragma once #include "runtime/object.h" namespace lean { -object * curry(object * f, unsigned n, object ** as); +object * curry(void * f, unsigned n, object ** as); }