Hi,

While prototyping codegen improvements for JITed expression evaluation,
I once more hit the issue that the FunctionCallInfoData structs are
really large (936 bytes), despite arguments beyond the fourth barely
every being used.  I think we should fix that.

What I think we should do is convert
FunctionCallInfoData->{arg,argisnull} into an array of NullableDatum
(new type, a struct of Datum and bool), and then use a variable length
array for the arguments.  In the super common case of 2 arguments that
reduces the size of the array from 936 to 64 bytes.  Besides the size
reduction this also noticably reduces the number of cachelines accessed
- before it's absolutely guaranteed that the arg and argnull arrays for
the same argument aren't on the same cacheline, after it's almost
guaranteed to be the case.

Attached is a *PROTOTYPE* patch doing so.  Note I was too lazy to fully
fix up the jit code, I didn't want to do the legwork before we've some
agreement on this.  We also can get rid of FUNC_MAX_ARGS after this, but
there's surrounding code that still relies on it.

There's some added uglyness, which I hope we can polish a bit
further. Right now we allocate a good number of FunctionCallInfoData
struct on the stack - which doesn't quite work afterwards anymore.  So
the stack allocations, for the majoroity cases where the argument number
is known, currently looks like:

        union {
                FunctionCallInfoData fcinfo;
                char *fcinfo_data[SizeForFunctionCallInfoData(0)];
        } fcinfodata;
        FunctionCallInfo fcinfo = &fcinfodata.fcinfo;

that's not pretty, but also not that bad.

It's a bit unfortunate that this'll break some extensions, but I don't
really see a way around that.  The current approach, to me, clearly
doesn't have a future.  I wonder if we should add a bunch of accessor
macros / inline functions that we (or extension authors) can backpatch
to reduce the pain of maintaining different code paths.

Besides the change here, I think we should also go much further with the
conversion to NullableDatum.  There's two main areas of change: I want
to move the execExpr.c related code so steps return data into
NullableDatums - that removes a good chunk of pointer dereferences and
allocations. Secondly I think we should move TupleTableSlot to this
format - the issue with nulls / datums being on separate cachelines is
noticeable in profiles, but more importantly the code looks more
consistent with it.


As an example for the difference in memory usage, here's the memory
consumption at ExecutorRun time, for TPCH's Q01:

master:
TopPortalContext: 8192 total in 1 blocks; 7664 free (0 chunks); 528 used
  PortalContext: 1024 total in 1 blocks; 576 free (0 chunks); 448 used:
    ExecutorState: 90744 total in 5 blocks; 31568 free (2 chunks); 59176 used
      ExprContext: 8192 total in 1 blocks; 7936 free (0 chunks); 256 used
      ExprContext: 8192 total in 1 blocks; 7936 free (0 chunks); 256 used
      ExprContext: 8192 total in 1 blocks; 7936 free (0 chunks); 256 used
      ExprContext: 8192 total in 1 blocks; 3488 free (0 chunks); 4704 used
      ExprContext: 8192 total in 1 blocks; 7936 free (0 chunks); 256 used
      ExprContext: 8192 total in 1 blocks; 7936 free (0 chunks); 256 used
Grand total: 149112 bytes in 13 blocks; 82976 free (2 chunks); 66136 used

patch:
TopPortalContext: 8192 total in 1 blocks; 7664 free (0 chunks); 528 used
  PortalContext: 1024 total in 1 blocks; 576 free (0 chunks); 448 used:
    ExecutorState: 65536 total in 4 blocks; 33536 free (6 chunks); 32000 used
      ExprContext: 8192 total in 1 blocks; 7936 free (0 chunks); 256 used
      ExprContext: 8192 total in 1 blocks; 7936 free (0 chunks); 256 used
      ExprContext: 8192 total in 1 blocks; 7936 free (0 chunks); 256 used
      ExprContext: 8192 total in 1 blocks; 5408 free (0 chunks); 2784 used
      ExprContext: 8192 total in 1 blocks; 7936 free (0 chunks); 256 used
      ExprContext: 8192 total in 1 blocks; 7936 free (0 chunks); 256 used
Grand total: 123904 bytes in 12 blocks; 86864 free (6 chunks); 37040 used

As you can see, the ExecutorState context uses nearly half the amount of
memory as before. In a lot of cases a good chunk of the benefit is going
to be hidden due to memory context sizing, but I'd expect that to matter
much less for more complex statements and plpgsql functions etc.

Comments?

Greetings,

Andres Freund
>From 50ac86917da52cbab61cffaabb1d443184b3aa87 Mon Sep 17 00:00:00 2001
From: Andres Freund <and...@anarazel.de>
Date: Tue, 5 Jun 2018 10:24:31 -0700
Subject: [PATCH v1] Variable length FunctionCallInfoData

Author: Andres Freund
Reviewed-By:
Discussion: https://postgr.es/m/
Backpatch:
---
 src/backend/commands/event_trigger.c  |  12 +-
 src/backend/commands/functioncmds.c   |  16 +-
 src/backend/commands/tablecmds.c      |  12 +-
 src/backend/commands/trigger.c        |  16 +-
 src/backend/executor/execExpr.c       |  81 +--
 src/backend/executor/execExprInterp.c | 131 ++--
 src/backend/executor/execSRF.c        |  42 +-
 src/backend/executor/functions.c      |   4 +-
 src/backend/executor/nodeAgg.c        |  74 ++-
 src/backend/executor/nodeWindowAgg.c  |  80 ++-
 src/backend/jit/llvm/llvmjit_expr.c   |  20 +-
 src/backend/tcop/fastpath.c           |  47 +-
 src/backend/utils/adt/arrayfuncs.c    | 153 +++--
 src/backend/utils/adt/int.c           |  23 +-
 src/backend/utils/adt/oid.c           |  23 +-
 src/backend/utils/adt/rowtypes.c      |  38 +-
 src/backend/utils/fmgr/fmgr.c         | 917 ++++++++++++--------------
 src/backend/utils/sort/sortsupport.c  |  13 +-
 src/include/executor/execExpr.h       |   6 +-
 src/include/executor/nodeAgg.h        |   6 +-
 src/include/fmgr.h                    |  15 +-
 src/include/nodes/execnodes.h         |   2 +-
 src/include/postgres.h                |   7 +
 src/pl/plperl/plperl.c                |  24 +-
 src/pl/plpgsql/src/pl_exec.c          |   8 +-
 src/pl/plpython/plpy_exec.c           |   4 +-
 src/pl/tcl/pltcl.c                    |  21 +-
 27 files changed, 912 insertions(+), 883 deletions(-)

diff --git a/src/backend/commands/event_trigger.c b/src/backend/commands/event_trigger.c
index eecc85d14e5..46af596fa18 100644
--- a/src/backend/commands/event_trigger.c
+++ b/src/backend/commands/event_trigger.c
@@ -1050,7 +1050,11 @@ EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata)
 	{
 		Oid			fnoid = lfirst_oid(lc);
 		FmgrInfo	flinfo;
-		FunctionCallInfoData fcinfo;
+		union {
+			FunctionCallInfoData fcinfo;
+			char *fcinfo_data[SizeForFunctionCallInfoData(0)];
+		} fcinfodata;
+		FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
 		PgStat_FunctionCallUsage fcusage;
 
 		elog(DEBUG1, "EventTriggerInvoke %u", fnoid);
@@ -1070,10 +1074,10 @@ EventTriggerInvoke(List *fn_oid_list, EventTriggerData *trigdata)
 		fmgr_info(fnoid, &flinfo);
 
 		/* Call the function, passing no arguments but setting a context. */
-		InitFunctionCallInfoData(fcinfo, &flinfo, 0,
+		InitFunctionCallInfoData(*fcinfo, &flinfo, 0,
 								 InvalidOid, (Node *) trigdata, NULL);
-		pgstat_init_function_usage(&fcinfo, &fcusage);
-		FunctionCallInvoke(&fcinfo);
+		pgstat_init_function_usage(fcinfo, &fcusage);
+		FunctionCallInvoke(fcinfo);
 		pgstat_end_function_usage(&fcusage, true);
 
 		/* Reclaim memory. */
diff --git a/src/backend/commands/functioncmds.c b/src/backend/commands/functioncmds.c
index 8864d9ae446..0e52997e95e 100644
--- a/src/backend/commands/functioncmds.c
+++ b/src/backend/commands/functioncmds.c
@@ -2213,7 +2213,11 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
 	int			i;
 	AclResult	aclresult;
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} fcinfodata;
+	FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
 	CallContext *callcontext;
 	EState	   *estate;
 	ExprContext *econtext;
@@ -2264,7 +2268,7 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
 	/* Initialize function call structure */
 	InvokeFunctionExecuteHook(fexpr->funcid);
 	fmgr_info(fexpr->funcid, &flinfo);
-	InitFunctionCallInfoData(fcinfo, &flinfo, nargs, fexpr->inputcollid, (Node *) callcontext, NULL);
+	InitFunctionCallInfoData(*fcinfo, &flinfo, nargs, fexpr->inputcollid, (Node *) callcontext, NULL);
 
 	/*
 	 * Evaluate procedure arguments inside a suitable execution context.  Note
@@ -2285,13 +2289,13 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
 
 		val = ExecEvalExprSwitchContext(exprstate, econtext, &isnull);
 
-		fcinfo.arg[i] = val;
-		fcinfo.argnull[i] = isnull;
+		fcinfo->args[i].datum = val;
+		fcinfo->args[i].isnull = isnull;
 
 		i++;
 	}
 
-	retval = FunctionCallInvoke(&fcinfo);
+	retval = FunctionCallInvoke(fcinfo);
 
 	if (fexpr->funcresulttype == VOIDOID)
 	{
@@ -2311,7 +2315,7 @@ ExecuteCallStmt(CallStmt *stmt, ParamListInfo params, bool atomic, DestReceiver
 		TupOutputState *tstate;
 		TupleTableSlot *slot;
 
-		if (fcinfo.isnull)
+		if (fcinfo->isnull)
 			elog(ERROR, "procedure returned null record");
 
 		td = DatumGetHeapTupleHeader(retval);
diff --git a/src/backend/commands/tablecmds.c b/src/backend/commands/tablecmds.c
index 0e95037dcf4..97c54a6ff80 100644
--- a/src/backend/commands/tablecmds.c
+++ b/src/backend/commands/tablecmds.c
@@ -8556,7 +8556,11 @@ validateForeignKeyConstraint(char *conname,
 
 	while ((tuple = heap_getnext(scan, ForwardScanDirection)) != NULL)
 	{
-		FunctionCallInfoData fcinfo;
+		union {
+			FunctionCallInfoData fcinfo;
+			char *fcinfo_data[SizeForFunctionCallInfoData(0)];
+		} fcinfodata;
+		FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
 		TriggerData trigdata;
 
 		/*
@@ -8564,7 +8568,7 @@ validateForeignKeyConstraint(char *conname,
 		 *
 		 * No parameters are passed, but we do set a context
 		 */
-		MemSet(&fcinfo, 0, sizeof(fcinfo));
+		MemSet(&fcinfodata, 0, sizeof(fcinfodata));
 
 		/*
 		 * We assume RI_FKey_check_ins won't look at flinfo...
@@ -8578,9 +8582,9 @@ validateForeignKeyConstraint(char *conname,
 		trigdata.tg_trigtuplebuf = scan->rs_cbuf;
 		trigdata.tg_newtuplebuf = InvalidBuffer;
 
-		fcinfo.context = (Node *) &trigdata;
+		fcinfo->context = (Node *) &trigdata;
 
-		RI_FKey_check_ins(&fcinfo);
+		RI_FKey_check_ins(fcinfo);
 	}
 
 	heap_endscan(scan);
diff --git a/src/backend/commands/trigger.c b/src/backend/commands/trigger.c
index 57519fe8d64..f6059e43908 100644
--- a/src/backend/commands/trigger.c
+++ b/src/backend/commands/trigger.c
@@ -2356,7 +2356,11 @@ ExecCallTriggerFunc(TriggerData *trigdata,
 					Instrumentation *instr,
 					MemoryContext per_tuple_context)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(0)];
+	} fcinfodata;
+	FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
 	PgStat_FunctionCallUsage fcusage;
 	Datum		result;
 	MemoryContext oldContext;
@@ -2401,15 +2405,15 @@ ExecCallTriggerFunc(TriggerData *trigdata,
 	/*
 	 * Call the function, passing no arguments but setting a context.
 	 */
-	InitFunctionCallInfoData(fcinfo, finfo, 0,
+	InitFunctionCallInfoData(*fcinfo, finfo, 0,
 							 InvalidOid, (Node *) trigdata, NULL);
 
-	pgstat_init_function_usage(&fcinfo, &fcusage);
+	pgstat_init_function_usage(fcinfo, &fcusage);
 
 	MyTriggerDepth++;
 	PG_TRY();
 	{
-		result = FunctionCallInvoke(&fcinfo);
+		result = FunctionCallInvoke(fcinfo);
 	}
 	PG_CATCH();
 	{
@@ -2427,11 +2431,11 @@ ExecCallTriggerFunc(TriggerData *trigdata,
 	 * Trigger protocol allows function to return a null pointer, but NOT to
 	 * set the isnull result flag.
 	 */
-	if (fcinfo.isnull)
+	if (fcinfo->isnull)
 		ereport(ERROR,
 				(errcode(ERRCODE_E_R_I_E_TRIGGER_PROTOCOL_VIOLATED),
 				 errmsg("trigger function %u returned null value",
-						fcinfo.flinfo->fn_oid)));
+						fcinfo->flinfo->fn_oid)));
 
 	/*
 	 * If doing EXPLAIN ANALYZE, stop charging time to this trigger, and count
diff --git a/src/backend/executor/execExpr.c b/src/backend/executor/execExpr.c
index 67ebe0f6967..d3c606f3c11 100644
--- a/src/backend/executor/execExpr.c
+++ b/src/backend/executor/execExpr.c
@@ -970,7 +970,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				/* Set up the primary fmgr lookup information */
 				finfo = palloc0(sizeof(FmgrInfo));
-				fcinfo = palloc0(sizeof(FunctionCallInfoData));
+				fcinfo = palloc0(SizeForFunctionCallInfoData(2));
 				fmgr_info(opexpr->opfuncid, finfo);
 				fmgr_info_set_expr((Node *) node, finfo);
 				InitFunctionCallInfoData(*fcinfo, finfo, 2,
@@ -978,7 +978,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				/* Evaluate scalar directly into left function argument */
 				ExecInitExprRec(scalararg, state,
-								&fcinfo->arg[0], &fcinfo->argnull[0]);
+								&fcinfo->args[0].datum, &fcinfo->args[0].isnull);
 
 				/*
 				 * Evaluate array argument into our return value.  There's no
@@ -1267,7 +1267,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				/* lookup the source type's output function */
 				scratch.d.iocoerce.finfo_out = palloc0(sizeof(FmgrInfo));
-				scratch.d.iocoerce.fcinfo_data_out = palloc0(sizeof(FunctionCallInfoData));
+				scratch.d.iocoerce.fcinfo_data_out = palloc0(SizeForFunctionCallInfoData(1));
 
 				getTypeOutputInfo(exprType((Node *) iocoerce->arg),
 								  &iofunc, &typisvarlena);
@@ -1279,7 +1279,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				/* lookup the result type's input function */
 				scratch.d.iocoerce.finfo_in = palloc0(sizeof(FmgrInfo));
-				scratch.d.iocoerce.fcinfo_data_in = palloc0(sizeof(FunctionCallInfoData));
+				scratch.d.iocoerce.fcinfo_data_in = palloc0(SizeForFunctionCallInfoData(3));
 
 				getTypeInputInfo(iocoerce->resulttype,
 								 &iofunc, &typioparam);
@@ -1294,10 +1294,10 @@ ExecInitExprRec(Expr *node, ExprState *state,
 				 * function, since they're constants.
 				 */
 				fcinfo_in = scratch.d.iocoerce.fcinfo_data_in;
-				fcinfo_in->arg[1] = ObjectIdGetDatum(typioparam);
-				fcinfo_in->argnull[1] = false;
-				fcinfo_in->arg[2] = Int32GetDatum(-1);
-				fcinfo_in->argnull[2] = false;
+				fcinfo_in->args[1].datum = ObjectIdGetDatum(typioparam);
+				fcinfo_in->args[1].isnull = false;
+				fcinfo_in->args[2].datum = Int32GetDatum(-1);
+				fcinfo_in->args[2].isnull = false;
 
 				ExprEvalPushStep(state, &scratch);
 				break;
@@ -1738,7 +1738,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 					/* Set up the primary fmgr lookup information */
 					finfo = palloc0(sizeof(FmgrInfo));
-					fcinfo = palloc0(sizeof(FunctionCallInfoData));
+					fcinfo = palloc0(SizeForFunctionCallInfoData(2));
 					fmgr_info(proc, finfo);
 					fmgr_info_set_expr((Node *) node, finfo);
 					InitFunctionCallInfoData(*fcinfo, finfo, 2,
@@ -1753,9 +1753,9 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 					/* evaluate left and right args directly into fcinfo */
 					ExecInitExprRec(left_expr, state,
-									&fcinfo->arg[0], &fcinfo->argnull[0]);
+									&fcinfo->args[0].datum, &fcinfo->args[0].isnull);
 					ExecInitExprRec(right_expr, state,
-									&fcinfo->arg[1], &fcinfo->argnull[1]);
+									&fcinfo->args[1].datum, &fcinfo->args[1].isnull);
 
 					scratch.opcode = EEOP_ROWCOMPARE_STEP;
 					scratch.d.rowcompare_step.finfo = finfo;
@@ -1881,7 +1881,7 @@ ExecInitExprRec(Expr *node, ExprState *state,
 
 				/* Perform function lookup */
 				finfo = palloc0(sizeof(FmgrInfo));
-				fcinfo = palloc0(sizeof(FunctionCallInfoData));
+				fcinfo = palloc0(SizeForFunctionCallInfoData(2));
 				fmgr_info(typentry->cmp_proc, finfo);
 				fmgr_info_set_expr((Node *) node, finfo);
 				InitFunctionCallInfoData(*fcinfo, finfo, 2,
@@ -2190,7 +2190,7 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
 
 	/* Allocate function lookup data and parameter workspace for this call */
 	scratch->d.func.finfo = palloc0(sizeof(FmgrInfo));
-	scratch->d.func.fcinfo_data = palloc0(sizeof(FunctionCallInfoData));
+	scratch->d.func.fcinfo_data = palloc0(SizeForFunctionCallInfoData(nargs));
 	flinfo = scratch->d.func.finfo;
 	fcinfo = scratch->d.func.fcinfo_data;
 
@@ -2229,13 +2229,14 @@ ExecInitFunc(ExprEvalStep *scratch, Expr *node, List *args, Oid funcid,
 			 */
 			Const	   *con = (Const *) arg;
 
-			fcinfo->arg[argno] = con->constvalue;
-			fcinfo->argnull[argno] = con->constisnull;
+			fcinfo->args[argno].datum = con->constvalue;
+			fcinfo->args[argno].isnull = con->constisnull;
 		}
 		else
 		{
 			ExecInitExprRec(arg, state,
-							&fcinfo->arg[argno], &fcinfo->argnull[argno]);
+							&fcinfo->args[argno].datum,
+							&fcinfo->args[argno].isnull);
 		}
 		argno++;
 	}
@@ -2868,10 +2869,11 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
 		int			numInputs = pertrans->numInputs;
 		int			argno;
 		int			setno;
-		FunctionCallInfo trans_fcinfo = &pertrans->transfn_fcinfo;
+		FunctionCallInfo trans_fcinfo = pertrans->transfn_fcinfo;
 		ListCell   *arg;
 		ListCell   *bail;
 		List	   *adjust_bailout = NIL;
+		NullableDatum   *strictargs = NULL;
 		bool	   *strictnulls = NULL;
 
 		/*
@@ -2909,7 +2911,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
 			Assert(pertrans->numSortCols == 0);
 			Assert(list_length(pertrans->aggref->args) == 1);
 
-			strictnulls = trans_fcinfo->argnull + 1;
+			strictargs = trans_fcinfo->args + 1;
 			source_tle = (TargetEntry *) linitial(pertrans->aggref->args);
 
 			/*
@@ -2923,21 +2925,21 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
 				 * value
 				 */
 				ExecInitExprRec(source_tle->expr, state,
-								&trans_fcinfo->arg[argno + 1],
-								&trans_fcinfo->argnull[argno + 1]);
+								&trans_fcinfo->args[argno + 1].datum,
+								&trans_fcinfo->args[argno + 1].isnull);
 			}
 			else
 			{
-				FunctionCallInfo ds_fcinfo = &pertrans->deserialfn_fcinfo;
+				FunctionCallInfo ds_fcinfo = pertrans->deserialfn_fcinfo;
 
 				/* evaluate argument */
 				ExecInitExprRec(source_tle->expr, state,
-								&ds_fcinfo->arg[0],
-								&ds_fcinfo->argnull[0]);
+								&ds_fcinfo->args[0].datum,
+								&ds_fcinfo->args[0].isnull);
 
 				/* Dummy second argument for type-safety reasons */
