diff --git a/src/backend/optimizer/geqo/geqo_eval.c b/src/backend/optimizer/geqo/geqo_eval.c
index 093d09ba975dd20ef783cb2572bf0a460b81bf72..31a77f46e4a3a6de68f7a77e88eb8523547bf547 100644
--- a/src/backend/optimizer/geqo/geqo_eval.c
+++ b/src/backend/optimizer/geqo/geqo_eval.c
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: geqo_eval.c,v 1.36 1999/05/16 19:45:00 tgl Exp $
+ * $Id: geqo_eval.c,v 1.37 1999/05/17 00:25:34 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -36,6 +36,7 @@
 
 #include "utils/palloc.h"
 #include "utils/elog.h"
+#include "utils/portal.h"
 
 #include "optimizer/internal.h"
 #include "optimizer/paths.h"
@@ -48,6 +49,38 @@
 #include "optimizer/geqo_gene.h"
 #include "optimizer/geqo.h"
 
+/*
+ * Variables set by geqo_eval_startup for use within a single GEQO run
+ */
+static MemoryContext geqo_eval_context;
+
+/*
+ * geqo_eval_startup:
+ *   Must be called during geqo_main startup (before geqo_eval may be called)
+ *
+ * The main thing we need to do here is prepare a private memory context for
+ * allocation of temp storage used while constructing a path in geqo_eval().
+ * Since geqo_eval() will be called many times, we can't afford to let all
+ * that memory go unreclaimed until end of statement.  We use a special
+ * named portal to hold the context, so that it will be freed even if
+ * we abort via elog(ERROR).  The working data is allocated in the portal's
+ * heap memory context.
+ */
+void
+geqo_eval_startup(void)
+{
+#define GEQO_PORTAL_NAME	"<geqo workspace>"
+	Portal geqo_portal = GetPortalByName(GEQO_PORTAL_NAME);
+
+	if (!PortalIsValid(geqo_portal)) {
+		/* First time through (within current transaction, that is) */
+		geqo_portal = CreatePortal(GEQO_PORTAL_NAME);
+		Assert(PortalIsValid(geqo_portal));
+	}
+
+	geqo_eval_context = (MemoryContext) PortalGetHeapMemory(geqo_portal);
+}
+
 /*
  * geqo_eval
  *
@@ -56,23 +89,30 @@
 Cost
 geqo_eval(Query *root, Gene *tour, int num_gene)
 {
-	RelOptInfo *joinrel;
-	Cost		fitness;
-	List	   *temp;
+	MemoryContext	oldcxt;
+	RelOptInfo	   *joinrel;
+	Cost			fitness;
+	List		   *savelist;
+
+	/* preserve root->join_rel_list, which gimme_tree changes */
+	savelist = root->join_rel_list;
 
-	/* remember root->join_rel_list ... */
-	/* because root->join_rel_list will be changed during the following */
-	temp = listCopy(root->join_rel_list);
+	/* create a temporary allocation context for the path construction work */
+	oldcxt = MemoryContextSwitchTo(geqo_eval_context);
+	StartPortalAllocMode(DefaultAllocMode, 0);
 
-	/* joinrel is readily processed query tree -- left-sided ! */
+	/* construct the best path for the given combination of relations */
 	joinrel = gimme_tree(root, tour, 0, num_gene, NULL);
 
 	/* compute fitness */
 	fitness = (Cost) joinrel->cheapestpath->path_cost;
 
-	root->join_rel_list = temp;
+	/* restore join_rel_list */
+	root->join_rel_list = savelist;
 
-	pfree(joinrel);
+	/* release all the memory acquired within gimme_tree */
+	EndPortalAllocMode();
+	MemoryContextSwitchTo(oldcxt);
 
 	return fitness;
 }
diff --git a/src/backend/optimizer/geqo/geqo_main.c b/src/backend/optimizer/geqo/geqo_main.c
index 76beb7c2495471457cce13da3f5aada9a9c72ced..2cedda675bdb8406e36ce79156d7d7d250907629 100644
--- a/src/backend/optimizer/geqo/geqo_main.c
+++ b/src/backend/optimizer/geqo/geqo_main.c
@@ -6,7 +6,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: geqo_main.c,v 1.14 1999/02/18 04:55:54 momjian Exp $
+ * $Id: geqo_main.c,v 1.15 1999/05/17 00:25:33 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -70,44 +70,31 @@ geqo(Query *root)
 	Chromosome *momma;
 	Chromosome *daddy;
 	Chromosome *kid;
-
+	int			number_of_rels;
+	Pool	   *pool;
+	int			pool_size,
+				number_generations,
+				status_interval;
+	Gene	   *best_tour;
+	RelOptInfo *best_rel;
 #if defined(ERX)
 	Edge	   *edge_table;		/* list of edges */
 	int			edge_failures = 0;
 	float		difference;
-
 #endif
