From b9bdcfb723ed6ab27bded850809f633b12d8c667 Mon Sep 17 00:00:00 2001 From: Jameson Nash Date: Fri, 6 Apr 2018 15:00:51 -0400 Subject: [PATCH] more accurate specsig tracking --- src/codegen.cpp | 6 +++--- src/debuginfo.cpp | 7 ------- src/dump.c | 1 + src/gf.c | 5 ++++- src/jitlayers.cpp | 19 +++++++++++++------ src/jltypes.c | 8 +++++--- src/julia.h | 1 + src/method.c | 1 + src/staticdata.c | 8 ++++++-- 9 files changed, 34 insertions(+), 22 deletions(-) diff --git a/src/codegen.cpp b/src/codegen.cpp index 714e888a6a7bc..e62dd388be549 100644 --- a/src/codegen.cpp +++ b/src/codegen.cpp @@ -2604,7 +2604,7 @@ static jl_cgval_t emit_invoke(jl_codectx_t &ctx, jl_expr_t *ex) // optimization: emit the correct name immediately, if we know it // TODO: use `emitted` map here too to try to consolidate names? if (li->specptr.fptr) { - if (specsig ? 1/*TODO*/ : li->invoke == jl_fptr_args) { + if (specsig ? li->isspecsig : li->invoke == jl_fptr_args) { protoname = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)li->specptr.fptr, li); need_to_emit = false; } @@ -3814,7 +3814,7 @@ static Function* gen_cfun_wrapper( callptr = (void*)lam->inferred_const; calltype = 2; } - else if (lam->invoke != jl_fptr_sparam) { + else if (lam->isspecsig) { callptr = lam->specptr.fptr; calltype = 3; } @@ -6389,7 +6389,7 @@ void jl_compile_workqueue( else if (li->invoke == &jl_fptr_args) { preal_decl = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)li->specptr.fptr, li); } - else if (li->invoke != &jl_fptr_sparam) { + else if (li->isspecsig) { preal_decl = jl_ExecutionEngine->getFunctionAtAddress((uintptr_t)li->specptr.fptr, li); preal_specsig = true; } diff --git a/src/debuginfo.cpp b/src/debuginfo.cpp index e9614ef9bb7be..df7edaea1fb04 100644 --- a/src/debuginfo.cpp +++ b/src/debuginfo.cpp @@ -326,8 +326,6 @@ class JuliaJITEventListener: public JITEventListener #endif // defined(_OS_X86_64_) #endif // defined(_OS_WINDOWS_) - std::vector> def_spec; - std::vector> def_invoke; auto symbols = object::computeSymbolSizes(debugObj); bool first = true; for (const auto &sym_size : symbols) { @@ -384,11 +382,6 @@ class JuliaJITEventListener: public JITEventListener objectmap[SectionLoadAddr] = tmp; first = false; } - // now process these in order, so we ensure the closure values are updated before removing the trampoline - for (auto &def : def_spec) - def.first->specptr.fptr = (void*)def.second; - for (auto &def : def_invoke) - def.first->invoke = (jl_callptr_t)def.second; } uv_rwlock_wrunlock(&threadsafe); jl_gc_safe_leave(ptls, gc_state); diff --git a/src/dump.c b/src/dump.c index 96a29dad728fc..87eafacc5ade6 100644 --- a/src/dump.c +++ b/src/dump.c @@ -1658,6 +1658,7 @@ static jl_value_t *jl_deserialize_value_method_instance(jl_serializer_state *s, abort(); } li->inInference = 0; + li->isspecsig = 0; li->specptr.fptr = NULL; if (read_int8(s->s) == 2) li->invoke = jl_fptr_const_return; diff --git a/src/gf.c b/src/gf.c index 92c16ab480327..7c72799803b10 100644 --- a/src/gf.c +++ b/src/gf.c @@ -419,6 +419,8 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( // changing rettype changes the llvm signature, // so clear all of the llvm state at the same time li->invoke = jl_fptr_trampoline; + li->isspecsig = 0; + li->specptr.fptr = NULL; li->rettype = rettype; jl_gc_wb(li, rettype); li->inferred = inferred; @@ -431,7 +433,6 @@ JL_DLLEXPORT jl_method_instance_t* jl_set_method_inferred( assert(const_flags & 2); li->invoke = jl_fptr_const_return; } - li->specptr.fptr = NULL; JL_GC_POP(); return li; } @@ -1753,6 +1754,7 @@ jl_callptr_t jl_compile_method_internal(jl_method_instance_t **pli, size_t world if (jl_is_method(def) && def->unspecialized) { jl_method_instance_t *unspec = def->unspecialized; if (unspec->invoke != jl_fptr_trampoline) { + li->isspecsig = 0; li->specptr = unspec->specptr; li->inferred = unspec->inferred; if (li->inferred) @@ -1797,6 +1799,7 @@ JL_DLLEXPORT jl_value_t *jl_fptr_trampoline(jl_method_instance_t *m, jl_value_t (void)jl_generate_fptr_for_unspecialized(unspec); if (unspec->invoke != jl_fptr_trampoline) { // use unspec pointers + m->isspecsig = 0; m->specptr = unspec->specptr; m->inferred = unspec->inferred; if (m->inferred) diff --git a/src/jitlayers.cpp b/src/jitlayers.cpp index c408457b4f3a8..d3ba72f09319f 100644 --- a/src/jitlayers.cpp +++ b/src/jitlayers.cpp @@ -96,19 +96,26 @@ static jl_callptr_t _jl_compile_linfo( jl_llvm_functions_t decls = std::get<1>(def.second); jl_value_t *rettype = std::get<2>(def.second); jl_callptr_t addr; - if (decls.functionObject == "jl_fptr_args") + bool isspecsig = false; + if (decls.functionObject == "jl_fptr_args") { addr = &jl_fptr_args; - else if (decls.functionObject == "jl_fptr_sparam") + } + else if (decls.functionObject == "jl_fptr_sparam") { addr = &jl_fptr_sparam; - else + } + else { addr = (jl_callptr_t)getAddressForFunction(decls.functionObject); + isspecsig = jl_egal(rettype, this_li->rettype); + } if (this_li->compile_traced) triggered_linfos.push_back(this_li); if (this_li->invoke == jl_fptr_trampoline) { // once set, don't change invoke-ptr, as that leads to race conditions // with the (not) simultaneous updates to invoke and specptr - if (!decls.specFunctionObject.empty() && jl_egal(rettype, this_li->rettype)) + if (!decls.specFunctionObject.empty()) { this_li->specptr.fptr = (void*)getAddressForFunction(decls.specFunctionObject); + this_li->isspecsig = isspecsig; + } this_li->invoke = addr; } else if (this_li->invoke == jl_fptr_const_return && !decls.specFunctionObject.empty()) { @@ -725,7 +732,7 @@ StringRef JuliaOJIT::getFunctionAtAddress(uint64_t Addr, jl_method_instance_t *l std::stringstream stream_fname; // try to pick an appropriate name that describes it if (Addr == (uintptr_t)li->invoke) { - stream_fname << "jlsysw_"; + stream_fname << "jsysw_"; } else if (li->invoke == &jl_fptr_args) { stream_fname << "jsys1_"; @@ -733,7 +740,7 @@ StringRef JuliaOJIT::getFunctionAtAddress(uint64_t Addr, jl_method_instance_t *l else if (li->invoke == &jl_fptr_sparam) { stream_fname << "jsys3_"; } - else if (li->invoke == &jl_fptr_sparam) { + else { stream_fname << "jlsys_"; } const char* unadorned_name = jl_symbol_name(li->def.method->name); diff --git a/src/jltypes.c b/src/jltypes.c index c3ea05b466fe7..a0daafda4bad7 100644 --- a/src/jltypes.c +++ b/src/jltypes.c @@ -2090,7 +2090,7 @@ void jl_init_types(void) jl_method_instance_type = jl_new_datatype(jl_symbol("MethodInstance"), core, jl_any_type, jl_emptysvec, - jl_perm_symsvec(13, + jl_perm_symsvec(14, "def", "specTypes", "rettype", @@ -2102,9 +2102,10 @@ void jl_init_types(void) "max_world", "inInference", "", + "specsig", "invoke", "specptr"), - jl_svec(13, + jl_svec(14, jl_new_struct(jl_uniontype_type, jl_method_type, jl_module_type), jl_any_type, jl_any_type, @@ -2116,6 +2117,7 @@ void jl_init_types(void) jl_long_type, jl_bool_type, jl_bool_type, + jl_bool_type, jl_any_type, // fptr jl_any_type), // fptr 0, 1, 4); @@ -2196,8 +2198,8 @@ void jl_init_types(void) #endif jl_svecset(jl_methtable_type->types, 8, jl_int32_type); // uint32_t jl_svecset(jl_method_type->types, 10, jl_method_instance_type); - jl_svecset(jl_method_instance_type->types, 11, jl_voidpointer_type); jl_svecset(jl_method_instance_type->types, 12, jl_voidpointer_type); + jl_svecset(jl_method_instance_type->types, 13, jl_voidpointer_type); jl_compute_field_offsets(jl_datatype_type); jl_compute_field_offsets(jl_typename_type); diff --git a/src/julia.h b/src/julia.h index 68fd294c59a45..998621bdd0736 100644 --- a/src/julia.h +++ b/src/julia.h @@ -308,6 +308,7 @@ typedef struct _jl_method_instance_t { size_t max_world; uint8_t inInference; // flags to tell if inference is running on this function uint8_t compile_traced; // if set will notify callback if this linfo is compiled + uint8_t isspecsig; // if specptr is specsig for specTypes->rettype jl_callptr_t invoke; // jlcall entry point jl_generic_specptr_t specptr; } jl_method_instance_t; diff --git a/src/method.c b/src/method.c index bf83d76c7bbc1..3489ea618e62f 100644 --- a/src/method.c +++ b/src/method.c @@ -285,6 +285,7 @@ JL_DLLEXPORT jl_method_instance_t *jl_new_method_instance_uninit(void) li->sparam_vals = jl_emptysvec; li->backedges = NULL; li->invoke = jl_fptr_trampoline; + li->isspecsig = 0; li->specptr.fptr = NULL; li->compile_traced = 0; li->specTypes = NULL; diff --git a/src/staticdata.c b/src/staticdata.c index fba31bc20e675..97637c1fce61a 100644 --- a/src/staticdata.c +++ b/src/staticdata.c @@ -648,6 +648,7 @@ static void jl_write_values(jl_serializer_state *s) jl_method_instance_t *newm = (jl_method_instance_t*)&s->s->buf[reloc_offset]; newm->invoke = NULL; + newm->isspecsig = 0; newm->specptr.fptr = NULL; int8_t fptr_id = JL_API_TRAMPOLINE; int8_t builtin_id = 0; @@ -1004,10 +1005,13 @@ static void jl_update_all_fptrs(jl_serializer_state *s) break; } void *fptr = (void*)(base + offset); - if (specfunc) + if (specfunc) { li->specptr.fptr = fptr; - else + li->isspecsig = 1; // TODO: set only if actually true + } + else { li->invoke = (jl_callptr_t)fptr; + } jl_fptr_to_llvm(fptr, li, specfunc); } }