-				ds_fcinfo->arg[1] = PointerGetDatum(NULL);
-				ds_fcinfo->argnull[1] = false;
+				ds_fcinfo->args[1].datum = PointerGetDatum(NULL);
+				ds_fcinfo->args[1].isnull = false;
 
 				/*
 				 * Don't call a strict deserialization function with NULL
@@ -2951,8 +2953,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
 				scratch.d.agg_deserialize.aggstate = aggstate;
 				scratch.d.agg_deserialize.fcinfo_data = ds_fcinfo;
 				scratch.d.agg_deserialize.jumpnull = -1;	/* adjust later */
-				scratch.resvalue = &trans_fcinfo->arg[argno + 1];
-				scratch.resnull = &trans_fcinfo->argnull[argno + 1];
+				scratch.resvalue = &trans_fcinfo->args[argno + 1].datum;
+				scratch.resnull = &trans_fcinfo->args[argno + 1].isnull;
 
 				ExprEvalPushStep(state, &scratch);
 				adjust_bailout = lappend_int(adjust_bailout,
@@ -2969,7 +2971,7 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
 			/*
 			 * Normal transition function without ORDER BY / DISTINCT.
 			 */
-			strictnulls = trans_fcinfo->argnull + 1;
+			strictargs = trans_fcinfo->args + 1;
 
 			foreach(arg, pertrans->aggref->args)
 			{
@@ -2980,8 +2982,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
 				 * value
 				 */
 				ExecInitExprRec(source_tle->expr, state,
-								&trans_fcinfo->arg[argno + 1],
-								&trans_fcinfo->argnull[argno + 1]);
+								&trans_fcinfo->args[argno + 1].datum,
+								&trans_fcinfo->args[argno + 1].isnull);
 				argno++;
 			}
 		}