-
 #if defined(CX) || defined(PX) || defined(OX1) || defined(OX2)
 	City	   *city_table;		/* list of cities */
-
 #endif
-
 #if defined(CX)
 	int			cycle_diffs = 0;
 	int			mutations = 0;
-
 #endif
 
-
-	int			number_of_rels;
-
-	Pool	   *pool;
-	int			pool_size,
-				number_generations,
-				status_interval;
-
-	Gene	   *best_tour;
-	RelOptInfo *best_rel;
-
-/*	Plan *best_plan; */
-
-
 /* set tour size */
 	number_of_rels = length(root->base_rel_list);
 
 /* set GA parameters */
-	geqo_params(number_of_rels);/* out of "$PGDATA/pg_geqo" file */
+	geqo_params(number_of_rels);	/* read "$PGDATA/pg_geqo" file */
 	pool_size = PoolSize;
 	number_generations = Generations;
 	status_interval = 10;
@@ -115,6 +102,9 @@ geqo(Query *root)
 /* seed random number generator */
 	srandom(RandomSeed);
 
+/* initialize plan evaluator */
+	geqo_eval_startup();
+
 /* allocate genetic pool memory */
 	pool = alloc_pool(pool_size, number_of_rels);
 
diff --git a/src/backend/optimizer/geqo/geqo_params.c b/src/backend/optimizer/geqo/geqo_params.c
index 1c664c1b3b1f4abd31ec1c32a128de6925183985..130b6355ac6705de6fa9869457a8b13c2fc5ea06 100644
--- a/src/backend/optimizer/geqo/geqo_params.c
+++ b/src/backend/optimizer/geqo/geqo_params.c
@@ -5,7 +5,7 @@
 *
 * Copyright (c) 1994, Regents of the University of California
 *
-* $Id: geqo_params.c,v 1.14 1999/02/15 03:22:01 momjian Exp $
+* $Id: geqo_params.c,v 1.15 1999/05/17 00:25:33 tgl Exp $
 *
 *-------------------------------------------------------------------------
 */
@@ -45,6 +45,16 @@
 
 #include "storage/fd.h"
 
+/*
+ * Parameter values read from the config file (or defaulted) are stored here
+ * by geqo_params().
+ */
+int			PoolSize;
+int			Generations;
+long		RandomSeed;
+double		SelectionBias;
+
+
 #define POOL_TAG		"Pool_Size"
 #define TRIAL_TAG		"Generations"
 #define RAND_TAG		"Random_Seed"
@@ -77,7 +87,7 @@ geqo_params(int string_length)
 
 	char	   *conf_file;
 
-/* these static variables are used to signal that a value has been set */
+	/* these flag variables signal that a value has been set from the file */
 	int			pool_size = 0;
 	int			number_trials = 0;
 	int			random_seed = 0;
diff --git a/src/include/optimizer/geqo.h b/src/include/optimizer/geqo.h
index 9a4c61d4a0556e717df1e26be8e0dbe85d4418c6..aba1d86096b4a6ae8415e758cec702aac8cbfcf8 100644
--- a/src/include/optimizer/geqo.h
+++ b/src/include/optimizer/geqo.h
@@ -5,7 +5,7 @@
  *
  * Copyright (c) 1994, Regents of the University of California
  *
- * $Id: geqo.h,v 1.13 1999/02/18 04:55:54 momjian Exp $
+ * $Id: geqo.h,v 1.14 1999/05/17 00:25:32 tgl Exp $
  *
  *-------------------------------------------------------------------------
  */
@@ -56,27 +56,22 @@
 #define SELECTION_BIAS 2.0		/* selective pressure within population */
  /* should be 1.5 <= SELECTION_BIAS <= 2.0 */
 
-int			PoolSize;
-int			Generations;
+/* parameter values set in geqo_params.c */
+extern int			PoolSize;
+extern int			Generations;
+extern long			RandomSeed;
+extern double		SelectionBias;
 
-long		RandomSeed;			/* defaults to (long) time(NULL) in
-								 * geqo_params.c */
-double		SelectionBias;
-
-/* logarithmic base for rel->size decrease in case of long
-   queries that cause an integer overflow; used in geqo_eval.c */
-
-#define GEQO_LOG_BASE 1.5		/* should be 1.0 < GEQO_LOG_BASE <= 2.0 */
- /* ^^^						*/
-
-/* geqo prototypes */
+/* routines in geqo_main.c */
 extern RelOptInfo *geqo(Query *root);
 
+/* routines in geqo_params.c */
 extern void geqo_params(int string_length);
 
+/* routines in geqo_eval.c */
+extern void geqo_eval_startup(void);
 extern Cost geqo_eval(Query *root, Gene *tour, int num_gene);
 extern RelOptInfo *gimme_tree(Query *root, Gene *tour, int rel_count,
 							  int num_gene, RelOptInfo *old_rel);
 
-
 #endif	 /* GEQO_H */