From a90c150c7c3e9dc42902e6e42ec91f6fe2657d44 Mon Sep 17 00:00:00 2001
From: soumyadeep2007 <sochakraborty@pivotal.io>
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

