Skip to content

Commit

Permalink
Merge pull request #22678 from JuliaLang/jn/cgctx-globals
Browse files Browse the repository at this point in the history
only store JIT function names, not full prototypes
  • Loading branch information
vtjnash authored Jul 14, 2017
2 parents ea61ec6 + 3ec5dc0 commit 615a7ba
Show file tree
Hide file tree
Showing 9 changed files with 266 additions and 295 deletions.
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 @@ -761,9 +761,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 @@ -802,27 +802,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 @@ -1164,13 +1163,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 @@ -859,9 +859,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

0 comments on commit 615a7ba

Please sign in to comment.