@@ -3029,8 +3031,12 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
 		 */
 		if (trans_fcinfo->flinfo->fn_strict && numInputs > 0)
 		{
-			scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK;
+			if (strictnulls)
+				scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_NULLS;
+			else
+				scratch.opcode = EEOP_AGG_STRICT_INPUT_CHECK_ARGS;
 			scratch.d.agg_strict_input_check.nulls = strictnulls;
+			scratch.d.agg_strict_input_check.args = strictargs;
 			scratch.d.agg_strict_input_check.jumpnull = -1; /* adjust later */
 			scratch.d.agg_strict_input_check.nargs = numInputs;
 			ExprEvalPushStep(state, &scratch);
@@ -3084,7 +3090,8 @@ ExecBuildAggTrans(AggState *aggstate, AggStatePerPhase phase,
 				Assert(as->d.jump.jumpdone == -1);
 				as->d.jump.jumpdone = state->steps_len;
 			}
-			else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK)
+			else if (as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_ARGS ||
+					 as->opcode == EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
 			{
 				Assert(as->d.agg_strict_input_check.jumpnull == -1);
 				as->d.agg_strict_input_check.jumpnull = state->steps_len;
@@ -3289,7 +3296,7 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
 
 		/* Set up the primary fmgr lookup information */
 		finfo = palloc0(sizeof(FmgrInfo));
-		fcinfo = palloc0(sizeof(FunctionCallInfoData));
+		fcinfo = palloc0(SizeForFunctionCallInfoData(2));
 		fmgr_info(foid, finfo);
 		fmgr_info_set_expr(NULL, finfo);
 		InitFunctionCallInfoData(*fcinfo, finfo, 2,
@@ -3299,16 +3306,16 @@ ExecBuildGroupingEqual(TupleDesc ldesc, TupleDesc rdesc,
 		scratch.opcode = EEOP_INNER_VAR;
 		scratch.d.var.attnum = attno - 1;
 		scratch.d.var.vartype = latt->atttypid;
-		scratch.resvalue = &fcinfo->arg[0];
-		scratch.resnull = &fcinfo->argnull[0];
+		scratch.resvalue = &fcinfo->args[0].datum;
+		scratch.resnull = &fcinfo->args[0].isnull;
 		ExprEvalPushStep(state, &scratch);
 
 		/* right arg */
 		scratch.opcode = EEOP_OUTER_VAR;
 		scratch.d.var.attnum = attno - 1;
 		scratch.d.var.vartype = ratt->atttypid;
-		scratch.resvalue = &fcinfo->arg[1];
-		scratch.resnull = &fcinfo->argnull[1];
+		scratch.resvalue = &fcinfo->args[1].datum;
+		scratch.resnull = &fcinfo->args[1].isnull;
 		ExprEvalPushStep(state, &scratch);
 
 		/* evaluate distinctness */
diff --git a/src/backend/executor/execExprInterp.c b/src/backend/executor/execExprInterp.c
index 76ad078fe66..9207becc1b2 100644
--- a/src/backend/executor/execExprInterp.c
+++ b/src/backend/executor/execExprInterp.c
@@ -386,7 +386,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 		&&CASE_EEOP_ALTERNATIVE_SUBPLAN,
 		&&CASE_EEOP_AGG_STRICT_DESERIALIZE,
 		&&CASE_EEOP_AGG_DESERIALIZE,
-		&&CASE_EEOP_AGG_STRICT_INPUT_CHECK,
+		&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
+		&&CASE_EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
 		&&CASE_EEOP_AGG_INIT_TRANS,
 		&&CASE_EEOP_AGG_STRICT_TRANS_CHECK,
 		&&CASE_EEOP_AGG_PLAIN_TRANS_BYVAL,
@@ -661,14 +662,14 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 		EEO_CASE(EEOP_FUNCEXPR_STRICT)
 		{
 			FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
-			bool	   *argnull = fcinfo->argnull;
+			NullableDatum *args = fcinfo->args;
 			int			argno;
 			Datum		d;
 
 			/* strict function, so check for NULL args */
 			for (argno = 0; argno < op->d.func.nargs; argno++)
 			{
-				if (argnull[argno])
+				if (args[argno].isnull)
 				{
 					*op->resnull = true;
 					goto strictfail;
@@ -1084,8 +1085,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 				FunctionCallInfo fcinfo_out;
 
 				fcinfo_out = op->d.iocoerce.fcinfo_data_out;
-				fcinfo_out->arg[0] = *op->resvalue;
-				fcinfo_out->argnull[0] = false;
+				fcinfo_out->args[0].datum = *op->resvalue;
+				fcinfo_out->args[0].isnull = false;
 
 				fcinfo_out->isnull = false;
 				str = DatumGetCString(FunctionCallInvoke(fcinfo_out));
@@ -1101,8 +1102,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 				Datum		d;
 
 				fcinfo_in = op->d.iocoerce.fcinfo_data_in;
-				fcinfo_in->arg[0] = PointerGetDatum(str);
-				fcinfo_in->argnull[0] = *op->resnull;
+				fcinfo_in->args[0].datum = PointerGetDatum(str);
+				fcinfo_in->args[0].isnull = *op->resnull;
 				/* second and third arguments are already set up */
 
 				fcinfo_in->isnull = false;
@@ -1139,13 +1140,13 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
 
 			/* check function arguments for NULLness */
-			if (fcinfo->argnull[0] && fcinfo->argnull[1])
+			if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
 			{
 				/* Both NULL? Then is not distinct... */
 				*op->resvalue = BoolGetDatum(false);
 				*op->resnull = false;
 			}
-			else if (fcinfo->argnull[0] || fcinfo->argnull[1])
+			else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
 			{
 				/* Only one is NULL? Then is distinct... */
 				*op->resvalue = BoolGetDatum(true);
@@ -1171,12 +1172,12 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 		{
 			FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
 
-			if (fcinfo->argnull[0] && fcinfo->argnull[1])
+			if (fcinfo->args[0].isnull && fcinfo->args[1].isnull)
 			{
 				*op->resvalue = BoolGetDatum(true);
 				*op->resnull = false;
 			}
-			else if (fcinfo->argnull[0] || fcinfo->argnull[1])
+			else if (fcinfo->args[0].isnull || fcinfo->args[1].isnull)
 			{
 				*op->resvalue = BoolGetDatum(false);
 				*op->resnull = false;
@@ -1202,7 +1203,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
 
 			/* if either argument is NULL they can't be equal */
-			if (!fcinfo->argnull[0] && !fcinfo->argnull[1])
+			if (!fcinfo->args[0].isnull && !fcinfo->args[1].isnull)
 			{
 				Datum		result;
 
@@ -1220,8 +1221,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			}
 
 			/* Arguments aren't equal, so return the first one */
-			*op->resvalue = fcinfo->arg[0];
-			*op->resnull = fcinfo->argnull[0];
+			*op->resvalue = fcinfo->args[0].datum;
+			*op->resnull = fcinfo->args[0].isnull;
 
 			EEO_NEXT();
 		}
@@ -1287,7 +1288,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 
 			/* force NULL result if strict fn and NULL input */
 			if (op->d.rowcompare_step.finfo->fn_strict &&
-				(fcinfo->argnull[0] || fcinfo->argnull[1]))
+				(fcinfo->args[0].isnull || fcinfo->args[1].isnull))
 			{
 				*op->resnull = true;
 				EEO_JUMP(op->d.rowcompare_step.jumpnull);
@@ -1526,10 +1527,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 		/* evaluate a strict aggregate deserialization function */
 		EEO_CASE(EEOP_AGG_STRICT_DESERIALIZE)
 		{
-			bool	   *argnull = op->d.agg_deserialize.fcinfo_data->argnull;
-
 			/* Don't call a strict deserialization function with NULL input */
-			if (argnull[0])
+			if (op->d.agg_deserialize.fcinfo_data->args[0].isnull)
 				EEO_JUMP(op->d.agg_deserialize.jumpnull);
 
 			/* fallthrough */
@@ -1559,15 +1558,29 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 		 * Check that a strict aggregate transition / combination function's
 		 * input is not NULL.
 		 */
-		EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK)
+		EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_ARGS)
 		{
 			int			argno;
-			bool	   *nulls = op->d.agg_strict_input_check.nulls;
+			NullableDatum *args = op->d.agg_strict_input_check.args;
 			int			nargs = op->d.agg_strict_input_check.nargs;
 
 			for (argno = 0; argno < nargs; argno++)
 			{
-				if (nulls[argno])
+				if (args[argno].isnull)
+					EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
+			}
+			EEO_NEXT();
+		}
+
+		EEO_CASE(EEOP_AGG_STRICT_INPUT_CHECK_NULLS)
+		{
+			int			argno;
+			bool		*isnull = op->d.agg_strict_input_check.nulls;
+			int			nargs = op->d.agg_strict_input_check.nargs;
+
+			for (argno = 0; argno < nargs; argno++)
+			{
+				if (isnull[argno])
 					EEO_JUMP(op->d.agg_strict_input_check.jumpnull);
 			}
 			EEO_NEXT();
@@ -1643,7 +1656,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 
 			Assert(pertrans->transtypeByVal);
 
-			fcinfo = &pertrans->transfn_fcinfo;
+			fcinfo = pertrans->transfn_fcinfo;
 
 			/* cf. select_current_set() */
 			aggstate->curaggcontext = op->d.agg_trans.aggcontext;
@@ -1655,8 +1668,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			/* invoke transition function in per-tuple context */
 			oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
 
-			fcinfo->arg[0] = pergroup->transValue;
-			fcinfo->argnull[0] = pergroup->transValueIsNull;
+			fcinfo->args[0].datum = pergroup->transValue;
+			fcinfo->args[0].isnull = pergroup->transValueIsNull;
 			fcinfo->isnull = false; /* just in case transfn doesn't set it */
 
 			newVal = FunctionCallInvoke(fcinfo);
@@ -1694,7 +1707,7 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 
 			Assert(!pertrans->transtypeByVal);
 
-			fcinfo = &pertrans->transfn_fcinfo;
+			fcinfo = pertrans->transfn_fcinfo;
 
 			/* cf. select_current_set() */
 			aggstate->curaggcontext = op->d.agg_trans.aggcontext;
@@ -1706,8 +1719,8 @@ ExecInterpExpr(ExprState *state, ExprContext *econtext, bool *isnull)
 			/* invoke transition function in per-tuple context */
 			oldContext = MemoryContextSwitchTo(aggstate->tmpcontext->ecxt_per_tuple_memory);
 
-			fcinfo->arg[0] = pergroup->transValue;
-			fcinfo->argnull[0] = pergroup->transValueIsNull;
+			fcinfo->args[0].datum = pergroup->transValue;
+			fcinfo->args[0].isnull = pergroup->transValueIsNull;
 			fcinfo->isnull = false; /* just in case transfn doesn't set it */
 
 			newVal = FunctionCallInvoke(fcinfo);
@@ -2060,7 +2073,7 @@ ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
 {
 	ExprEvalStep *op = &state->steps[0];
 	FunctionCallInfo fcinfo;
-	bool	   *argnull;
+	NullableDatum *args;
 	int			argno;
 	Datum		d;
 
@@ -2074,12 +2087,12 @@ ExecJustApplyFuncToCase(ExprState *state, ExprContext *econtext, bool *isnull)
 	op++;
 
 	fcinfo = op->d.func.fcinfo_data;
-	argnull = fcinfo->argnull;
+	args = fcinfo->args;
 
 	/* strict function, so check for NULL args */
 	for (argno = 0; argno < op->d.func.nargs; argno++)
 	{
-		if (argnull[argno])
+		if (args[argno].isnull)
 		{
 			*isnull = true;
 			return (Datum) 0;
@@ -2205,14 +2218,14 @@ ExecEvalFuncExprStrictFusage(ExprState *state, ExprEvalStep *op,
 
 	FunctionCallInfo fcinfo = op->d.func.fcinfo_data;
 	PgStat_FunctionCallUsage fcusage;
-	bool	   *argnull = fcinfo->argnull;
+	NullableDatum *args = fcinfo->args;
 	int			argno;
 	Datum		d;
 
 	/* strict function, so check for NULL args */
 	for (argno = 0; argno < op->d.func.nargs; argno++)
 	{
-		if (argnull[argno])
+		if (args[argno].isnull)
 		{
 			*op->resnull = true;
 			return;
@@ -2330,7 +2343,11 @@ void
 ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
 {
 	SQLValueFunction *svf = op->d.sqlvaluefunction.svf;
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(0)];
+	} fcinfodata;
+	FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
 
 	*op->resnull = false;
 
@@ -2362,24 +2379,24 @@ ExecEvalSQLValueFunction(ExprState *state, ExprEvalStep *op)
 		case SVFOP_CURRENT_ROLE:
 		case SVFOP_CURRENT_USER:
 		case SVFOP_USER:
-			InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
-			*op->resvalue = current_user(&fcinfo);
-			*op->resnull = fcinfo.isnull;
+			InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+			*op->resvalue = current_user(fcinfo);
+			*op->resnull = fcinfo->isnull;
 			break;
 		case SVFOP_SESSION_USER:
-			InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
-			*op->resvalue = session_user(&fcinfo);
-			*op->resnull = fcinfo.isnull;
+			InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+			*op->resvalue = session_user(fcinfo);
+			*op->resnull = fcinfo->isnull;
 			break;
 		case SVFOP_CURRENT_CATALOG:
-			InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
-			*op->resvalue = current_database(&fcinfo);
-			*op->resnull = fcinfo.isnull;
+			InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+			*op->resvalue = current_database(fcinfo);
+			*op->resnull = fcinfo->isnull;
 			break;
 		case SVFOP_CURRENT_SCHEMA:
-			InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
-			*op->resvalue = current_schema(&fcinfo);
-			*op->resnull = fcinfo.isnull;
+			InitFunctionCallInfoData(*fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+			*op->resvalue = current_schema(fcinfo);
+			*op->resnull = fcinfo->isnull;
 			break;
 	}
 }
@@ -2812,8 +2829,8 @@ ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
 	int			off;
 
 	/* set at initialization */
-	Assert(fcinfo->argnull[0] == false);
-	Assert(fcinfo->argnull[1] == false);
+	Assert(fcinfo->args[0].isnull == false);
+	Assert(fcinfo->args[1].isnull == false);
 
 	/* default to null result */
 	*op->resnull = true;
@@ -2835,8 +2852,8 @@ ExecEvalMinMax(ExprState *state, ExprEvalStep *op)
 			int			cmpresult;
 
 			/* apply comparison function */
-			fcinfo->arg[0] = *op->resvalue;
-			fcinfo->arg[1] = values[off];
+			fcinfo->args[0].datum = *op->resvalue;
+			fcinfo->args[1].datum = values[off];
 
 			fcinfo->isnull = false;
 			cmpresult = DatumGetInt32(FunctionCallInvoke(fcinfo));
@@ -3388,7 +3405,7 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
 	 * If the scalar is NULL, and the function is strict, return NULL; no
 	 * point in iterating the loop.
 	 */
-	if (fcinfo->argnull[0] && strictfunc)
+	if (fcinfo->args[0].isnull && strictfunc)
 	{
 		*op->resnull = true;
 		return;
@@ -3428,20 +3445,20 @@ ExecEvalScalarArrayOp(ExprState *state, ExprEvalStep *op)
 		/* Get array element, checking for NULL */
 		if (bitmap && (*bitmap & bitmask) == 0)
 		{
-			fcinfo->arg[1] = (Datum) 0;
-			fcinfo->argnull[1] = true;
+			fcinfo->args[1].datum = (Datum) 0;
+			fcinfo->args[1].isnull = true;
 		}
 		else
 		{
 			elt = fetch_att(s, typbyval, typlen);
 			s = att_addlength_pointer(s, typlen, s);
 			s = (char *) att_align_nominal(s, typalign);
-			fcinfo->arg[1] = elt;
-			fcinfo->argnull[1] = false;
+			fcinfo->args[1].datum = elt;
+			fcinfo->args[1].isnull = false;
 		}
 
 		/* Call comparison function */
-		if (fcinfo->argnull[1] && strictfunc)
+		if (fcinfo->args[1].isnull && strictfunc)
 		{
 			fcinfo->isnull = true;
 			thisresult = (Datum) 0;
@@ -4040,7 +4057,7 @@ ExecEvalWholeRowVar(ExprState *state, ExprEvalStep *op, ExprContext *econtext)
 void
 ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup pergroup)
 {
-	FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+	FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
 	MemoryContext oldContext;
 
 	/*
@@ -4051,7 +4068,7 @@ ExecAggInitGroup(AggState *aggstate, AggStatePerTrans pertrans, AggStatePerGroup
 	 */
 	oldContext = MemoryContextSwitchTo(
 									   aggstate->curaggcontext->ecxt_per_tuple_memory);
-	pergroup->transValue = datumCopy(fcinfo->arg[1],
+	pergroup->transValue = datumCopy(fcinfo->args[1].datum,
 									 pertrans->transtypeByVal,
 									 pertrans->transtypeLen);
 	pergroup->transValueIsNull = false;
diff --git a/src/backend/executor/execSRF.c b/src/backend/executor/execSRF.c
index b97b8d797ec..882cb6b3e38 100644
--- a/src/backend/executor/execSRF.c
+++ b/src/backend/executor/execSRF.c
@@ -109,7 +109,10 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 	Oid			funcrettype;
 	bool		returnsTuple;
 	bool		returnsSet = false;
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} fcinfo;
 	PgStat_FunctionCallUsage fcusage;
 	ReturnSetInfo rsinfo;
 	HeapTupleData tmptup;
@@ -157,9 +160,9 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 		 * This path is similar to ExecMakeFunctionResultSet.
 		 */
 		returnsSet = setexpr->funcReturnsSet;
-		InitFunctionCallInfoData(fcinfo, &(setexpr->func),
+		InitFunctionCallInfoData(fcinfo.fcinfo, &(setexpr->func),
 								 list_length(setexpr->args),
-								 setexpr->fcinfo_data.fncollation,
+								 setexpr->fcinfo->fncollation,
 								 NULL, (Node *) &rsinfo);
 
 		/*
@@ -174,7 +177,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 		 */
 		MemoryContextReset(argContext);
 		oldcontext = MemoryContextSwitchTo(argContext);
-		ExecEvalFuncArgs(&fcinfo, setexpr->args, econtext);
+		ExecEvalFuncArgs(&fcinfo.fcinfo, setexpr->args, econtext);
 		MemoryContextSwitchTo(oldcontext);
 
 		/*
@@ -186,9 +189,9 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 		{
 			int			i;
 
-			for (i = 0; i < fcinfo.nargs; i++)
+			for (i = 0; i < fcinfo.fcinfo.nargs; i++)
 			{
-				if (fcinfo.argnull[i])
+				if (fcinfo.fcinfo.args[i].isnull)
 					goto no_function_result;
 			}
 		}
@@ -196,7 +199,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 	else
 	{
 		/* Treat setexpr as a generic expression */
-		InitFunctionCallInfoData(fcinfo, NULL, 0, InvalidOid, NULL, NULL);
+		InitFunctionCallInfoData(fcinfo.fcinfo, NULL, 0, InvalidOid, NULL, NULL);
 	}
 
 	/*
@@ -224,11 +227,11 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 		/* Call the function or expression one time */
 		if (!setexpr->elidedFuncState)
 		{
-			pgstat_init_function_usage(&fcinfo, &fcusage);
+			pgstat_init_function_usage(&fcinfo.fcinfo, &fcusage);
 
-			fcinfo.isnull = false;
+			fcinfo.fcinfo.isnull = false;
 			rsinfo.isDone = ExprSingleResult;
-			result = FunctionCallInvoke(&fcinfo);
+			result = FunctionCallInvoke(&fcinfo.fcinfo);
 
 			pgstat_end_function_usage(&fcusage,
 									  rsinfo.isDone != ExprMultipleResult);
@@ -236,7 +239,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 		else
 		{
 			result =
-				ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo.isnull);
+				ExecEvalExpr(setexpr->elidedFuncState, econtext, &fcinfo.fcinfo.isnull);
 			rsinfo.isDone = ExprSingleResult;
 		}
 
@@ -277,7 +280,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 			 */
 			if (returnsTuple)
 			{
-				if (!fcinfo.isnull)
+				if (!fcinfo.fcinfo.isnull)
 				{
 					HeapTupleHeader td = DatumGetHeapTupleHeader(result);
 
@@ -338,7 +341,7 @@ ExecMakeTableFunctionResult(SetExprState *setexpr,
 			else
 			{
 				/* Scalar-type case: just store the function result */
-				tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.isnull);
+				tuplestore_putvalues(tupstore, tupdesc, &result, &fcinfo.fcinfo.isnull);
 			}
 
 			/*
@@ -547,7 +550,7 @@ restart:
 	 * rows from this SRF have been returned, otherwise ValuePerCall SRFs
 	 * would reference freed memory after the first returned row.
 	 */
-	fcinfo = &fcache->fcinfo_data;
+	fcinfo = fcache->fcinfo;
 	arguments = fcache->args;
 	if (!fcache->setArgsValid)
 	{
@@ -587,7 +590,7 @@ restart:
 	{
 		for (i = 0; i < fcinfo->nargs; i++)
 		{
-			if (fcinfo->argnull[i])
+			if (fcinfo->args[i].isnull)
 			{
 				callit = false;
 				break;
@@ -704,7 +707,8 @@ init_sexpr(Oid foid, Oid input_collation, Expr *node,
 	fmgr_info_set_expr((Node *) sexpr->expr, &(sexpr->func));
 
 	/* Initialize the function call parameter struct as well */
-	InitFunctionCallInfoData(sexpr->fcinfo_data, &(sexpr->func),
+	sexpr->fcinfo = (FunctionCallInfo) palloc(SizeForFunctionCallInfoData(list_length(sexpr->args)));
+	InitFunctionCallInfoData(*sexpr->fcinfo, &(sexpr->func),
 							 list_length(sexpr->args),
 							 input_collation, NULL, NULL);
 
@@ -820,9 +824,9 @@ ExecEvalFuncArgs(FunctionCallInfo fcinfo,
 	{
 		ExprState  *argstate = (ExprState *) lfirst(arg);
 
-		fcinfo->arg[i] = ExecEvalExpr(argstate,
-									  econtext,
-									  &fcinfo->argnull[i]);
+		fcinfo->args[i].datum = ExecEvalExpr(argstate,
+											 econtext,
+											 &fcinfo->args[i].isnull);
 		i++;
 	}
 
diff --git a/src/backend/executor/functions.c b/src/backend/executor/functions.c
index 23545896d4d..672dcd981cd 100644
--- a/src/backend/executor/functions.c
+++ b/src/backend/executor/functions.c
@@ -933,8 +933,8 @@ postquel_sub_params(SQLFunctionCachePtr fcache,
 		{
 			ParamExternData *prm = &paramLI->params[i];
 
-			prm->value = fcinfo->arg[i];
-			prm->isnull = fcinfo->argnull[i];
+			prm->value = fcinfo->args[i].datum;
+			prm->isnull = fcinfo->args[i].isnull;
 			prm->pflags = 0;
 			prm->ptype = fcache->pinfo->argtypes[i];
 		}
diff --git a/src/backend/executor/nodeAgg.c b/src/backend/executor/nodeAgg.c
index 0fe0c22c1ea..90a5e1ba2ad 100644
--- a/src/backend/executor/nodeAgg.c
+++ b/src/backend/executor/nodeAgg.c
@@ -553,7 +553,7 @@ advance_transition_function(AggState *aggstate,
 							AggStatePerTrans pertrans,
 							AggStatePerGroup pergroupstate)
 {
-	FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+	FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
 	MemoryContext oldContext;
 	Datum		newVal;
 
@@ -568,7 +568,7 @@ advance_transition_function(AggState *aggstate,
 
 		for (i = 1; i <= numTransInputs; i++)
 		{
-			if (fcinfo->argnull[i])
+			if (fcinfo->args[i].isnull)
 				return;
 		}
 		if (pergroupstate->noTransValue)
@@ -584,7 +584,7 @@ advance_transition_function(AggState *aggstate,
 			 */
 			oldContext = MemoryContextSwitchTo(
 											   aggstate->curaggcontext->ecxt_per_tuple_memory);
-			pergroupstate->transValue = datumCopy(fcinfo->arg[1],
+			pergroupstate->transValue = datumCopy(fcinfo->args[1].datum,
 												  pertrans->transtypeByVal,
 												  pertrans->transtypeLen);
 			pergroupstate->transValueIsNull = false;
@@ -613,8 +613,8 @@ advance_transition_function(AggState *aggstate,
 	/*
 	 * OK to call the transition function
 	 */
-	fcinfo->arg[0] = pergroupstate->transValue;
-	fcinfo->argnull[0] = pergroupstate->transValueIsNull;
+	fcinfo->args[0].datum = pergroupstate->transValue;
+	fcinfo->args[0].isnull = pergroupstate->transValueIsNull;
 	fcinfo->isnull = false;		/* just in case transfn doesn't set it */
 
 	newVal = FunctionCallInvoke(fcinfo);
@@ -717,7 +717,7 @@ process_ordered_aggregate_single(AggState *aggstate,
 	bool		isDistinct = (pertrans->numDistinctCols > 0);
 	Datum		newAbbrevVal = (Datum) 0;
 	Datum		oldAbbrevVal = (Datum) 0;
-	FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+	FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
 	Datum	   *newVal;
 	bool	   *isNull;
 
@@ -726,8 +726,8 @@ process_ordered_aggregate_single(AggState *aggstate,
 	tuplesort_performsort(pertrans->sortstates[aggstate->current_set]);
 
 	/* Load the column into argument 1 (arg 0 will be transition value) */
-	newVal = fcinfo->arg + 1;
-	isNull = fcinfo->argnull + 1;
+	newVal = &fcinfo->args[1].datum;
+	isNull = &fcinfo->args[1].isnull;
 
 	/*
 	 * Note: if input type is pass-by-ref, the datums returned by the sort are
@@ -803,7 +803,7 @@ process_ordered_aggregate_multi(AggState *aggstate,
 								AggStatePerGroup pergroupstate)
 {
 	ExprContext *tmpcontext = aggstate->tmpcontext;
-	FunctionCallInfo fcinfo = &pertrans->transfn_fcinfo;
+	FunctionCallInfo fcinfo = pertrans->transfn_fcinfo;
 	TupleTableSlot *slot1 = pertrans->sortslot;
 	TupleTableSlot *slot2 = pertrans->uniqslot;
 	int			numTransInputs = pertrans->numTransInputs;
@@ -843,8 +843,8 @@ process_ordered_aggregate_multi(AggState *aggstate,
 			/* Start from 1, since the 0th arg will be the transition value */
 			for (i = 0; i < numTransInputs; i++)
 			{
-				fcinfo->arg[i + 1] = slot1->tts_values[i];
-				fcinfo->argnull[i + 1] = slot1->tts_isnull[i];
+				fcinfo->args[i + 1].datum = slot1->tts_values[i];
+				fcinfo->args[i + 1].isnull = slot1->tts_isnull[i];
 			}
 
 			advance_transition_function(aggstate, pertrans, pergroupstate);
@@ -897,7 +897,11 @@ finalize_aggregate(AggState *aggstate,
 				   AggStatePerGroup pergroupstate,
 				   Datum *resultVal, bool *resultIsNull)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} fcinfodata;
+	FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
 	bool		anynull = false;
 	MemoryContext oldContext;
 	int			i;
@@ -917,10 +921,10 @@ finalize_aggregate(AggState *aggstate,
 	{
 		ExprState  *expr = (ExprState *) lfirst(lc);
 
-		fcinfo.arg[i] = ExecEvalExpr(expr,
-									 aggstate->ss.ps.ps_ExprContext,
-									 &fcinfo.argnull[i]);
-		anynull |= fcinfo.argnull[i];
+		fcinfo->args[i].datum = ExecEvalExpr(expr,
+											aggstate->ss.ps.ps_ExprContext,
+											&fcinfo->args[i].isnull);
+		anynull |= fcinfo->args[i].isnull;
 		i++;
 	}
 
@@ -934,27 +938,27 @@ finalize_aggregate(AggState *aggstate,
 		/* set up aggstate->curperagg for AggGetAggref() */
 		aggstate->curperagg = peragg;
 
-		InitFunctionCallInfoData(fcinfo, &peragg->finalfn,
+		InitFunctionCallInfoData(*fcinfo, &peragg->finalfn,
 								 numFinalArgs,
 								 pertrans->aggCollation,
 								 (void *) aggstate, NULL);
 
 		/* Fill in the transition state value */
-		fcinfo.arg[0] = MakeExpandedObjectReadOnly(pergroupstate->transValue,
+		fcinfo->args[0].datum = MakeExpandedObjectReadOnly(pergroupstate->transValue,
 												   pergroupstate->transValueIsNull,
 												   pertrans->transtypeLen);
-		fcinfo.argnull[0] = pergroupstate->transValueIsNull;
+		fcinfo->args[0].isnull = pergroupstate->transValueIsNull;
 		anynull |= pergroupstate->transValueIsNull;
 
 		/* Fill any remaining argument positions with nulls */
 		for (; i < numFinalArgs; i++)
 		{
-			fcinfo.arg[i] = (Datum) 0;
-			fcinfo.argnull[i] = true;
+			fcinfo->args[i].datum = (Datum) 0;
+			fcinfo->args[i].isnull = true;
 			anynull = true;
 		}
 
-		if (fcinfo.flinfo->fn_strict && anynull)
+		if (fcinfo->flinfo->fn_strict && anynull)
 		{
 			/* don't call a strict function with NULL inputs */
 			*resultVal = (Datum) 0;
@@ -962,8 +966,8 @@ finalize_aggregate(AggState *aggstate,
 		}
 		else
 		{
-			*resultVal = FunctionCallInvoke(&fcinfo);
-			*resultIsNull = fcinfo.isnull;
+			*resultVal = FunctionCallInvoke(fcinfo);
+			*resultIsNull = fcinfo->isnull;
 		}
 		aggstate->curperagg = NULL;
 	}
@@ -1018,12 +1022,12 @@ finalize_partialaggregate(AggState *aggstate,
 		}
 		else
 		{
-			FunctionCallInfo fcinfo = &pertrans->serialfn_fcinfo;
+			FunctionCallInfo fcinfo = pertrans->serialfn_fcinfo;
 
-			fcinfo->arg[0] = MakeExpandedObjectReadOnly(pergroupstate->transValue,
-														pergroupstate->transValueIsNull,
-														pertrans->transtypeLen);
-			fcinfo->argnull[0] = pergroupstate->transValueIsNull;
+			fcinfo->args[0].datum = MakeExpandedObjectReadOnly(pergroupstate->transValue,
+															   pergroupstate->transValueIsNull,
+															   pertrans->transtypeLen);
+			fcinfo->args[0].isnull = pergroupstate->transValueIsNull;
 
 			*resultVal = FunctionCallInvoke(fcinfo);
 			*resultIsNull = fcinfo->isnull;
@@ -2926,7 +2930,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 		fmgr_info(aggtransfn, &pertrans->transfn);
 		fmgr_info_set_expr((Node *) combinefnexpr, &pertrans->transfn);
 
-		InitFunctionCallInfoData(pertrans->transfn_fcinfo,
+		pertrans->transfn_fcinfo = (FunctionCallInfo) palloc(SizeForFunctionCallInfoData(2));
+		InitFunctionCallInfoData(*pertrans->transfn_fcinfo,
 								 &pertrans->transfn,
 								 2,
 								 pertrans->aggCollation,
@@ -2964,7 +2969,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 		fmgr_info(aggtransfn, &pertrans->transfn);
 		fmgr_info_set_expr((Node *) transfnexpr, &pertrans->transfn);
 
-		InitFunctionCallInfoData(pertrans->transfn_fcinfo,
+		pertrans->transfn_fcinfo = (FunctionCallInfo) palloc(SizeForFunctionCallInfoData(pertrans->numTransInputs + 1));
+		InitFunctionCallInfoData(*pertrans->transfn_fcinfo,
 								 &pertrans->transfn,
 								 pertrans->numTransInputs + 1,
 								 pertrans->aggCollation,
@@ -3002,7 +3008,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 		fmgr_info(aggserialfn, &pertrans->serialfn);
 		fmgr_info_set_expr((Node *) serialfnexpr, &pertrans->serialfn);
 
-		InitFunctionCallInfoData(pertrans->serialfn_fcinfo,
+		pertrans->serialfn_fcinfo = (FunctionCallInfo) palloc(SizeForFunctionCallInfoData(1));
+		InitFunctionCallInfoData(*pertrans->serialfn_fcinfo,
 								 &pertrans->serialfn,
 								 1,
 								 InvalidOid,
@@ -3016,7 +3023,8 @@ build_pertrans_for_aggref(AggStatePerTrans pertrans,
 		fmgr_info(aggdeserialfn, &pertrans->deserialfn);
 		fmgr_info_set_expr((Node *) deserialfnexpr, &pertrans->deserialfn);
 
-		InitFunctionCallInfoData(pertrans->deserialfn_fcinfo,
+		pertrans->deserialfn_fcinfo = (FunctionCallInfo) palloc(SizeForFunctionCallInfoData(2));
+		InitFunctionCallInfoData(*pertrans->deserialfn_fcinfo,
 								 &pertrans->deserialfn,
 								 2,
 								 InvalidOid,
diff --git a/src/backend/executor/nodeWindowAgg.c b/src/backend/executor/nodeWindowAgg.c
index fe5369a0c7b..9c1fd24065c 100644
--- a/src/backend/executor/nodeWindowAgg.c
+++ b/src/backend/executor/nodeWindowAgg.c
@@ -243,8 +243,11 @@ advance_windowaggregate(WindowAggState *winstate,
 {
 	WindowFuncExprState *wfuncstate = perfuncstate->wfuncstate;
 	int			numArguments = perfuncstate->numArguments;
-	FunctionCallInfoData fcinfodata;
-	FunctionCallInfo fcinfo = &fcinfodata;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} fcinfodata;
+	FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
 	Datum		newVal;
 	ListCell   *arg;
 	int			i;
@@ -273,8 +276,8 @@ advance_windowaggregate(WindowAggState *winstate,
 	{
 		ExprState  *argstate = (ExprState *) lfirst(arg);
 
-		fcinfo->arg[i] = ExecEvalExpr(argstate, econtext,
-									  &fcinfo->argnull[i]);
+		fcinfo->args[i].datum = ExecEvalExpr(argstate, econtext,
+											 &fcinfo->args[i].isnull);
 		i++;
 	}
 
@@ -287,7 +290,7 @@ advance_windowaggregate(WindowAggState *winstate,
 		 */
 		for (i = 1; i <= numArguments; i++)
 		{
-			if (fcinfo->argnull[i])
+			if (fcinfo->args[i].isnull)
 			{
 				MemoryContextSwitchTo(oldContext);
 				return;
@@ -306,7 +309,7 @@ advance_windowaggregate(WindowAggState *winstate,
 		if (peraggstate->transValueCount == 0 && peraggstate->transValueIsNull)
 		{
 			MemoryContextSwitchTo(peraggstate->aggcontext);
-			peraggstate->transValue = datumCopy(fcinfo->arg[1],
+			peraggstate->transValue = datumCopy(fcinfo->args[1].datum,
 												peraggstate->transtypeByVal,
 												peraggstate->transtypeLen);
 			peraggstate->transValueIsNull = false;
@@ -339,8 +342,8 @@ advance_windowaggregate(WindowAggState *winstate,
 							 numArguments + 1,
 							 perfuncstate->winCollation,
 							 (void *) winstate, NULL);
-	fcinfo->arg[0] = peraggstate->transValue;
-	fcinfo->argnull[0] = peraggstate->transValueIsNull;
+	fcinfo->args[0].datum = peraggstate->transValue;
+	fcinfo->args[0].isnull = peraggstate->transValueIsNull;
 	winstate->curaggcontext = peraggstate->aggcontext;
 	newVal = FunctionCallInvoke(fcinfo);
 	winstate->curaggcontext = NULL;
@@ -420,8 +423,11 @@ advance_windowaggregate_base(WindowAggState *winstate,
 {
 	WindowFuncExprState *wfuncstate = perfuncstate->wfuncstate;
 	int			numArguments = perfuncstate->numArguments;
-	FunctionCallInfoData fcinfodata;
-	FunctionCallInfo fcinfo = &fcinfodata;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} fcinfodata;
+	FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
 	Datum		newVal;
 	ListCell   *arg;
 	int			i;
@@ -450,8 +456,8 @@ advance_windowaggregate_base(WindowAggState *winstate,
 	{
 		ExprState  *argstate = (ExprState *) lfirst(arg);
 
-		fcinfo->arg[i] = ExecEvalExpr(argstate, econtext,
-									  &fcinfo->argnull[i]);
+		fcinfo->args[i].datum = ExecEvalExpr(argstate, econtext,
+											 &fcinfo->args[i].isnull);
 		i++;
 	}
 
@@ -464,7 +470,7 @@ advance_windowaggregate_base(WindowAggState *winstate,
 		 */
 		for (i = 1; i <= numArguments; i++)
 		{
-			if (fcinfo->argnull[i])
+			if (fcinfo->args[i].isnull)
 			{
 				MemoryContextSwitchTo(oldContext);
 				return true;
@@ -510,8 +516,8 @@ advance_windowaggregate_base(WindowAggState *winstate,
 							 numArguments + 1,
 							 perfuncstate->winCollation,
 							 (void *) winstate, NULL);
-	fcinfo->arg[0] = peraggstate->transValue;
-	fcinfo->argnull[0] = peraggstate->transValueIsNull;
+	fcinfo->args[0].datum = peraggstate->transValue;
+	fcinfo->args[0].isnull = peraggstate->transValueIsNull;
 	winstate->curaggcontext = peraggstate->aggcontext;
 	newVal = FunctionCallInvoke(fcinfo);
 	winstate->curaggcontext = NULL;
@@ -592,29 +598,33 @@ finalize_windowaggregate(WindowAggState *winstate,
 	if (OidIsValid(peraggstate->finalfn_oid))
 	{
 		int			numFinalArgs = peraggstate->numFinalArgs;
-		FunctionCallInfoData fcinfo;
+		union {
+			FunctionCallInfoData fcinfo;
+			char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+		} fcinfodata;
+		FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
 		bool		anynull;
 		int			i;
 
-		InitFunctionCallInfoData(fcinfo, &(peraggstate->finalfn),
+		InitFunctionCallInfoData(fcinfodata.fcinfo, &(peraggstate->finalfn),
 								 numFinalArgs,
 								 perfuncstate->winCollation,
 								 (void *) winstate, NULL);
-		fcinfo.arg[0] = MakeExpandedObjectReadOnly(peraggstate->transValue,
-												   peraggstate->transValueIsNull,
-												   peraggstate->transtypeLen);
-		fcinfo.argnull[0] = peraggstate->transValueIsNull;
+		fcinfo->args[0].datum = MakeExpandedObjectReadOnly(peraggstate->transValue,
+														   peraggstate->transValueIsNull,
+														   peraggstate->transtypeLen);
+		fcinfo->args[0].isnull = peraggstate->transValueIsNull;
 		anynull = peraggstate->transValueIsNull;
 
 		/* Fill any remaining argument positions with nulls */
 		for (i = 1; i < numFinalArgs; i++)
 		{
-			fcinfo.arg[i] = (Datum) 0;
-			fcinfo.argnull[i] = true;
+			fcinfo->args[i].datum = (Datum) 0;
+			fcinfo->args[i].isnull = true;
 			anynull = true;
 		}
 
-		if (fcinfo.flinfo->fn_strict && anynull)
+		if (fcinfo->flinfo->fn_strict && anynull)
 		{
 			/* don't call a strict function with NULL inputs */
 			*result = (Datum) 0;
@@ -623,9 +633,9 @@ finalize_windowaggregate(WindowAggState *winstate,
 		else
 		{
 			winstate->curaggcontext = peraggstate->aggcontext;
-			*result = FunctionCallInvoke(&fcinfo);
+			*result = FunctionCallInvoke(fcinfo);
 			winstate->curaggcontext = NULL;
-			*isnull = fcinfo.isnull;
+			*isnull = fcinfo->isnull;
 		}
 	}
 	else
@@ -1032,8 +1042,13 @@ static void
 eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate,
 					Datum *result, bool *isnull)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		/* FIXME: variable length allocation */
+		char *fcinfo_data[SizeForFunctionCallInfoData(10)];
+	} d;
 	MemoryContext oldContext;
+	int argno;
 
 	oldContext = MemoryContextSwitchTo(winstate->ss.ps.ps_ExprContext->ecxt_per_tuple_memory);
 
@@ -1043,24 +1058,25 @@ eval_windowfunction(WindowAggState *winstate, WindowStatePerFunc perfuncstate,
 	 * implementations to support varying numbers of arguments.  The real info
 	 * goes through the WindowObject, which is passed via fcinfo->context.
 	 */
-	InitFunctionCallInfoData(fcinfo, &(perfuncstate->flinfo),
+	InitFunctionCallInfoData(d.fcinfo, &(perfuncstate->flinfo),
 							 perfuncstate->numArguments,
 							 perfuncstate->winCollation,
 							 (void *) perfuncstate->winobj, NULL);
 	/* Just in case, make all the regular argument slots be null */
-	memset(fcinfo.argnull, true, perfuncstate->numArguments);
+	for (argno = 0; argno < perfuncstate->numArguments; argno++)
+		d.fcinfo.args[argno].isnull = true;
 	/* Window functions don't have a current aggregate context, either */
 	winstate->curaggcontext = NULL;
 
-	*result = FunctionCallInvoke(&fcinfo);
-	*isnull = fcinfo.isnull;
+	*result = FunctionCallInvoke(&d.fcinfo);
+	*isnull = d.fcinfo.isnull;
 
 	/*
 	 * Make sure pass-by-ref data is allocated in the appropriate context. (We
 	 * need this in case the function returns a pointer into some short-lived
 	 * tuple, as is entirely possible.)
 	 */
-	if (!perfuncstate->resulttypeByVal && !fcinfo.isnull &&
+	if (!perfuncstate->resulttypeByVal && !d.fcinfo.isnull &&
 		!MemoryContextContains(CurrentMemoryContext,
 							   DatumGetPointer(*result)))
 		*result = datumCopy(*result,
diff --git a/src/backend/jit/llvm/llvmjit_expr.c b/src/backend/jit/llvm/llvmjit_expr.c
index 36c5f7d500e..04bfd162227 100644
--- a/src/backend/jit/llvm/llvmjit_expr.c
+++ b/src/backend/jit/llvm/llvmjit_expr.c
@@ -2117,15 +2117,16 @@ llvm_compile_expr(ExprState *state)
 			case EEOP_AGG_STRICT_INPUT_CHECK:
 				{
 					int			nargs = op->d.agg_strict_input_check.nargs;
-					bool	   *nulls = op->d.agg_strict_input_check.nulls;
+					NullableDatum *args = op->d.agg_strict_input_check.args;
 					int			jumpnull;
 					int			argno;
 
-					LLVMValueRef v_nullp;
+					LLVMValueRef v_argp;
 					LLVMBasicBlockRef *b_checknulls;
 
 					jumpnull = op->d.agg_strict_input_check.jumpnull;
-					v_nullp = l_ptr_const(nulls, l_ptr(TypeStorageBool));
+					/* FIXME: This isn't correct, it's a NullableDatum now */
+					v_argp = l_ptr_const(args, l_ptr(TypeStorageBool));
 
 					/* create blocks for checking args */
 					b_checknulls = palloc(sizeof(LLVMBasicBlockRef *) * nargs);
@@ -2153,7 +2154,8 @@ llvm_compile_expr(ExprState *state)
 						else
 							b_argnotnull = b_checknulls[argno + 1];
 
-						v_argisnull = l_load_gep1(b, v_nullp, v_argno, "");
+						/* FIXME: This isn't correct */
+						v_argisnull = l_load_gep1(b, v_argp, v_argno, "");
 
 						LLVMBuildCondBr(b,
 										LLVMBuildICmp(b,
@@ -2330,7 +2332,7 @@ llvm_compile_expr(ExprState *state)
 					aggstate = op->d.agg_trans.aggstate;
 					pertrans = op->d.agg_trans.pertrans;
 
-					fcinfo = &pertrans->transfn_fcinfo;
+					fcinfo = pertrans->transfn_fcinfo;
 
 					v_aggstatep = l_ptr_const(aggstate,
 											  l_ptr(StructAggState));
@@ -2598,12 +2600,8 @@ BuildV1Call(LLVMJitContext *context, LLVMBuilderRef b,
 		LLVMValueRef v_lifetime = create_LifetimeEnd(mod);
 		LLVMValueRef params[2];
 
-		params[0] = l_int64_const(sizeof(fcinfo->arg));
-		params[1] = l_ptr_const(fcinfo->arg, l_ptr(LLVMInt8Type()));
-		LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
-
-		params[0] = l_int64_const(sizeof(fcinfo->argnull));
-		params[1] = l_ptr_const(fcinfo->argnull, l_ptr(LLVMInt8Type()));
+		params[0] = l_int64_const(sizeof(NullableDatum) * fcinfo->nargs);
+		params[1] = l_ptr_const(fcinfo->args, l_ptr(LLVMInt8Type()));
 		LLVMBuildCall(b, v_lifetime, params, lengthof(params), "");
 
 		params[0] = l_int64_const(sizeof(fcinfo->isnull));
diff --git a/src/backend/tcop/fastpath.c b/src/backend/tcop/fastpath.c
index d16ba5ec927..2394f800fce 100644
--- a/src/backend/tcop/fastpath.c
+++ b/src/backend/tcop/fastpath.c
@@ -260,7 +260,11 @@ HandleFunctionRequest(StringInfo msgBuf)
 {
 	Oid			fid;
 	AclResult	aclresult;
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} fcinfodata;
+	FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
 	int16		rformat;
 	Datum		retval;
 	struct fp_info my_fp;
@@ -332,12 +336,12 @@ HandleFunctionRequest(StringInfo msgBuf)
 	 * functions can't be called this way.  Perhaps we should pass
 	 * DEFAULT_COLLATION_OID, instead?
 	 */
-	InitFunctionCallInfoData(fcinfo, &fip->flinfo, 0, InvalidOid, NULL, NULL);
+	InitFunctionCallInfoData(*fcinfo, &fip->flinfo, 0, InvalidOid, NULL, NULL);
 
 	if (PG_PROTOCOL_MAJOR(FrontendProtocol) >= 3)
-		rformat = parse_fcall_arguments(msgBuf, fip, &fcinfo);
+		rformat = parse_fcall_arguments(msgBuf, fip, fcinfo);
 	else
-		rformat = parse_fcall_arguments_20(msgBuf, fip, &fcinfo);
+		rformat = parse_fcall_arguments_20(msgBuf, fip, fcinfo);
 
 	/* Verify we reached the end of the message where expected. */
 	pq_getmsgend(msgBuf);
@@ -350,9 +354,9 @@ HandleFunctionRequest(StringInfo msgBuf)
 	{
 		int			i;
 
-		for (i = 0; i < fcinfo.nargs; i++)
+		for (i = 0; i < fcinfo->nargs; i++)
 		{
-			if (fcinfo.argnull[i])
+			if (fcinfo->args[i].isnull)
 			{
 				callit = false;
 				break;
@@ -363,18 +367,18 @@ HandleFunctionRequest(StringInfo msgBuf)
 	if (callit)
 	{
 		/* Okay, do it ... */
-		retval = FunctionCallInvoke(&fcinfo);
+		retval = FunctionCallInvoke(fcinfo);
 	}
 	else
 	{
-		fcinfo.isnull = true;
+		fcinfo->isnull = true;
 		retval = (Datum) 0;
 	}
 
 	/* ensure we do at least one CHECK_FOR_INTERRUPTS per function call */
 	CHECK_FOR_INTERRUPTS();
 
-	SendFunctionResult(retval, fcinfo.isnull, fip->rettype, rformat);
+	SendFunctionResult(retval, fcinfo->isnull, fip->rettype, rformat);
 
 	/* We no longer need the snapshot */
 	PopActiveSnapshot();
@@ -450,11 +454,11 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip,
 		argsize = pq_getmsgint(msgBuf, 4);
 		if (argsize == -1)
 		{
-			fcinfo->argnull[i] = true;
+			fcinfo->args[i].isnull = true;
 		}
 		else
 		{
-			fcinfo->argnull[i] = false;
+			fcinfo->args[i].isnull = false;
 			if (argsize < 0)
 				ereport(ERROR,
 						(errcode(ERRCODE_PROTOCOL_VIOLATION),
@@ -494,8 +498,8 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip,
 			else
 				pstring = pg_client_to_server(abuf.data, argsize);
 
-			fcinfo->arg[i] = OidInputFunctionCall(typinput, pstring,
-												  typioparam, -1);
+			fcinfo->args[i].datum = OidInputFunctionCall(typinput, pstring,
+														 typioparam, -1);
 			/* Free result of encoding conversion, if any */
 			if (pstring && pstring != abuf.data)
 				pfree(pstring);
@@ -514,8 +518,8 @@ parse_fcall_arguments(StringInfo msgBuf, struct fp_info *fip,
 			else
 				bufptr = &abuf;
 
-			fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, bufptr,
-													typioparam, -1);
+			fcinfo->args[i].datum = OidReceiveFunctionCall(typreceive, bufptr,
+														   typioparam, -1);
 
 			/* Trouble if it didn't eat the whole buffer */
 			if (argsize != -1 && abuf.cursor != abuf.len)
@@ -579,12 +583,13 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info *fip,
 		argsize = pq_getmsgint(msgBuf, 4);
 		if (argsize == -1)
 		{
-			fcinfo->argnull[i] = true;
-			fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, NULL,
-													typioparam, -1);
+			/* FIXME: huh? */
+			fcinfo->args[i].isnull = true;
+			fcinfo->args[i].datum = OidReceiveFunctionCall(typreceive, NULL,
+														   typioparam, -1);
 			continue;
 		}
-		fcinfo->argnull[i] = false;
+		fcinfo->args[i].isnull = false;
 		if (argsize < 0)
 			ereport(ERROR,
 					(errcode(ERRCODE_PROTOCOL_VIOLATION),
@@ -597,8 +602,8 @@ parse_fcall_arguments_20(StringInfo msgBuf, struct fp_info *fip,
 							   pq_getmsgbytes(msgBuf, argsize),
 							   argsize);
 
-		fcinfo->arg[i] = OidReceiveFunctionCall(typreceive, &abuf,
-												typioparam, -1);
+		fcinfo->args[i].datum = OidReceiveFunctionCall(typreceive, &abuf,
+													   typioparam, -1);
 
 		/* Trouble if it didn't eat the whole buffer */
 		if (abuf.cursor != abuf.len)
diff --git a/src/backend/utils/adt/arrayfuncs.c b/src/backend/utils/adt/arrayfuncs.c
index 0cbdbe5587e..602348d04d5 100644
--- a/src/backend/utils/adt/arrayfuncs.c
+++ b/src/backend/utils/adt/arrayfuncs.c
@@ -3581,7 +3581,10 @@ array_eq(PG_FUNCTION_ARGS)
 	array_iter	it1;
 	array_iter	it2;
 	int			i;
-	FunctionCallInfoData locfcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(2)];
+	} locfcinfo;
 
 	if (element_type != AARR_ELEMTYPE(array2))
 		ereport(ERROR,
@@ -3621,7 +3624,7 @@ array_eq(PG_FUNCTION_ARGS)
 		/*
 		 * apply the operator to each pair of array elements.
 		 */
-		InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
+		InitFunctionCallInfoData(locfcinfo.fcinfo, &typentry->eq_opr_finfo, 2,
 								 collation, NULL, NULL);
 
 		/* Loop over source data */
@@ -3657,12 +3660,12 @@ array_eq(PG_FUNCTION_ARGS)
 			/*
 			 * Apply the operator to the element pair
 			 */
-			locfcinfo.arg[0] = elt1;
-			locfcinfo.arg[1] = elt2;
-			locfcinfo.argnull[0] = false;
-			locfcinfo.argnull[1] = false;
-			locfcinfo.isnull = false;
-			oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
+			locfcinfo.fcinfo.args[0].datum = elt1;
+			locfcinfo.fcinfo.args[0].isnull = false;
+			locfcinfo.fcinfo.args[1].datum = elt2;
+			locfcinfo.fcinfo.args[1].isnull = false;
+			locfcinfo.fcinfo.isnull = false;
+			oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo.fcinfo));
 			if (!oprresult)
 			{
 				result = false;
@@ -3752,7 +3755,11 @@ array_cmp(FunctionCallInfo fcinfo)
 	array_iter	it1;
 	array_iter	it2;
 	int			i;
-	FunctionCallInfoData locfcinfo;
+		union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(2)];
+	} locfcinfo;
+
 
 	if (element_type != AARR_ELEMTYPE(array2))
 		ereport(ERROR,
@@ -3785,7 +3792,7 @@ array_cmp(FunctionCallInfo fcinfo)
 	/*
 	 * apply the operator to each pair of array elements.
 	 */
-	InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
+	InitFunctionCallInfoData(locfcinfo.fcinfo, &typentry->cmp_proc_finfo, 2,
 							 collation, NULL, NULL);
 
 	/* Loop over source data */
@@ -3824,12 +3831,12 @@ array_cmp(FunctionCallInfo fcinfo)
 		}
 
 		/* Compare the pair of elements */
-		locfcinfo.arg[0] = elt1;
-		locfcinfo.arg[1] = elt2;
-		locfcinfo.argnull[0] = false;
-		locfcinfo.argnull[1] = false;
-		locfcinfo.isnull = false;
-		cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
+		locfcinfo.fcinfo.args[0].datum = elt1;
+		locfcinfo.fcinfo.args[0].isnull = false;
+		locfcinfo.fcinfo.args[1].datum = elt2;
+		locfcinfo.fcinfo.args[1].isnull = false;
+		locfcinfo.fcinfo.isnull = false;
+		cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo.fcinfo));
 
 		if (cmpresult == 0)
 			continue;			/* equal */
@@ -3916,7 +3923,11 @@ hash_array(PG_FUNCTION_ARGS)
 	char		typalign;
 	int			i;
 	array_iter	iter;
-	FunctionCallInfoData locfcinfo;
+		union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(1)];
+	} locfcinfo;
+
 
 	/*
 	 * We arrange to look up the hash function only once per series of calls,
@@ -3944,7 +3955,7 @@ hash_array(PG_FUNCTION_ARGS)
 	/*
 	 * apply the hash function to each array element.
 	 */
-	InitFunctionCallInfoData(locfcinfo, &typentry->hash_proc_finfo, 1,
+	InitFunctionCallInfoData(locfcinfo.fcinfo, &typentry->hash_proc_finfo, 1,
 							 InvalidOid, NULL, NULL);
 
 	/* Loop over source data */
@@ -3968,10 +3979,10 @@ hash_array(PG_FUNCTION_ARGS)
 		else
 		{
 			/* Apply the hash function */
-			locfcinfo.arg[0] = elt;
-			locfcinfo.argnull[0] = false;
-			locfcinfo.isnull = false;
-			elthash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo));
+			locfcinfo.fcinfo.args[0].datum = elt;
+			locfcinfo.fcinfo.args[0].isnull = false;
+			locfcinfo.fcinfo.isnull = false;
+			elthash = DatumGetUInt32(FunctionCallInvoke(&locfcinfo.fcinfo));
 		}
 
 		/*
@@ -4014,7 +4025,11 @@ hash_array_extended(PG_FUNCTION_ARGS)
 	char		typalign;
 	int			i;
 	array_iter	iter;
-	FunctionCallInfoData locfcinfo;
+		union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(2)];
+	} locfcinfo;
+
 
 	typentry = (TypeCacheEntry *) fcinfo->flinfo->fn_extra;
 	if (typentry == NULL ||
@@ -4033,7 +4048,7 @@ hash_array_extended(PG_FUNCTION_ARGS)
 	typbyval = typentry->typbyval;
 	typalign = typentry->typalign;
 
-	InitFunctionCallInfoData(locfcinfo, &typentry->hash_extended_proc_finfo, 2,
+	InitFunctionCallInfoData(locfcinfo.fcinfo, &typentry->hash_extended_proc_finfo, 2,
 							 InvalidOid, NULL, NULL);
 
 	/* Loop over source data */
@@ -4056,12 +4071,11 @@ hash_array_extended(PG_FUNCTION_ARGS)
 		else
 		{
 			/* Apply the hash function */
-			locfcinfo.arg[0] = elt;
-			locfcinfo.arg[1] = Int64GetDatum(seed);
-			locfcinfo.argnull[0] = false;
-			locfcinfo.argnull[1] = false;
-			locfcinfo.isnull = false;
-			elthash = DatumGetUInt64(FunctionCallInvoke(&locfcinfo));
+			locfcinfo.fcinfo.args[0].datum = elt;
+			locfcinfo.fcinfo.args[0].isnull = false;
+			locfcinfo.fcinfo.args[1].datum = Int64GetDatum(seed);
+			locfcinfo.fcinfo.args[1].isnull = false;
+			elthash = DatumGetUInt64(FunctionCallInvoke(&locfcinfo.fcinfo));
 		}
 
 		result = (result << 5) - result + elthash;
@@ -4104,7 +4118,11 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation,
 	int			i;
 	int			j;
 	array_iter	it1;
-	FunctionCallInfoData locfcinfo;
+		union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(2)];
+	} locfcinfo;
+
 
 	if (element_type != AARR_ELEMTYPE(array2))
 		ereport(ERROR,
@@ -4155,7 +4173,7 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation,
 	/*
 	 * Apply the comparison operator to each pair of array elements.
 	 */
-	InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
+	InitFunctionCallInfoData(locfcinfo.fcinfo, &typentry->eq_opr_finfo, 2,
 							 collation, NULL, NULL);
 
 	/* Loop over source data */
@@ -4197,12 +4215,12 @@ array_contain_compare(AnyArrayType *array1, AnyArrayType *array2, Oid collation,
 			/*
 			 * Apply the operator to the element pair
 			 */
-			locfcinfo.arg[0] = elt1;
-			locfcinfo.arg[1] = elt2;
-			locfcinfo.argnull[0] = false;
-			locfcinfo.argnull[1] = false;
-			locfcinfo.isnull = false;
-			oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
+			locfcinfo.fcinfo.args[0].datum = elt1;
+			locfcinfo.fcinfo.args[0].isnull = false;
+			locfcinfo.fcinfo.args[1].datum = elt2;
+			locfcinfo.fcinfo.args[1].isnull = false;
+			locfcinfo.fcinfo.isnull = false;
+			oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo.fcinfo));
 			if (oprresult)
 				break;
 		}
@@ -6053,7 +6071,11 @@ array_replace_internal(ArrayType *array,
 	int			bitmask;
 	bool		changed = false;
 	TypeCacheEntry *typentry;
-	FunctionCallInfoData locfcinfo;
+		union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(2)];
+	} locfcinfo;
+
 
 	element_type = ARR_ELEMTYPE(array);
 	ndim = ARR_NDIM(array);
@@ -6108,7 +6130,7 @@ array_replace_internal(ArrayType *array,
 	}
 
 	/* Prepare to apply the comparison operator */
-	InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
+	InitFunctionCallInfoData(locfcinfo.fcinfo, &typentry->eq_opr_finfo, 2,
 							 collation, NULL, NULL);
 
 	/* Allocate temporary arrays for new values */
@@ -6166,12 +6188,12 @@ array_replace_internal(ArrayType *array,
 				/*
 				 * Apply the operator to the element pair
 				 */
-				locfcinfo.arg[0] = elt;
-				locfcinfo.arg[1] = search;
-				locfcinfo.argnull[0] = false;
-				locfcinfo.argnull[1] = false;
-				locfcinfo.isnull = false;
-				oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
+				locfcinfo.fcinfo.args[0].datum = elt;
+				locfcinfo.fcinfo.args[0].isnull = false;
+				locfcinfo.fcinfo.args[1].datum = search;
+				locfcinfo.fcinfo.args[1].isnull = false;
+				locfcinfo.fcinfo.isnull = false;
+				oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo.fcinfo));
 				if (!oprresult)
 				{
 					/* no match, keep element */
@@ -6451,7 +6473,11 @@ width_bucket_array_fixed(Datum operand,
 	char	   *thresholds_data;
 	int			typlen = typentry->typlen;
 	bool		typbyval = typentry->typbyval;
-	FunctionCallInfoData locfcinfo;
+		union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(2)];
+	} locfcinfo;
+
 	int			left;
 	int			right;
 
@@ -6461,7 +6487,7 @@ width_bucket_array_fixed(Datum operand,
 	 */
 	thresholds_data = (char *) ARR_DATA_PTR(thresholds);
 
-	InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
+	InitFunctionCallInfoData(locfcinfo.fcinfo, &typentry->cmp_proc_finfo, 2,
 							 collation, NULL, NULL);
 
 	/* Find the bucket */
@@ -6475,13 +6501,13 @@ width_bucket_array_fixed(Datum operand,
 
 		ptr = thresholds_data + mid * typlen;
 
-		locfcinfo.arg[0] = operand;
-		locfcinfo.arg[1] = fetch_att(ptr, typbyval, typlen);
-		locfcinfo.argnull[0] = false;
-		locfcinfo.argnull[1] = false;
-		locfcinfo.isnull = false;
+		locfcinfo.fcinfo.args[0].datum = operand;
+		locfcinfo.fcinfo.args[0].isnull = false;
+		locfcinfo.fcinfo.args[1].datum = fetch_att(ptr, typbyval, typlen);
+		locfcinfo.fcinfo.args[1].isnull = false;
+		locfcinfo.fcinfo.isnull = false;
 
-		cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
+		cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo.fcinfo));
 
 		if (cmpresult < 0)
 			right = mid;
@@ -6505,13 +6531,17 @@ width_bucket_array_variable(Datum operand,
 	int			typlen = typentry->typlen;
 	bool		typbyval = typentry->typbyval;
 	char		typalign = typentry->typalign;
-	FunctionCallInfoData locfcinfo;
+		union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(2)];
+	} locfcinfo;
+
 	int			left;
 	int			right;
 
 	thresholds_data = (char *) ARR_DATA_PTR(thresholds);
 
-	InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
+	InitFunctionCallInfoData(locfcinfo.fcinfo, &typentry->cmp_proc_finfo, 2,
 							 collation, NULL, NULL);
 
 	/* Find the bucket */
@@ -6532,13 +6562,12 @@ width_bucket_array_variable(Datum operand,
 			ptr = (char *) att_align_nominal(ptr, typalign);
 		}
 
-		locfcinfo.arg[0] = operand;
-		locfcinfo.arg[1] = fetch_att(ptr, typbyval, typlen);
-		locfcinfo.argnull[0] = false;
-		locfcinfo.argnull[1] = false;
-		locfcinfo.isnull = false;
+		locfcinfo.fcinfo.args[0].datum = operand;
+		locfcinfo.fcinfo.args[0].isnull = false;
+		locfcinfo.fcinfo.args[1].datum = fetch_att(ptr, typbyval, typlen);
+		locfcinfo.fcinfo.args[1].isnull = false;
 
-		cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
+		cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo.fcinfo));
 
 		if (cmpresult < 0)
 			right = mid;
diff --git a/src/backend/utils/adt/int.c b/src/backend/utils/adt/int.c
index 559c365fecd..ac90ad280df 100644
--- a/src/backend/utils/adt/int.c
+++ b/src/backend/utils/adt/int.c
@@ -202,7 +202,10 @@ Datum
 int2vectorrecv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
-	FunctionCallInfoData locfcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} locfcinfo;
 	int2vector *result;
 
 	/*
@@ -211,19 +214,19 @@ int2vectorrecv(PG_FUNCTION_ARGS)
 	 * fcinfo->flinfo->fn_extra.  So we need to pass it our own flinfo
 	 * parameter.
 	 */
-	InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
+	InitFunctionCallInfoData(locfcinfo.fcinfo, fcinfo->flinfo, 3,
 							 InvalidOid, NULL, NULL);
 
-	locfcinfo.arg[0] = PointerGetDatum(buf);
-	locfcinfo.arg[1] = ObjectIdGetDatum(INT2OID);
-	locfcinfo.arg[2] = Int32GetDatum(-1);
-	locfcinfo.argnull[0] = false;
-	locfcinfo.argnull[1] = false;
-	locfcinfo.argnull[2] = false;
+	locfcinfo.fcinfo.args[0].datum = PointerGetDatum(buf);
+	locfcinfo.fcinfo.args[0].isnull = false;
+	locfcinfo.fcinfo.args[1].datum = ObjectIdGetDatum(INT2OID);
+	locfcinfo.fcinfo.args[1].isnull = false;
+	locfcinfo.fcinfo.args[2].datum = Int32GetDatum(-1);
+	locfcinfo.fcinfo.args[2].isnull = false;
 
-	result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo));
+	result = (int2vector *) DatumGetPointer(array_recv(&locfcinfo.fcinfo));
 
-	Assert(!locfcinfo.isnull);
+	Assert(!locfcinfo.fcinfo.isnull);
 
 	/* sanity checks: int2vector must be 1-D, 0-based, no nulls */
 	if (ARR_NDIM(result) != 1 ||
diff --git a/src/backend/utils/adt/oid.c b/src/backend/utils/adt/oid.c
index b0670e0d9f7..3f9fbab0330 100644
--- a/src/backend/utils/adt/oid.c
+++ b/src/backend/utils/adt/oid.c
@@ -257,7 +257,10 @@ Datum
 oidvectorrecv(PG_FUNCTION_ARGS)
 {
 	StringInfo	buf = (StringInfo) PG_GETARG_POINTER(0);
-	FunctionCallInfoData locfcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} locfcinfo;
 	oidvector  *result;
 
 	/*
@@ -266,19 +269,19 @@ oidvectorrecv(PG_FUNCTION_ARGS)
 	 * fcinfo->flinfo->fn_extra.  So we need to pass it our own flinfo
 	 * parameter.
 	 */
-	InitFunctionCallInfoData(locfcinfo, fcinfo->flinfo, 3,
+	InitFunctionCallInfoData(locfcinfo.fcinfo, fcinfo->flinfo, 3,
 							 InvalidOid, NULL, NULL);
 
-	locfcinfo.arg[0] = PointerGetDatum(buf);
-	locfcinfo.arg[1] = ObjectIdGetDatum(OIDOID);
-	locfcinfo.arg[2] = Int32GetDatum(-1);
-	locfcinfo.argnull[0] = false;
-	locfcinfo.argnull[1] = false;
-	locfcinfo.argnull[2] = false;
+	locfcinfo.fcinfo.args[0].datum = PointerGetDatum(buf);
+	locfcinfo.fcinfo.args[0].isnull = false;
+	locfcinfo.fcinfo.args[1].datum = ObjectIdGetDatum(OIDOID);
+	locfcinfo.fcinfo.args[1].isnull = false;
+	locfcinfo.fcinfo.args[2].datum = Int32GetDatum(-1);
+	locfcinfo.fcinfo.args[2].isnull = false;
 
-	result = (oidvector *) DatumGetPointer(array_recv(&locfcinfo));
+	result = (oidvector *) DatumGetPointer(array_recv(&locfcinfo.fcinfo));
 
-	Assert(!locfcinfo.isnull);
+	Assert(!locfcinfo.fcinfo.isnull);
 
 	/* sanity checks: oidvector must be 1-D, 0-based, no nulls */
 	if (ARR_NDIM(result) != 1 ||
diff --git a/src/backend/utils/adt/rowtypes.c b/src/backend/utils/adt/rowtypes.c
index 5f729342f8d..9b10a6b13c0 100644
--- a/src/backend/utils/adt/rowtypes.c
+++ b/src/backend/utils/adt/rowtypes.c
@@ -942,7 +942,10 @@ record_cmp(FunctionCallInfo fcinfo)
 		 */
 		if (!nulls1[i1] || !nulls2[i2])
 		{
-			FunctionCallInfoData locfcinfo;
+			union {
+				FunctionCallInfoData fcinfo;
+				char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+			} locfcinfo;
 			int32		cmpresult;
 
 			if (nulls1[i1])
@@ -959,14 +962,14 @@ record_cmp(FunctionCallInfo fcinfo)
 			}
 
 			/* Compare the pair of elements */
-			InitFunctionCallInfoData(locfcinfo, &typentry->cmp_proc_finfo, 2,
+			InitFunctionCallInfoData(locfcinfo.fcinfo, &typentry->cmp_proc_finfo, 2,
 									 collation, NULL, NULL);
-			locfcinfo.arg[0] = values1[i1];
-			locfcinfo.arg[1] = values2[i2];
-			locfcinfo.argnull[0] = false;
-			locfcinfo.argnull[1] = false;
-			locfcinfo.isnull = false;
-			cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo));
+			locfcinfo.fcinfo.args[0].datum = values1[i1];
+			locfcinfo.fcinfo.args[0].isnull = false;
+			locfcinfo.fcinfo.args[1].datum = values2[i2];
+			locfcinfo.fcinfo.args[1].isnull = false;
+			locfcinfo.fcinfo.isnull = false;
+			cmpresult = DatumGetInt32(FunctionCallInvoke(&locfcinfo.fcinfo));
 
 			if (cmpresult < 0)
 			{
@@ -1123,7 +1126,10 @@ record_eq(PG_FUNCTION_ARGS)
 		Form_pg_attribute att2;
 		TypeCacheEntry *typentry;
 		Oid			collation;
-		FunctionCallInfoData locfcinfo;
+		union {
+			FunctionCallInfoData fcinfo;
+			char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+		} locfcinfo;
 		bool		oprresult;
 
 		/*
@@ -1193,14 +1199,14 @@ record_eq(PG_FUNCTION_ARGS)
 			}
 
 			/* Compare the pair of elements */
-			InitFunctionCallInfoData(locfcinfo, &typentry->eq_opr_finfo, 2,
+			InitFunctionCallInfoData(locfcinfo.fcinfo, &typentry->eq_opr_finfo, 2,
 									 collation, NULL, NULL);
-			locfcinfo.arg[0] = values1[i1];
-			locfcinfo.arg[1] = values2[i2];
-			locfcinfo.argnull[0] = false;
-			locfcinfo.argnull[1] = false;
-			locfcinfo.isnull = false;
-			oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo));
+			locfcinfo.fcinfo.args[0].datum = values1[i1];
+			locfcinfo.fcinfo.args[0].isnull = false;
+			locfcinfo.fcinfo.args[1].datum = values2[i2];
+			locfcinfo.fcinfo.args[1].isnull = false;
+			locfcinfo.fcinfo.isnull = false;
+			oprresult = DatumGetBool(FunctionCallInvoke(&locfcinfo.fcinfo));
 			if (!oprresult)
 			{
 				result = false;
diff --git a/src/backend/utils/fmgr/fmgr.c b/src/backend/utils/fmgr/fmgr.c
index 6cbbd5b78b0..738979c03f1 100644
--- a/src/backend/utils/fmgr/fmgr.c
+++ b/src/backend/utils/fmgr/fmgr.c
@@ -782,7 +782,6 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
  *		Support routines for callers of fmgr-compatible functions
  *-------------------------------------------------------------------------
  */
-
 /*
  * These are for invocation of a specifically named function with a
  * directly-computed parameter list.  Note that neither arguments nor result
@@ -792,18 +791,21 @@ fmgr_security_definer(PG_FUNCTION_ARGS)
 Datum
 DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(1)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 1, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, NULL, 1, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.argnull[0] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
@@ -812,20 +814,23 @@ DirectFunctionCall1Coll(PGFunction func, Oid collation, Datum arg1)
 Datum
 DirectFunctionCall2Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(2)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 2, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, NULL, 2, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
@@ -835,22 +840,25 @@ Datum
 DirectFunctionCall3Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 						Datum arg3)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 3, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, NULL, 3, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
@@ -860,24 +868,27 @@ Datum
 DirectFunctionCall4Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 						Datum arg3, Datum arg4)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(4)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 4, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, NULL, 4, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
@@ -887,26 +898,29 @@ Datum
 DirectFunctionCall5Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 						Datum arg3, Datum arg4, Datum arg5)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(5)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 5, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, NULL, 5, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
+	d.fcinfo.args[4].datum = arg5;
+	d.fcinfo.args[4].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
@@ -917,28 +931,31 @@ DirectFunctionCall6Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 						Datum arg3, Datum arg4, Datum arg5,
 						Datum arg6)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(6)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 6, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, NULL, 6, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
+	d.fcinfo.args[4].datum = arg5;
+	d.fcinfo.args[4].isnull = false;
+	d.fcinfo.args[5].datum = arg6;
+	d.fcinfo.args[5].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
@@ -949,30 +966,33 @@ DirectFunctionCall7Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 						Datum arg3, Datum arg4, Datum arg5,
 						Datum arg6, Datum arg7)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(7)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 7, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, NULL, 7, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.arg[6] = arg7;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
-	fcinfo.argnull[6] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
+	d.fcinfo.args[4].datum = arg5;
+	d.fcinfo.args[4].isnull = false;
+	d.fcinfo.args[5].datum = arg6;
+	d.fcinfo.args[5].isnull = false;
+	d.fcinfo.args[6].datum = arg7;
+	d.fcinfo.args[6].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
@@ -983,32 +1003,35 @@ DirectFunctionCall8Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 						Datum arg3, Datum arg4, Datum arg5,
 						Datum arg6, Datum arg7, Datum arg8)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(8)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 8, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, NULL, 8, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.arg[6] = arg7;
-	fcinfo.arg[7] = arg8;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
-	fcinfo.argnull[6] = false;
-	fcinfo.argnull[7] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
+	d.fcinfo.args[4].datum = arg5;
+	d.fcinfo.args[4].isnull = false;
+	d.fcinfo.args[5].datum = arg6;
+	d.fcinfo.args[5].isnull = false;
+	d.fcinfo.args[6].datum = arg7;
+	d.fcinfo.args[6].isnull = false;
+	d.fcinfo.args[7].datum = arg8;
+	d.fcinfo.args[7].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
@@ -1020,34 +1043,37 @@ DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 						Datum arg6, Datum arg7, Datum arg8,
 						Datum arg9)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(9)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, NULL, 9, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, NULL, 9, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.arg[6] = arg7;
-	fcinfo.arg[7] = arg8;
-	fcinfo.arg[8] = arg9;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
-	fcinfo.argnull[6] = false;
-	fcinfo.argnull[7] = false;
-	fcinfo.argnull[8] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
+	d.fcinfo.args[4].datum = arg5;
+	d.fcinfo.args[4].isnull = false;
+	d.fcinfo.args[5].datum = arg6;
+	d.fcinfo.args[5].isnull = false;
+	d.fcinfo.args[6].datum = arg7;
+	d.fcinfo.args[6].isnull = false;
+	d.fcinfo.args[7].datum = arg8;
+	d.fcinfo.args[7].isnull = false;
+	d.fcinfo.args[8].datum = arg9;
+	d.fcinfo.args[8].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
@@ -1065,18 +1091,21 @@ DirectFunctionCall9Coll(PGFunction func, Oid collation, Datum arg1, Datum arg2,
 Datum
 CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(1)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 1, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.argnull[0] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
@@ -1085,25 +1114,53 @@ CallerFInfoFunctionCall1(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum
 Datum
 CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(2)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 2, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
 
-	result = (*func) (&fcinfo);
+	result = (*func) (&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
+	if (d.fcinfo.isnull)
 		elog(ERROR, "function %p returned NULL", (void *) func);
 
 	return result;
 }
 
+/*
+ * These are for invocation of a previously-looked-up function with a
+ * directly-computed parameter list.  Note that neither arguments nor result
+ * are allowed to be NULL.
+ */
+Datum
+FunctionCall0Coll(FmgrInfo *flinfo, Oid collation)
+{
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(0)];
+	} d;
+	Datum		result;
+
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 0, collation, NULL, NULL);
+
+	result = FunctionCallInvoke(&d.fcinfo);
+
+	/* Check for null result, since caller is clearly not expecting one */
+	if (d.fcinfo.isnull)
+		elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
+
+	return result;
+}
+
 /*
  * These are for invocation of a previously-looked-up function with a
  * directly-computed parameter list.  Note that neither arguments nor result
@@ -1112,19 +1169,22 @@ CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo, Oid collation, Datum
 Datum
 FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(1)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 1, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 1, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.argnull[0] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+	if (d.fcinfo.isnull)
+		elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
 
 	return result;
 }
@@ -1132,21 +1192,24 @@ FunctionCall1Coll(FmgrInfo *flinfo, Oid collation, Datum arg1)
 Datum
 FunctionCall2Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(2)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 2, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 2, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+	if (d.fcinfo.isnull)
+		elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
 
 	return result;
 }
@@ -1155,23 +1218,26 @@ Datum
 FunctionCall3Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 				  Datum arg3)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 3, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 3, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+	if (d.fcinfo.isnull)
+		elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
 
 	return result;
 }
@@ -1180,25 +1246,28 @@ Datum
 FunctionCall4Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 				  Datum arg3, Datum arg4)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(4)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 4, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 4, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+	if (d.fcinfo.isnull)
+		elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
 
 	return result;
 }
@@ -1207,27 +1276,30 @@ Datum
 FunctionCall5Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 				  Datum arg3, Datum arg4, Datum arg5)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(5)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 5, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 5, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
+	d.fcinfo.args[4].datum = arg5;
+	d.fcinfo.args[4].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+	if (d.fcinfo.isnull)
+		elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
 
 	return result;
 }
@@ -1237,29 +1309,32 @@ FunctionCall6Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 				  Datum arg3, Datum arg4, Datum arg5,
 				  Datum arg6)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(6)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 6, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 6, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
+	d.fcinfo.args[4].datum = arg5;
+	d.fcinfo.args[4].isnull = false;
+	d.fcinfo.args[5].datum = arg6;
+	d.fcinfo.args[5].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+	if (d.fcinfo.isnull)
+		elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
 
 	return result;
 }
@@ -1269,31 +1344,34 @@ FunctionCall7Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 				  Datum arg3, Datum arg4, Datum arg5,
 				  Datum arg6, Datum arg7)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(7)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 7, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 7, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.arg[6] = arg7;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
-	fcinfo.argnull[6] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
+	d.fcinfo.args[4].datum = arg5;
+	d.fcinfo.args[4].isnull = false;
+	d.fcinfo.args[5].datum = arg6;
+	d.fcinfo.args[5].isnull = false;
+	d.fcinfo.args[6].datum = arg7;
+	d.fcinfo.args[6].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+	if (d.fcinfo.isnull)
+		elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
 
 	return result;
 }
@@ -1303,33 +1381,36 @@ FunctionCall8Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 				  Datum arg3, Datum arg4, Datum arg5,
 				  Datum arg6, Datum arg7, Datum arg8)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(8)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 8, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 8, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.arg[6] = arg7;
-	fcinfo.arg[7] = arg8;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
-	fcinfo.argnull[6] = false;
-	fcinfo.argnull[7] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
+	d.fcinfo.args[4].datum = arg5;
+	d.fcinfo.args[4].isnull = false;
+	d.fcinfo.args[5].datum = arg6;
+	d.fcinfo.args[5].isnull = false;
+	d.fcinfo.args[6].datum = arg7;
+	d.fcinfo.args[6].isnull = false;
+	d.fcinfo.args[7].datum = arg8;
+	d.fcinfo.args[7].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+	if (d.fcinfo.isnull)
+		elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
 
 	return result;
 }
@@ -1340,35 +1421,38 @@ FunctionCall9Coll(FmgrInfo *flinfo, Oid collation, Datum arg1, Datum arg2,
 				  Datum arg6, Datum arg7, Datum arg8,
 				  Datum arg9)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(9)];
+	} d;
 	Datum		result;
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 9, collation, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 9, collation, NULL, NULL);
 
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.arg[6] = arg7;
-	fcinfo.arg[7] = arg8;
-	fcinfo.arg[8] = arg9;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
-	fcinfo.argnull[6] = false;
-	fcinfo.argnull[7] = false;
-	fcinfo.argnull[8] = false;
+	d.fcinfo.args[0].datum = arg1;
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = arg2;
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = arg3;
+	d.fcinfo.args[2].isnull = false;
+	d.fcinfo.args[3].datum = arg4;
+	d.fcinfo.args[3].isnull = false;
+	d.fcinfo.args[4].datum = arg5;
+	d.fcinfo.args[4].isnull = false;
+	d.fcinfo.args[5].datum = arg6;
+	d.fcinfo.args[5].isnull = false;
+	d.fcinfo.args[6].datum = arg7;
+	d.fcinfo.args[6].isnull = false;
+	d.fcinfo.args[7].datum = arg8;
+	d.fcinfo.args[7].isnull = false;
+	d.fcinfo.args[8].datum = arg9;
+	d.fcinfo.args[8].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", fcinfo.flinfo->fn_oid);
+	if (d.fcinfo.isnull)
+		elog(ERROR, "function %u returned NULL", flinfo->fn_oid);
 
 	return result;
 }
@@ -1385,68 +1469,30 @@ Datum
 OidFunctionCall0Coll(Oid functionId, Oid collation)
 {
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
-	Datum		result;
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 0, collation, NULL, NULL);
-
-	result = FunctionCallInvoke(&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
-	return result;
+	return FunctionCall0Coll(&flinfo, collation);
 }
 
 Datum
 OidFunctionCall1Coll(Oid functionId, Oid collation, Datum arg1)
 {
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
-	Datum		result;
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 1, collation, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.argnull[0] = false;
-
-	result = FunctionCallInvoke(&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
-	return result;
+	return FunctionCall1Coll(&flinfo, collation, arg1);
 }
 
 Datum
 OidFunctionCall2Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2)
 {
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
-	Datum		result;
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 2, collation, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-
-	result = FunctionCallInvoke(&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
-	return result;
+	return FunctionCall2Coll(&flinfo, collation, arg1, arg2);
 }
 
 Datum
@@ -1454,27 +1500,10 @@ OidFunctionCall3Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 					 Datum arg3)
 {
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
-	Datum		result;
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 3, collation, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-
-	result = FunctionCallInvoke(&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
-	return result;
+	return FunctionCall3Coll(&flinfo, collation, arg1, arg2, arg3);
 }
 
 Datum
@@ -1482,29 +1511,10 @@ OidFunctionCall4Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 					 Datum arg3, Datum arg4)
 {
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
-	Datum		result;
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 4, collation, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-
-	result = FunctionCallInvoke(&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
-	return result;
+	return FunctionCall4Coll(&flinfo, collation, arg1, arg2, arg3, arg4);
 }
 
 Datum
@@ -1512,31 +1522,10 @@ OidFunctionCall5Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 					 Datum arg3, Datum arg4, Datum arg5)
 {
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
-	Datum		result;
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 5, collation, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-
-	result = FunctionCallInvoke(&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
-	return result;
+	return FunctionCall5Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5);
 }
 
 Datum
@@ -1545,33 +1534,11 @@ OidFunctionCall6Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 					 Datum arg6)
 {
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
-	Datum		result;
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 6, collation, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
-
-	result = FunctionCallInvoke(&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
-	return result;
+	return FunctionCall6Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
+							 arg6);
 }
 
 Datum
@@ -1580,35 +1547,11 @@ OidFunctionCall7Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 					 Datum arg6, Datum arg7)
 {
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
-	Datum		result;
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 7, collation, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.arg[6] = arg7;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
-	fcinfo.argnull[6] = false;
-
-	result = FunctionCallInvoke(&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
-	return result;
+	return FunctionCall7Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
+							 arg6, arg7);
 }
 
 Datum
@@ -1617,37 +1560,11 @@ OidFunctionCall8Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 					 Datum arg6, Datum arg7, Datum arg8)
 {
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
-	Datum		result;
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 8, collation, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.arg[6] = arg7;
-	fcinfo.arg[7] = arg8;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
-	fcinfo.argnull[6] = false;
-	fcinfo.argnull[7] = false;
-
-	result = FunctionCallInvoke(&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
-	return result;
+	return FunctionCall8Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
+							 arg6, arg7, arg8);
 }
 
 Datum
@@ -1657,39 +1574,11 @@ OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 					 Datum arg9)
 {
 	FmgrInfo	flinfo;
-	FunctionCallInfoData fcinfo;
-	Datum		result;
 
 	fmgr_info(functionId, &flinfo);
 
-	InitFunctionCallInfoData(fcinfo, &flinfo, 9, collation, NULL, NULL);
-
-	fcinfo.arg[0] = arg1;
-	fcinfo.arg[1] = arg2;
-	fcinfo.arg[2] = arg3;
-	fcinfo.arg[3] = arg4;
-	fcinfo.arg[4] = arg5;
-	fcinfo.arg[5] = arg6;
-	fcinfo.arg[6] = arg7;
-	fcinfo.arg[7] = arg8;
-	fcinfo.arg[8] = arg9;
-	fcinfo.argnull[0] = false;
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
-	fcinfo.argnull[3] = false;
-	fcinfo.argnull[4] = false;
-	fcinfo.argnull[5] = false;
-	fcinfo.argnull[6] = false;
-	fcinfo.argnull[7] = false;
-	fcinfo.argnull[8] = false;
-
-	result = FunctionCallInvoke(&fcinfo);
-
-	/* Check for null result, since caller is clearly not expecting one */
-	if (fcinfo.isnull)
-		elog(ERROR, "function %u returned NULL", flinfo.fn_oid);
-
-	return result;
+	return FunctionCall9Coll(&flinfo, collation, arg1, arg2, arg3, arg4, arg5,
+							 arg6, arg7, arg8, arg9);
 }
 
 
@@ -1708,35 +1597,38 @@ OidFunctionCall9Coll(Oid functionId, Oid collation, Datum arg1, Datum arg2,
 Datum
 InputFunctionCall(FmgrInfo *flinfo, char *str, Oid typioparam, int32 typmod)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} d;
 	Datum		result;
 
 	if (str == NULL && flinfo->fn_strict)
 		return (Datum) 0;		/* just return null result */
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
 
-	fcinfo.arg[0] = CStringGetDatum(str);
-	fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
-	fcinfo.arg[2] = Int32GetDatum(typmod);
-	fcinfo.argnull[0] = (str == NULL);
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
+	d.fcinfo.args[0].datum = CStringGetDatum(str);
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = ObjectIdGetDatum(typioparam);
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = Int32GetDatum(typmod);
+	d.fcinfo.args[2].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Should get null result if and only if str is NULL */
 	if (str == NULL)
 	{
-		if (!fcinfo.isnull)
+		if (!d.fcinfo.isnull)
 			elog(ERROR, "input function %u returned non-NULL",
-				 fcinfo.flinfo->fn_oid);
+				 flinfo->fn_oid);
 	}
 	else
 	{
-		if (fcinfo.isnull)
+		if (d.fcinfo.isnull)
 			elog(ERROR, "input function %u returned NULL",
-				 fcinfo.flinfo->fn_oid);
+				 flinfo->fn_oid);
 	}
 
 	return result;
@@ -1767,35 +1659,38 @@ Datum
 ReceiveFunctionCall(FmgrInfo *flinfo, StringInfo buf,
 					Oid typioparam, int32 typmod)
 {
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} d;
 	Datum		result;
 
 	if (buf == NULL && flinfo->fn_strict)
 		return (Datum) 0;		/* just return null result */
 
-	InitFunctionCallInfoData(fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
+	InitFunctionCallInfoData(d.fcinfo, flinfo, 3, InvalidOid, NULL, NULL);
 
-	fcinfo.arg[0] = PointerGetDatum(buf);
-	fcinfo.arg[1] = ObjectIdGetDatum(typioparam);
-	fcinfo.arg[2] = Int32GetDatum(typmod);
-	fcinfo.argnull[0] = (buf == NULL);
-	fcinfo.argnull[1] = false;
-	fcinfo.argnull[2] = false;
+	d.fcinfo.args[0].datum = PointerGetDatum(buf);
+	d.fcinfo.args[0].isnull = false;
+	d.fcinfo.args[1].datum = ObjectIdGetDatum(typioparam);
+	d.fcinfo.args[1].isnull = false;
+	d.fcinfo.args[2].datum = Int32GetDatum(typmod);
+	d.fcinfo.args[2].isnull = false;
 
-	result = FunctionCallInvoke(&fcinfo);
+	result = FunctionCallInvoke(&d.fcinfo);
 
 	/* Should get null result if and only if buf is NULL */
 	if (buf == NULL)
 	{
-		if (!fcinfo.isnull)
+		if (!d.fcinfo.isnull)
 			elog(ERROR, "receive function %u returned non-NULL",
-				 fcinfo.flinfo->fn_oid);
+				 flinfo->fn_oid);
 	}
 	else
 	{
-		if (fcinfo.isnull)
+		if (d.fcinfo.isnull)
 			elog(ERROR, "receive function %u returned NULL",
-				 fcinfo.flinfo->fn_oid);
+				 flinfo->fn_oid);
 	}
 
 	return result;
diff --git a/src/backend/utils/sort/sortsupport.c b/src/backend/utils/sort/sortsupport.c
index 8c09fe4a430..31aa4100d67 100644
--- a/src/backend/utils/sort/sortsupport.c
+++ b/src/backend/utils/sort/sortsupport.c
@@ -26,10 +26,11 @@
 /* Info needed to use an old-style comparison function as a sort comparator */
 typedef struct
 {
-	FunctionCallInfoData fcinfo;	/* reusable callinfo structure */
 	FmgrInfo	flinfo;			/* lookup data for comparison function */
+	FunctionCallInfoData fcinfo;	/* reusable callinfo structure */
 } SortShimExtra;
 
+#define SizeForSortShimExtra(nargs) (offsetof(SortShimExtra, fcinfo) + SizeForFunctionCallInfoData(nargs))
 
 /*
  * Shim function for calling an old-style comparator
@@ -44,8 +45,8 @@ comparison_shim(Datum x, Datum y, SortSupport ssup)
 	SortShimExtra *extra = (SortShimExtra *) ssup->ssup_extra;
 	Datum		result;
 
-	extra->fcinfo.arg[0] = x;
-	extra->fcinfo.arg[1] = y;
+	extra->fcinfo.args[0].datum = x;
+	extra->fcinfo.args[1].datum = y;
 
 	/* just for paranoia's sake, we reset isnull each time */
 	extra->fcinfo.isnull = false;
@@ -69,7 +70,7 @@ PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup)
 	SortShimExtra *extra;
 
 	extra = (SortShimExtra *) MemoryContextAlloc(ssup->ssup_cxt,
-												 sizeof(SortShimExtra));
+												 SizeForSortShimExtra(2));
 
 	/* Lookup the comparison function */
 	fmgr_info_cxt(cmpFunc, &extra->flinfo, ssup->ssup_cxt);
@@ -77,8 +78,8 @@ PrepareSortSupportComparisonShim(Oid cmpFunc, SortSupport ssup)
 	/* We can initialize the callinfo just once and re-use it */
 	InitFunctionCallInfoData(extra->fcinfo, &extra->flinfo, 2,
 							 ssup->ssup_collation, NULL, NULL);
-	extra->fcinfo.argnull[0] = false;
-	extra->fcinfo.argnull[1] = false;
+	extra->fcinfo.args[0].isnull = false;
+	extra->fcinfo.args[1].isnull = false;
 
 	ssup->ssup_extra = extra;
 	ssup->comparator = comparison_shim;
diff --git a/src/include/executor/execExpr.h b/src/include/executor/execExpr.h
index 233d9d4094e..414a5193547 100644
--- a/src/include/executor/execExpr.h
+++ b/src/include/executor/execExpr.h
@@ -224,7 +224,8 @@ typedef enum ExprEvalOp
 	/* aggregation related nodes */
 	EEOP_AGG_STRICT_DESERIALIZE,
 	EEOP_AGG_DESERIALIZE,
-	EEOP_AGG_STRICT_INPUT_CHECK,
+	EEOP_AGG_STRICT_INPUT_CHECK_ARGS,
+	EEOP_AGG_STRICT_INPUT_CHECK_NULLS,
 	EEOP_AGG_INIT_TRANS,
 	EEOP_AGG_STRICT_TRANS_CHECK,
 	EEOP_AGG_PLAIN_TRANS_BYVAL,
@@ -600,7 +601,8 @@ typedef struct ExprEvalStep
 		/* for EEOP_AGG_STRICT_INPUT_CHECK */
 		struct
 		{
-			bool	   *nulls;
+			NullableDatum *args;
+			bool *nulls;
 			int			nargs;
 			int			jumpnull;
 		}			agg_strict_input_check;
diff --git a/src/include/executor/nodeAgg.h b/src/include/executor/nodeAgg.h
index 8fb8c8fe802..51aec33fd8d 100644
--- a/src/include/executor/nodeAgg.h
+++ b/src/include/executor/nodeAgg.h
@@ -158,12 +158,12 @@ typedef struct AggStatePerTransData
 	 * re-initializing the unchanging fields; which isn't much, but it seems
 	 * worth the extra space consumption.
 	 */
-	FunctionCallInfoData transfn_fcinfo;
+	FunctionCallInfo transfn_fcinfo;
 
 	/* Likewise for serialization and deserialization functions */
-	FunctionCallInfoData serialfn_fcinfo;
+	FunctionCallInfo serialfn_fcinfo;
 
-	FunctionCallInfoData deserialfn_fcinfo;
+	FunctionCallInfo deserialfn_fcinfo;
 }			AggStatePerTransData;
 
 /*
diff --git a/src/include/fmgr.h b/src/include/fmgr.h
index 101f513ba67..0928af0e954 100644
--- a/src/include/fmgr.h
+++ b/src/include/fmgr.h
@@ -84,11 +84,14 @@ typedef struct FunctionCallInfoData
 	bool		isnull;			/* function must set true if result is NULL */
 	short		nargs;			/* # arguments actually passed */
 #define FIELDNO_FUNCTIONCALLINFODATA_ARG 6
-	Datum		arg[FUNC_MAX_ARGS]; /* Arguments passed to function */
-#define FIELDNO_FUNCTIONCALLINFODATA_ARGNULL 7
-	bool		argnull[FUNC_MAX_ARGS]; /* T if arg[i] is actually NULL */
+#define FIELDNO_FUNCTIONCALLINFODATA_ARGNULL 6
+
+	NullableDatum args[FLEXIBLE_ARRAY_MEMBER];
+
 } FunctionCallInfoData;
 
+#define SizeForFunctionCallInfoData(nargs) (offsetof(FunctionCallInfoData, args) + sizeof(NullableDatum) * (nargs))
+
 /*
  * This routine fills a FmgrInfo struct, given the OID
  * of the function to be called.
@@ -141,7 +144,6 @@ extern void fmgr_symbol(Oid functionId, char **mod, char **fn);
  */
 #define FunctionCallInvoke(fcinfo)	((* (fcinfo)->flinfo->fn_addr) (fcinfo))
 
-
 /*-------------------------------------------------------------------------
  *		Support macros to ease writing fmgr-compatible functions
  *
@@ -176,7 +178,7 @@ extern void fmgr_symbol(Oid functionId, char **mod, char **fn);
  * If function is not marked "proisstrict" in pg_proc, it must check for
  * null arguments using this macro.  Do not try to GETARG a null argument!
  */
-#define PG_ARGISNULL(n)  (fcinfo->argnull[n])
+#define PG_ARGISNULL(n)  (fcinfo->args[n].isnull)
 
 /*
  * Support for fetching detoasted copies of toastable datatypes (all of
@@ -235,7 +237,7 @@ extern struct varlena *pg_detoast_datum_packed(struct varlena *datum);
 
 /* Macros for fetching arguments of standard types */
 
-#define PG_GETARG_DATUM(n)	 (fcinfo->arg[n])
+#define PG_GETARG_DATUM(n)	 (fcinfo->args[n].datum)
 #define PG_GETARG_INT32(n)	 DatumGetInt32(PG_GETARG_DATUM(n))
 #define PG_GETARG_UINT32(n)  DatumGetUInt32(PG_GETARG_DATUM(n))
 #define PG_GETARG_INT16(n)	 DatumGetInt16(PG_GETARG_DATUM(n))
@@ -514,6 +516,7 @@ extern Datum CallerFInfoFunctionCall2(PGFunction func, FmgrInfo *flinfo,
  * directly-computed parameter list.  Note that neither arguments nor result
  * are allowed to be NULL.
  */
+extern Datum FunctionCall0Coll(FmgrInfo *flinfo, Oid collation);
 extern Datum FunctionCall1Coll(FmgrInfo *flinfo, Oid collation,
 				  Datum arg1);
 extern Datum FunctionCall2Coll(FmgrInfo *flinfo, Oid collation,
diff --git a/src/include/nodes/execnodes.h b/src/include/nodes/execnodes.h
index da7f52cab09..af029c42af9 100644
--- a/src/include/nodes/execnodes.h
+++ b/src/include/nodes/execnodes.h
@@ -807,7 +807,7 @@ typedef struct SetExprState
 	 * (by InitFunctionCallInfoData) if func.fn_oid is valid.  It also saves
 	 * argument values between calls, when setArgsValid is true.
 	 */
-	FunctionCallInfoData fcinfo_data;
+	FunctionCallInfo fcinfo;
 } SetExprState;
 
 /* ----------------
diff --git a/src/include/postgres.h b/src/include/postgres.h
index b596fcb513e..b3ff25dc6e2 100644
--- a/src/include/postgres.h
+++ b/src/include/postgres.h
@@ -366,6 +366,13 @@ typedef struct
 
 typedef uintptr_t Datum;
 
+typedef struct NullableDatum
+{
+	Datum datum;
+	bool isnull;
+	/* FIXME: space for flags? */
+} NullableDatum;
+
 #define SIZEOF_DATUM SIZEOF_VOID_P
 
 /*
diff --git a/src/pl/plperl/plperl.c b/src/pl/plperl/plperl.c
index 4342c02b272..d3547e7835c 100644
--- a/src/pl/plperl/plperl.c
+++ b/src/pl/plperl/plperl.c
@@ -1875,7 +1875,11 @@ Datum
 plperl_inline_handler(PG_FUNCTION_ARGS)
 {
 	InlineCodeBlock *codeblock = (InlineCodeBlock *) PG_GETARG_POINTER(0);
-	FunctionCallInfoData fake_fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(0)];
+	} fake_fcinfodata;
+	FunctionCallInfo fake_fcinfo = &fake_fcinfodata.fcinfo;
 	FmgrInfo	flinfo;
 	plperl_proc_desc desc;
 	plperl_call_data *volatile save_call_data = current_call_data;
@@ -1897,10 +1901,10 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
 	 * plperl_call_perl_func().  In particular note that this sets things up
 	 * with no arguments passed, and a result type of VOID.
 	 */
-	MemSet(&fake_fcinfo, 0, sizeof(fake_fcinfo));
+	MemSet(&fake_fcinfodata, 0, sizeof(fake_fcinfodata));
 	MemSet(&flinfo, 0, sizeof(flinfo));
 	MemSet(&desc, 0, sizeof(desc));
-	fake_fcinfo.flinfo = &flinfo;
+	fake_fcinfo->flinfo = &flinfo;
 	flinfo.fn_oid = InvalidOid;
 	flinfo.fn_mcxt = CurrentMemoryContext;
 
@@ -1918,7 +1922,7 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
 	desc.nargs = 0;
 	desc.reference = NULL;
 
-	this_call_data.fcinfo = &fake_fcinfo;
+	this_call_data.fcinfo = fake_fcinfo;
 	this_call_data.prodesc = &desc;
 	/* we do not bother with refcounting the fake prodesc */
 
@@ -1938,7 +1942,7 @@ plperl_inline_handler(PG_FUNCTION_ARGS)
 		if (!desc.reference)	/* can this happen? */
 			elog(ERROR, "could not create internal procedure for anonymous code block");
 
-		perlret = plperl_call_perl_func(&desc, &fake_fcinfo);
+		perlret = plperl_call_perl_func(&desc, fake_fcinfo);
 
 		SvREFCNT_dec_current(perlret);
 
@@ -2192,11 +2196,11 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
 
 	for (i = 0; i < desc->nargs; i++)
 	{
-		if (fcinfo->argnull[i])
+		if (fcinfo->args[i].isnull)
 			PUSHs(&PL_sv_undef);
 		else if (desc->arg_is_rowtype[i])
 		{
-			SV		   *sv = plperl_hash_from_datum(fcinfo->arg[i]);
+			SV		   *sv = plperl_hash_from_datum(fcinfo->args[i].datum);
 
 			PUSHs(sv_2mortal(sv));
 		}
@@ -2206,15 +2210,15 @@ plperl_call_perl_func(plperl_proc_desc *desc, FunctionCallInfo fcinfo)
 			Oid			funcid;
 
 			if (OidIsValid(desc->arg_arraytype[i]))
-				sv = plperl_ref_from_pg_array(fcinfo->arg[i], desc->arg_arraytype[i]);
+				sv = plperl_ref_from_pg_array(fcinfo->args[i].datum, desc->arg_arraytype[i]);
 			else if ((funcid = get_transform_fromsql(argtypes[i], current_call_data->prodesc->lang_oid, current_call_data->prodesc->trftypes)))
-				sv = (SV *) DatumGetPointer(OidFunctionCall1(funcid, fcinfo->arg[i]));
+				sv = (SV *) DatumGetPointer(OidFunctionCall1(funcid, fcinfo->args[i].datum));
 			else
 			{
 				char	   *tmp;
 
 				tmp = OutputFunctionCall(&(desc->arg_out_func[i]),
-										 fcinfo->arg[i]);
+										 fcinfo->args[i].datum);
 				sv = cstr2sv(tmp);
 				pfree(tmp);
 			}
diff --git a/src/pl/plpgsql/src/pl_exec.c b/src/pl/plpgsql/src/pl_exec.c
index 3f2c3fbf9c2..2749f2a51f5 100644
--- a/src/pl/plpgsql/src/pl_exec.c
+++ b/src/pl/plpgsql/src/pl_exec.c
@@ -488,8 +488,8 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
 					PLpgSQL_var *var = (PLpgSQL_var *) estate.datums[n];
 
 					assign_simple_var(&estate, var,
-									  fcinfo->arg[i],
-									  fcinfo->argnull[i],
+									  fcinfo->args[i].datum,
+									  fcinfo->args[i].isnull,
 									  false);
 
 					/*
@@ -540,12 +540,12 @@ plpgsql_exec_function(PLpgSQL_function *func, FunctionCallInfo fcinfo,
 				{
 					PLpgSQL_rec *rec = (PLpgSQL_rec *) estate.datums[n];
 
-					if (!fcinfo->argnull[i])
+					if (!fcinfo->args[i].isnull)
 					{
 						/* Assign row value from composite datum */
 						exec_move_row_from_datum(&estate,
 												 (PLpgSQL_variable *) rec,
-												 fcinfo->arg[i]);
+												 fcinfo->args[i].datum);
 					}
 					else
 					{
diff --git a/src/pl/plpython/plpy_exec.c b/src/pl/plpython/plpy_exec.c
index 47ed95dcc60..d1a8c395ffd 100644
--- a/src/pl/plpython/plpy_exec.c
+++ b/src/pl/plpython/plpy_exec.c
@@ -436,10 +436,10 @@ PLy_function_build_args(FunctionCallInfo fcinfo, PLyProcedure *proc)
 		{
 			PLyDatumToOb *arginfo = &proc->args[i];
 
-			if (fcinfo->argnull[i])
+			if (fcinfo->args[i].isnull)
 				arg = NULL;
 			else
-				arg = PLy_input_convert(arginfo, fcinfo->arg[i]);
+				arg = PLy_input_convert(arginfo, fcinfo->args[i].datum);
 
 			if (arg == NULL)
 			{
diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index 12f7b137809..2865598d099 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -601,7 +601,12 @@ call_pltcl_start_proc(Oid prolang, bool pltrusted)
 	Form_pg_proc procStruct;
 	AclResult	aclresult;
 	FmgrInfo	finfo;
-	FunctionCallInfoData fcinfo;
+	union {
+		FunctionCallInfoData fcinfo;
+		char *fcinfo_data[SizeForFunctionCallInfoData(3)];
+	} fcinfodata;
+	FunctionCallInfo fcinfo = &fcinfodata.fcinfo;
+
 	PgStat_FunctionCallUsage fcusage;
 
 	/* select appropriate GUC */
@@ -662,11 +667,11 @@ call_pltcl_start_proc(Oid prolang, bool pltrusted)
 	 */
 	InvokeFunctionExecuteHook(procOid);
 	fmgr_info(procOid, &finfo);
-	InitFunctionCallInfoData(fcinfo, &finfo,
+	InitFunctionCallInfoData(*fcinfo, &finfo,
 							 0,
 							 InvalidOid, NULL, NULL);
-	pgstat_init_function_usage(&fcinfo, &fcusage);
-	(void) FunctionCallInvoke(&fcinfo);
+	pgstat_init_function_usage(fcinfo, &fcusage);
+	(void) FunctionCallInvoke(fcinfo);
 	pgstat_end_function_usage(&fcusage, true);
 
 	/* Pop the error context stack */
@@ -873,7 +878,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
 				/**************************************************
 				 * For tuple values, add a list for 'array set ...'
 				 **************************************************/
-				if (fcinfo->argnull[i])
+				if (fcinfo->args[i].isnull)
 					Tcl_ListObjAppendElement(NULL, tcl_cmd, Tcl_NewObj());
 				else
 				{
@@ -884,7 +889,7 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
 					HeapTupleData tmptup;
 					Tcl_Obj    *list_tmp;
 
-					td = DatumGetHeapTupleHeader(fcinfo->arg[i]);
+					td = DatumGetHeapTupleHeader(fcinfo->args[i].datum);
 					/* Extract rowtype info and find a tupdesc */
 					tupType = HeapTupleHeaderGetTypeId(td);
 					tupTypmod = HeapTupleHeaderGetTypMod(td);
@@ -905,14 +910,14 @@ pltcl_func_handler(PG_FUNCTION_ARGS, pltcl_call_state *call_state,
 				 * Single values are added as string element
 				 * of their external representation
 				 **************************************************/
-				if (fcinfo->argnull[i])
+				if (fcinfo->args[i].isnull)
 					Tcl_ListObjAppendElement(NULL, tcl_cmd, Tcl_NewObj());
 				else
 				{
 					char	   *tmp;
 
 					tmp = OutputFunctionCall(&prodesc->arg_out_func[i],
-											 fcinfo->arg[i]);
+											 fcinfo->args[i].datum);
 					UTF_BEGIN;
 					Tcl_ListObjAppendElement(NULL, tcl_cmd,
 											 Tcl_NewStringObj(UTF_E2U(tmp), -1));
-- 
2.17.0.rc1.dirty

Reply via email to