Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

only store JIT function names, not full prototypes #22678

Merged
merged 2 commits into from
Jul 14, 2017
Merged
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
33 changes: 33 additions & 0 deletions src/cgutils.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,39 @@ static Instruction *tbaa_decorate(MDNode *md, Instruction *load_or_store)
return load_or_store;
}

static Function *function_proto(Function *F, Module *M = nullptr)
{
// Copy the declaration characteristics of the Function (not the body)
Function *NewF = Function::Create(F->getFunctionType(),
Function::ExternalLinkage,
F->getName(),
M);

// Declarations are not allowed to have personality routines, but
// copyAttributesFrom sets them anyway. Temporarily unset the personality
// routine from `F`, since copying it and then resetting is more expensive
// as well as introducing an extra use from this unowned function, which
// can cause crashes in the LLVMContext's global destructor.
llvm::Constant *OldPersonalityFn = nullptr;
if (F->hasPersonalityFn()) {
OldPersonalityFn = F->getPersonalityFn();
F->setPersonalityFn(nullptr);
}

// FunctionType does not include any attributes. Copy them over manually
// as codegen may make decisions based on the presence of certain attributes
NewF->copyAttributesFrom(F);

if (OldPersonalityFn)
F->setPersonalityFn(OldPersonalityFn);

// DLLImport only needs to be set for the shadow module
// it just gets annoying in the JIT
NewF->setDLLStorageClass(GlobalValue::DefaultStorageClass);

return NewF;
}

