From a90c150c7c3e9dc42902e6e42ec91f6fe2657d44 Mon Sep 17 00:00:00 2001 From: soumyadeep2007 Date: Wed, 19 Feb 2020 16:12:39 -0800 Subject: [PATCH v3] Resolve PL handler names for JITed code instead of using const pointers This patch is similar in spirit to 8c2769405f and would similarly increase the scope for inlining and optimization. Earlier for references to PL functions, a const pointer to the PL's handler function was emitted. Specifically, fmgr_symbol() would return modname=NULL, basename=NULL for such a PL function reference. Then in llvm_function_reference() a const pointer to fcinfo->finfo->fn_addr (which would always be the PL handler's address for a PL function reference) would be emitted. Now, instead, look up the qualified PL handler's library and C function name in fmgr_symbol(), so that llvm_resolve_symbol() can resolve the PL handler's address. --- src/backend/jit/llvm/llvmjit.c | 29 +++------------------- src/backend/utils/fmgr/fmgr.c | 45 ++++++++++++++++++++++++++++------ 2 files changed, 42 insertions(+), 32 deletions(-) diff --git a/src/backend/jit/llvm/llvmjit.c b/src/backend/jit/llvm/llvmjit.c index af8b34aaaf..8c547c9090 100644 --- a/src/backend/jit/llvm/llvmjit.c +++ b/src/backend/jit/llvm/llvmjit.c @@ -363,39 +363,18 @@ llvm_function_reference(LLVMJitContext *context, fmgr_symbol(fcinfo->flinfo->fn_oid, &modname, &basename); - if (modname != NULL && basename != NULL) + Assert(basename != NULL); + + if (modname != NULL) { /* external function in loadable library */ funcname = psprintf("pgextern.%s.%s", modname, basename); } - else if (basename != NULL) + else { /* internal function */ funcname = psprintf("%s", basename); } - else - { - /* - * Function we don't know to handle, return pointer. We do so by - * creating a global constant containing a pointer to the function. - * Makes IR more readable. - */ - LLVMValueRef v_fn_addr; - - funcname = psprintf("pgoidextern.%u", - fcinfo->flinfo->fn_oid); - v_fn = LLVMGetNamedGlobal(mod, funcname); - if (v_fn != 0) - return LLVMBuildLoad(builder, v_fn, ""); - - v_fn_addr = l_ptr_const(fcinfo->flinfo->fn_addr, TypePGFunction); - - v_fn = LLVMAddGlobal(mod, TypePGFunction, funcname); - LLVMSetInitializer(v_fn, v_fn_addr); - LLVMSetGlobalConstant(v_fn, true); - - return LLVMBuildLoad(builder, v_fn, ""); - } /* check if function already has been added */ v_fn = LLVMGetNamedFunction(mod, funcname); diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c index 2b4226d3a8..fd967346d0 100644 --- a/src/backend/utils/fmgr/fmgr.c +++ b/src/backend/utils/fmgr/fmgr.c @@ -265,15 +265,15 @@ fmgr_info_cxt_security(Oid functionId, FmgrInfo *finfo, MemoryContext mcxt, /* * Return module and C function name providing implementation of functionId. * - * If *mod == NULL and *fn == NULL, no C symbol is known to implement - * function. - * * If *mod == NULL and *fn != NULL, the function is implemented by a symbol in * the main binary. * * If *mod != NULL and *fn !=NULL the function is implemented in an extension * shared object. * + * If functionId references a PL function, mod and fn will point to the PL + * handler's shared object and function name. + * * The returned module and function names are pstrdup'ed into the current * memory context. */ @@ -285,6 +285,11 @@ fmgr_symbol(Oid functionId, char **mod, char **fn) bool isnull; Datum prosrcattr; Datum probinattr; + Datum pronameattr; + Oid language; + HeapTuple languageTuple; + Form_pg_language languageStruct; + HeapTuple plhandlerTuple; /* Otherwise we need the pg_proc entry */ procedureTuple = SearchSysCache1(PROCOID, ObjectIdGetDatum(functionId)); @@ -304,8 +309,9 @@ fmgr_symbol(Oid functionId, char **mod, char **fn) return; } + language = procedureStruct->prolang; /* see fmgr_info_cxt_security for the individual cases */ - switch (procedureStruct->prolang) + switch (language) { case INTERNALlanguageId: prosrcattr = SysCacheGetAttr(PROCOID, procedureTuple, @@ -342,9 +348,34 @@ fmgr_symbol(Oid functionId, char **mod, char **fn) break; default: - *mod = NULL; - *fn = NULL; /* unknown, pass pointer */ - break; + /* + * We referenced a PL function. Return PL handler's module and C + * function name. + */ + languageTuple = SearchSysCache1(LANGOID, + ObjectIdGetDatum(language)); + if (!HeapTupleIsValid(languageTuple)) + elog(ERROR, "cache lookup failed for language %u", language); + languageStruct = (Form_pg_language) GETSTRUCT(languageTuple); + plhandlerTuple = SearchSysCache1(PROCOID, + ObjectIdGetDatum(languageStruct->lanplcallfoid)); + if (!HeapTupleIsValid(plhandlerTuple)) + elog(ERROR, "cache lookup failed for function %u", languageStruct->lanplcallfoid); + + probinattr = SysCacheGetAttr(PROCOID, plhandlerTuple, + Anum_pg_proc_probin, &isnull); + if (isnull) + *mod = NULL; + else + *mod = TextDatumGetCString(probinattr); + + pronameattr = SysCacheGetAttr(PROCOID, plhandlerTuple, + Anum_pg_proc_proname, &isnull); + Assert(!isnull); + *fn = pstrdup(NameStr(*(DatumGetName(pronameattr)))); + + ReleaseSysCache(languageTuple); + ReleaseSysCache(plhandlerTuple); } ReleaseSysCache(procedureTuple); -- 2.24.1