Commit e3d2c721 authored by Kevin Modzelewski's avatar Kevin Modzelewski

Cache some properties of function versions to make resolution faster

For calling runtime functions, we usually just have one function that
handles all types.  We can bypass most of the resolution work by just
skipping to that function.
parent b73cb68e
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include "llvm/Support/FileSystem.h" #include "llvm/Support/FileSystem.h"
#include "analysis/scoping_analysis.h" #include "analysis/scoping_analysis.h"
#include "codegen/compvars.h"
#include "core/ast.h" #include "core/ast.h"
#include "core/util.h" #include "core/util.h"
...@@ -200,4 +201,20 @@ GlobalState::GlobalState() : context(llvm::getGlobalContext()), cur_module(NULL) ...@@ -200,4 +201,20 @@ GlobalState::GlobalState() : context(llvm::getGlobalContext()), cur_module(NULL)
llvm::JITEventListener* makeRegistryListener() { llvm::JITEventListener* makeRegistryListener() {
return new RegistryEventListener(); return new RegistryEventListener();
} }
FunctionSpecialization::FunctionSpecialization(ConcreteCompilerType* rtn_type) : rtn_type(rtn_type) {
accepts_all_inputs = true;
boxed_return_value = (rtn_type->llvmType() == UNKNOWN->llvmType());
}
FunctionSpecialization::FunctionSpecialization(ConcreteCompilerType* rtn_type,
const std::vector<ConcreteCompilerType*>& arg_types)
: rtn_type(rtn_type), arg_types(arg_types) {
accepts_all_inputs = true;
boxed_return_value = (rtn_type->llvmType() == UNKNOWN->llvmType());
for (auto t : arg_types) {
accepts_all_inputs = accepts_all_inputs && (t == UNKNOWN);
}
}
} }
...@@ -157,14 +157,11 @@ public: ...@@ -157,14 +157,11 @@ public:
struct FunctionSpecialization { struct FunctionSpecialization {
ConcreteCompilerType* rtn_type; ConcreteCompilerType* rtn_type;
std::vector<ConcreteCompilerType*> arg_types; std::vector<ConcreteCompilerType*> arg_types;
bool boxed_return_value;
bool accepts_all_inputs;
FunctionSpecialization(ConcreteCompilerType* rtn_type) : rtn_type(rtn_type) {} FunctionSpecialization(ConcreteCompilerType* rtn_type);
FunctionSpecialization(ConcreteCompilerType* rtn_type, const std::vector<ConcreteCompilerType*>& arg_types);
FunctionSpecialization(ConcreteCompilerType* rtn_type, ConcreteCompilerType* arg1, ConcreteCompilerType* arg2)
: rtn_type(rtn_type), arg_types({ arg1, arg2 }) {}
FunctionSpecialization(ConcreteCompilerType* rtn_type, const std::vector<ConcreteCompilerType*>& arg_types)
: rtn_type(rtn_type), arg_types(arg_types) {}
}; };
class BoxedClosure; class BoxedClosure;
...@@ -278,6 +275,7 @@ public: ...@@ -278,6 +275,7 @@ public:
FunctionList FunctionList
versions; // any compiled versions along with their type parameters; in order from most preferred to least versions; // any compiled versions along with their type parameters; in order from most preferred to least
CompiledFunction* always_use_version; // if this version is set, always use it (for unboxed cases)
std::unordered_map<const OSREntryDescriptor*, CompiledFunction*> osr_versions; std::unordered_map<const OSREntryDescriptor*, CompiledFunction*> osr_versions;
// Functions can provide an "internal" version, which will get called instead // Functions can provide an "internal" version, which will get called instead
...@@ -290,12 +288,12 @@ public: ...@@ -290,12 +288,12 @@ public:
CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, SourceInfo* source) CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, SourceInfo* source)
: num_args(num_args), num_defaults(num_defaults), takes_varargs(takes_varargs), takes_kwargs(takes_kwargs), : num_args(num_args), num_defaults(num_defaults), takes_varargs(takes_varargs), takes_kwargs(takes_kwargs),
source(source), param_names(source->ast) { source(source), param_names(source->ast), always_use_version(NULL) {
assert(num_args >= num_defaults); assert(num_args >= num_defaults);
} }
CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, const ParamNames& param_names) CLFunction(int num_args, int num_defaults, bool takes_varargs, bool takes_kwargs, const ParamNames& param_names)
: num_args(num_args), num_defaults(num_defaults), takes_varargs(takes_varargs), takes_kwargs(takes_kwargs), : num_args(num_args), num_defaults(num_defaults), takes_varargs(takes_varargs), takes_kwargs(takes_kwargs),
source(NULL), param_names(param_names) { source(NULL), param_names(param_names), always_use_version(NULL) {
assert(num_args >= num_defaults); assert(num_args >= num_defaults);
} }
......
...@@ -2444,17 +2444,29 @@ static inline Box*& getArg(int idx, Box*& arg1, Box*& arg2, Box*& arg3, Box** ar ...@@ -2444,17 +2444,29 @@ static inline Box*& getArg(int idx, Box*& arg1, Box*& arg2, Box*& arg3, Box** ar
return args[idx - 3]; return args[idx - 3];
} }
static StatCounter slowpath_pickversion("slowpath_pickversion");
static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oarg1, Box* oarg2, Box* oarg3, static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oarg1, Box* oarg2, Box* oarg3,
Box** oargs) { Box** oargs) {
LOCK_REGION(codegen_rwlock.asWrite()); LOCK_REGION(codegen_rwlock.asWrite());
CompiledFunction* chosen_cf = NULL; if (f->always_use_version)
return f->always_use_version;
slowpath_pickversion.log();
for (CompiledFunction* cf : f->versions) { for (CompiledFunction* cf : f->versions) {
assert(cf->spec->arg_types.size() == num_output_args); assert(cf->spec->arg_types.size() == num_output_args);
if (cf->spec->rtn_type->llvmType() != UNKNOWN->llvmType()) if (!cf->spec->boxed_return_value)
continue; continue;
if (cf->spec->accepts_all_inputs) {
if (cf == f->versions[0] && cf->effort == EffortLevel::MAXIMAL)
f->always_use_version = cf;
return cf;
}
assert(cf->spec->rtn_type->llvmType() == UNKNOWN->llvmType());
bool works = true; bool works = true;
for (int i = 0; i < num_output_args; i++) { for (int i = 0; i < num_output_args; i++) {
Box* arg = getArg(i, oarg1, oarg2, oarg3, oargs); Box* arg = getArg(i, oarg1, oarg2, oarg3, oargs);
...@@ -2469,38 +2481,33 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa ...@@ -2469,38 +2481,33 @@ static CompiledFunction* pickVersion(CLFunction* f, int num_output_args, Box* oa
if (!works) if (!works)
continue; continue;
chosen_cf = cf; return cf;
break;
} }
if (chosen_cf == NULL) { if (f->source == NULL) {
if (f->source == NULL) { // TODO I don't think this should be happening any more?
// TODO I don't think this should be happening any more? printf("Error: couldn't find suitable function version and no source to recompile!\n");
printf("Error: couldn't find suitable function version and no source to recompile!\n"); printf("(First version: %p)\n", f->versions[0]->code);
printf("(First version: %p)\n", f->versions[0]->code); abort();
abort(); }
}
EffortLevel new_effort = initialEffort(); EffortLevel new_effort = initialEffort();
std::vector<ConcreteCompilerType*> arg_types; std::vector<ConcreteCompilerType*> arg_types;
for (int i = 0; i < num_output_args; i++) { for (int i = 0; i < num_output_args; i++) {
if (new_effort == EffortLevel::INTERPRETED) { if (new_effort == EffortLevel::INTERPRETED) {
arg_types.push_back(UNKNOWN); arg_types.push_back(UNKNOWN);
} else { } else {
Box* arg = getArg(i, oarg1, oarg2, oarg3, oargs); Box* arg = getArg(i, oarg1, oarg2, oarg3, oargs);
assert(arg); // only builtin functions can pass NULL args assert(arg); // only builtin functions can pass NULL args
arg_types.push_back(typeFromClass(arg->cls)); arg_types.push_back(typeFromClass(arg->cls));
}
} }
FunctionSpecialization* spec = new FunctionSpecialization(UNKNOWN, arg_types);
// this also pushes the new CompiledVersion to the back of the version list:
chosen_cf = compileFunction(f, spec, new_effort, NULL);
} }
FunctionSpecialization* spec = new FunctionSpecialization(UNKNOWN, arg_types);
return chosen_cf; // this also pushes the new CompiledVersion to the back of the version list:
return compileFunction(f, spec, new_effort, NULL);
} }
static std::string getFunctionName(CLFunction* f) { static std::string getFunctionName(CLFunction* f) {
......
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