#define prepare_call(Callee) prepare_call_in(jl_Module, (Callee))
static Value *prepare_call_in(Module *M, Value *Callee)
{
Expand Down
443 changes: 208 additions & 235 deletions src/codegen.cpp

Large diffs are not rendered by default.

4 changes: 2 additions & 2 deletions src/debuginfo.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,8 @@ class JuliaJITEventListener: public JITEventListener
if (linfo->compile_traced)
triggered_linfos.push_back(linfo);
linfo_in_flight.erase(linfo_it);
Function *F = (Function*)linfo->functionObjectsDecls.functionObject;
if (!linfo->fptr && F && F->getName().equals(sName)) {
const char *F = linfo->functionObjectsDecls.functionObject;
if (!linfo->fptr && F && sName.equals(F)) {
int jlcall_api = jl_jlcall_api(F);
if (linfo->inferred || jlcall_api != 1) {
linfo->jlcall_api = jlcall_api;
Expand Down
21 changes: 10 additions & 11 deletions src/jitlayers.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -760,9 +760,9 @@ static void jl_add_to_ee(std::unique_ptr<Module> m)
jl_ExecutionEngine->addModule(std::move(m));
}

void jl_finalize_function(Function *F)
void jl_finalize_function(StringRef F)
{
std::unique_ptr<Module> m(module_for_fname.lookup(F->getName()));
std::unique_ptr<Module> m(module_for_fname.lookup(F));
if (m) {
jl_merge_recursive(m.get(), m.get());
jl_add_to_ee(std::move(m));
Expand Down Expand Up @@ -801,27 +801,26 @@ static void jl_merge_recursive(Module *m, Module *collector)

// see if any of the functions needed by F are still WIP
static StringSet<> incomplete_fname;
static bool jl_can_finalize_function(StringRef F, SmallSet<Module*, 16> &known)
static bool can_finalize_function(StringRef F, SmallSet<Module*, 16> &known)
{
if (incomplete_fname.find(F) != incomplete_fname.end())
return false;
Module *M = module_for_fname.lookup(F);
if (M && known.insert(M).second)
{
if (M && known.insert(M).second) {
for (Module::iterator I = M->begin(), E = M->end(); I != E; ++I) {
Function *F = &*I;
if (F->isDeclaration() && !isIntrinsicFunction(F)) {
if (!jl_can_finalize_function(F->getName(), known))
if (!can_finalize_function(F->getName(), known))
return false;
}
}
}
return true;
}
bool jl_can_finalize_function(Function *F)
bool jl_can_finalize_function(StringRef F)
{
SmallSet<Module*, 16> known;
return jl_can_finalize_function(F->getName(), known);
return can_finalize_function(F, known);
}

// let the JIT know this function is a WIP
Expand Down Expand Up @@ -1162,13 +1161,13 @@ void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char
imaging_mode = false;
}

extern "C" int32_t jl_assign_functionID(void *function)
extern "C" int32_t jl_assign_functionID(const char *fname)
{
// give the function an index in the constant lookup table
assert(imaging_mode);
if (function == NULL)
if (fname == NULL)
return 0;
jl_sysimg_fvars.push_back(shadow_output->getNamedValue(((Function*)function)->getName()));
jl_sysimg_fvars.push_back(shadow_output->getNamedValue(fname));
return jl_sysimg_fvars.size();
}

Expand Down
36 changes: 2 additions & 34 deletions src/jitlayers.h
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ void* jl_get_globalvar(GlobalVariable *gv);
GlobalVariable *jl_get_global_for(const char *cname, void *addr, Module *M);
void jl_add_to_shadow(Module *m);
void jl_init_function(Function *f);
bool jl_can_finalize_function(Function *F);
void jl_finalize_function(Function *F);
bool jl_can_finalize_function(StringRef F);
void jl_finalize_function(StringRef F);
void jl_finalize_module(Module *m, bool shadow);

// Connect Modules via prototypes, each owned by module `M`
Expand All @@ -69,38 +69,6 @@ static inline GlobalVariable *global_proto(GlobalVariable *G, Module *M = NULL)
return proto;
}

static inline Function *function_proto(Function *F, Module *M = NULL)
{
// Copy the declaration characteristics of the Function (not the body)
Function *NewF = Function::Create(F->getFunctionType(),
Function::ExternalLinkage,
F->getName(), M);

// Declarations are not allowed to have personality routines, but
// copyAttributesFrom sets them anyway. Temporarily unset the personality
// routine from `F`, since copying it and then resetting is more expensive
// as well as introducing an extra use from this unowned function, which
// can cause crashes in the LLVMContext's global destructor.
llvm::Constant *OldPersonalityFn = nullptr;
if (F->hasPersonalityFn()) {
OldPersonalityFn = F->getPersonalityFn();
F->setPersonalityFn(nullptr);
}

// FunctionType does not include any attributes. Copy them over manually
// as codegen may make decisions based on the presence of certain attributes
NewF->copyAttributesFrom(F);

if (OldPersonalityFn)
F->setPersonalityFn(OldPersonalityFn);

// DLLImport only needs to be set for the shadow module
// it just gets annoying in the JIT
NewF->setDLLStorageClass(GlobalValue::DefaultStorageClass);

return NewF;
}

static inline GlobalVariable *prepare_global_in(Module *M, GlobalVariable *G)
{
if (G->getParent() == M)
Expand Down
10 changes: 4 additions & 6 deletions src/julia.h
Original file line number Diff line number Diff line change
Expand Up @@ -206,8 +206,8 @@ JL_EXTENSION typedef struct {
} jl_generic_fptr_t;

typedef struct _jl_llvm_functions_t {
void *functionObject; // jlcall llvm Function
void *specFunctionObject; // specialized llvm Function
const char *functionObject; // jlcall llvm Function name
const char *specFunctionObject; // specialized llvm Function name
} jl_llvm_functions_t;

// This type describes a single function body
Expand Down Expand Up @@ -287,10 +287,8 @@ typedef struct _jl_method_instance_t {
jl_fptr_t fptr; // jlcall entry point with api specified by jlcall_api
jl_fptr_t unspecialized_ducttape; // if template can't be compiled due to intrinsics, an un-inferred fptr may get stored here, jlcall_api = 1

// On the old JIT, handles to all Functions generated for this linfo
// For the new JITs, handles to declarations in the shadow module
// with the same name as the generated functions for this linfo, suitable
// for referencing in LLVM IR
// names of declarations in the JIT,
// suitable for referencing in LLVM IR
jl_llvm_functions_t functionObjectsDecls;
} jl_method_instance_t;

Expand Down
8 changes: 4 additions & 4 deletions src/julia_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -312,7 +312,7 @@ jl_svec_t *jl_perm_symsvec(size_t n, ...);
jl_value_t *jl_gc_realloc_string(jl_value_t *s, size_t sz);

jl_code_info_t *jl_type_infer(jl_method_instance_t **li, size_t world, int force);
jl_generic_fptr_t jl_generate_fptr(jl_method_instance_t *li, void *F, size_t world);
jl_generic_fptr_t jl_generate_fptr(jl_method_instance_t *li, const char *F, size_t world);
jl_llvm_functions_t jl_compile_linfo(
jl_method_instance_t **pli,
jl_code_info_t *src,
Expand All @@ -332,7 +332,7 @@ STATIC_INLINE jl_value_t *jl_compile_method_internal(jl_generic_fptr_t *fptr,
if (__unlikely(fptr->fptr == NULL || fptr->jlcall_api == 0)) {
size_t world = jl_get_ptls_states()->world_age;
// first see if it likely needs to be compiled
void *F = meth->functionObjectsDecls.functionObject;
const char *F = meth->functionObjectsDecls.functionObject;
if (!F) // ask codegen to try to turn it into llvm code
F = jl_compile_for_dispatch(&meth, world).functionObject;
if (meth->jlcall_api == 2)
Expand Down Expand Up @@ -616,8 +616,8 @@ static inline void jl_set_gc_and_wait(void)

void jl_dump_native(const char *bc_fname, const char *unopt_bc_fname, const char *obj_fname, const char *sysimg_data, size_t sysimg_len);
int32_t jl_get_llvm_gv(jl_value_t *p);
int32_t jl_assign_functionID(/*llvm::Function*/void *function);
int32_t jl_jlcall_api(/*llvm::Function*/const void *function);
int32_t jl_assign_functionID(const char *fname);
int32_t jl_jlcall_api(const char *fname);
// the first argument to jl_idtable_rehash is used to return a value
// make sure it is rooted if it is used after the function returns
JL_DLLEXPORT jl_array_t *jl_idtable_rehash(jl_array_t *a, size_t newsz);
Expand Down
2 changes: 1 addition & 1 deletion src/method.c
Original file line number Diff line number Diff line change
Expand Up @@ -244,7 +244,7 @@ STATIC_INLINE jl_value_t *jl_call_staged(jl_svec_t *sparam_vals, jl_method_insta
fptr.jlcall_api = generator->jlcall_api;
if (__unlikely(fptr.fptr == NULL || fptr.jlcall_api == 0)) {
size_t world = generator->def.method->min_world;
void *F = jl_compile_linfo(&generator, (jl_code_info_t*)generator->inferred, world, &jl_default_cgparams).functionObject;
const char *F = jl_compile_linfo(&generator, (jl_code_info_t*)generator->inferred, world, &jl_default_cgparams).functionObject;
fptr = jl_generate_fptr(generator, F, world);
}
assert(jl_svec_len(generator->def.method->sparam_syms) == jl_svec_len(sparam_vals));
Expand Down
4 changes: 2 additions & 2 deletions test/inference.jl
Original file line number Diff line number Diff line change
Expand Up @@ -858,9 +858,9 @@ let f, m
end

# issue #22290
f22290() = return nothing
f22290() = return 3
for i in 1:3
ir = sprint(io->code_llvm(io, f22290, Tuple{}))
ir = sprint(io -> code_llvm(io, f22290, Tuple{}))
@test contains(ir, "julia_f22290")
end

Expand Down