Commit b73cb68e authored by Kevin Modzelewski's avatar Kevin Modzelewski

Add a fastpath in callFunc for simple cases

parent ec20c12f
......@@ -65,6 +65,9 @@ public:
#else
struct Stats {
static void dump() { printf("(Stats disabled)\n"); }
static void log(int id, int count = 1) {}
static int getStatId(const std::string& name) { return 0; }
static void endOfInit() {}
};
struct StatCounter {
StatCounter(const char* name) {}
......
......@@ -66,14 +66,15 @@ struct ArgPassSpec {
int totalPassed() { return num_args + num_keywords + (has_starargs ? 1 : 0) + (has_kwargs ? 1 : 0); }
uintptr_t asInt() const { return *reinterpret_cast<const uintptr_t*>(this); }
uint32_t asInt() const { return *reinterpret_cast<const uint32_t*>(this); }
void dump() {
printf("(has_starargs=%s, has_kwargs=%s, num_keywords=%d, num_args=%d)\n", has_starargs ? "true" : "false",
has_kwargs ? "true" : "false", num_keywords, num_args);
}
};
static_assert(sizeof(ArgPassSpec) <= sizeof(void*), "ArgPassSpec doesn't fit in register!");
static_assert(sizeof(ArgPassSpec) <= sizeof(void*), "ArgPassSpec doesn't fit in register! (CC is probably wrong)");
static_assert(sizeof(ArgPassSpec) == sizeof(uint32_t), "ArgPassSpec::asInt needs to be updated");
namespace gc {
......
......@@ -187,6 +187,8 @@ static int main(int argc, char** argv) {
} catch (ExcInfo e) {
int retcode = 1;
(void)handle_toplevel_exn(e, &retcode);
if (stats)
Stats::dump();
return retcode;
}
}
......@@ -210,6 +212,8 @@ static int main(int argc, char** argv) {
} catch (ExcInfo e) {
int retcode = 1;
(void)handle_toplevel_exn(e, &retcode);
if (stats)
Stats::dump();
return retcode;
}
}
......@@ -257,8 +261,11 @@ static int main(int argc, char** argv) {
compileAndRunModule(m, main_module);
} catch (ExcInfo e) {
int retcode = 0xdeadbeef; // should never be seen
if (handle_toplevel_exn(e, &retcode))
if (handle_toplevel_exn(e, &retcode)) {
if (stats)
Stats::dump();
return retcode;
}
}
}
}
......@@ -275,7 +282,7 @@ static int main(int argc, char** argv) {
int rtncode = joinRuntime();
_t.split("finishing up");
if (VERBOSITY() >= 1 || stats)
if (stats)
Stats::dump();
return rtncode;
......
......@@ -2551,6 +2551,8 @@ static KeywordDest placeKeyword(const ParamNames& param_names, llvm::SmallVector
}
}
static StatCounter slowpath_callfunc("slowpath_callfunc");
static StatCounter slowpath_callfunc_slowpath("slowpath_callfunc_slowpath");
Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpec argspec, Box* arg1, Box* arg2,
Box* arg3, Box** args, const std::vector<const std::string*>* keyword_names) {
......@@ -2562,17 +2564,14 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
* - error about missing parameters
*/
static StatCounter slowpath_resolveclfunc("slowpath_callfunc");
slowpath_resolveclfunc.log();
BoxedClosure* closure = func->closure;
CLFunction* f = func->f;
FunctionList& versions = f->versions;
slowpath_callfunc.log();
int num_output_args = f->numReceivedArgs();
int num_passed_args = argspec.totalPassed();
BoxedClosure* closure = func->closure;
if (argspec.has_starargs || argspec.has_kwargs || func->isGenerator) {
rewrite_args = NULL;
REWRITE_ABORTED("");
......@@ -2605,6 +2604,16 @@ Box* callFunc(BoxedFunctionBase* func, CallRewriteArgs* rewrite_args, ArgPassSpe
}
}
// Fast path: if it's a simple-enough call, we don't have to do anything special. On a simple
// django-admin test this covers something like 93% of all calls to callFunc.
if (!func->isGenerator) {
if (argspec.num_keywords == 0 && !argspec.has_starargs && !argspec.has_kwargs && argspec.num_args == f->num_args
&& !f->takes_varargs && !f->takes_kwargs) {
return callCLFunc(f, rewrite_args, argspec.num_args, closure, NULL, arg1, arg2, arg3, args);
}
}
slowpath_callfunc_slowpath.log();
if (rewrite_args) {
// We might have trouble if we have more output args than input args,
// such as if we need more space to pass defaults.
......
......@@ -195,7 +195,7 @@ def run_test(fn, check_stats, run_memcheck):
out = "\n".join(out_lines)
stats = None
if code == 0 and collect_stats:
if code >= 0 and collect_stats:
stats = {}
assert out.count("Stats:") == 1
out, stats_str = out.split("Stats:")
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment