diff --git a/src/pl/tcl/pltcl.c b/src/pl/tcl/pltcl.c
index d6b72f7d6862395a420f3455355c28ef7d407f10..48a3206da1ce8e51009889e37f153a5db110d7b6 100644
--- a/src/pl/tcl/pltcl.c
+++ b/src/pl/tcl/pltcl.c
@@ -2104,6 +2104,7 @@ static int
 pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
 				  int argc, CONST84 char *argv[])
 {
+	volatile MemoryContext plan_cxt = NULL;
 	int			nargs;
 	CONST84 char **args;
 	pltcl_query_desc *qdesc;
@@ -2132,13 +2133,24 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
 
 	/************************************************************
 	 * Allocate the new querydesc structure
+	 *
+	 * struct qdesc and subsidiary data all live in plan_cxt.  Note that if the
+	 * function is recompiled for whatever reason, permanent memory leaks
+	 * occur.  FIXME someday.
 	 ************************************************************/
-	qdesc = (pltcl_query_desc *) malloc(sizeof(pltcl_query_desc));
+	plan_cxt = AllocSetContextCreate(TopMemoryContext,
+									 "PL/TCL spi_prepare query",
+									 ALLOCSET_SMALL_MINSIZE,
+									 ALLOCSET_SMALL_INITSIZE,
+									 ALLOCSET_SMALL_MAXSIZE);
+	MemoryContextSwitchTo(plan_cxt);
+	qdesc = (pltcl_query_desc *) palloc0(sizeof(pltcl_query_desc));
 	snprintf(qdesc->qname, sizeof(qdesc->qname), "%p", qdesc);
 	qdesc->nargs = nargs;
-	qdesc->argtypes = (Oid *) malloc(nargs * sizeof(Oid));
-	qdesc->arginfuncs = (FmgrInfo *) malloc(nargs * sizeof(FmgrInfo));
-	qdesc->argtypioparams = (Oid *) malloc(nargs * sizeof(Oid));
+	qdesc->argtypes = (Oid *) palloc(nargs * sizeof(Oid));
+	qdesc->arginfuncs = (FmgrInfo *) palloc(nargs * sizeof(FmgrInfo));
+	qdesc->argtypioparams = (Oid *) palloc(nargs * sizeof(Oid));
+	MemoryContextSwitchTo(oldcontext);
 
 	/************************************************************
 	 * Execute the prepare inside a sub-transaction, so we can cope with
@@ -2166,7 +2178,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
 			getTypeInputInfo(typId, &typInput, &typIOParam);
 
 			qdesc->argtypes[i] = typId;
-			perm_fmgr_info(typInput, &(qdesc->arginfuncs[i]));
+			fmgr_info_cxt(typInput, &(qdesc->arginfuncs[i]), plan_cxt);
 			qdesc->argtypioparams[i] = typIOParam;
 		}
 
@@ -2193,10 +2205,7 @@ pltcl_SPI_prepare(ClientData cdata, Tcl_Interp *interp,
 	{
 		pltcl_subtrans_abort(interp, oldcontext, oldowner);
 
-		free(qdesc->argtypes);
-		free(qdesc->arginfuncs);
-		free(qdesc->argtypioparams);
-		free(qdesc);
+		MemoryContextDelete(plan_cxt);
 		ckfree((char *) args);
 
 		return TCL_ERROR;