Index: proto/misc2.pro
===================================================================
--- proto/misc2.pro	(revision 209)
+++ proto/misc2.pro	(working copy)
@@ -50,6 +50,7 @@
 extern void ga_clear_strings __ARGS((garray_T *gap));
 extern void ga_init __ARGS((garray_T *gap));
 extern void ga_init2 __ARGS((garray_T *gap, int itemsize, int growsize));
+extern void ga_init3 __ARGS((garray_T *gap, int itemsize, int growsize, int growaccel));
 extern int ga_grow __ARGS((garray_T *gap, int n));
 extern void ga_concat __ARGS((garray_T *gap, char_u *s));
 extern void ga_append __ARGS((garray_T *gap, int c));
Index: regexp.c
===================================================================
--- regexp.c	(revision 209)
+++ regexp.c	(working copy)
@@ -378,14 +378,6 @@
 
 static char_u		*reg_prev_sub = NULL;
 
-#if defined(EXITFREE) || defined(PROTO)
-    void
-free_regexp_stuff()
-{
-    vim_free(reg_prev_sub);
-}
-#endif
-
 /*
  * REGEXP_INRANGE contains all characters which are always special in a []
  * range after '\'.
@@ -3332,7 +3324,20 @@
     return r;
 }
 
+
 /*
+ * Both for regstack and backpos tables we use the following strategy of
+ * allocation (to reduce malloc/free calls). Initial size is the size of table
+ * with which it is created. After executing the match we check the size of the
+ * table and free the memory only if the array has grown more than initial
+ * capacity. The idea is simple: keep the memory across the calls in case of
+ * shallow regexps but don't allow to hold a lot of memory after some
+ * memory-requiring search.
+ */
+#define REGSTACK_INITIAL    2048
+#define BACKPOS_INITIAL     16
+
+/*
  * Match a regexp against a string ("line" points to the string) or multiple
  * lines ("line" is NULL, use reg_getline()).
  */
@@ -3345,16 +3350,14 @@
     char_u	*s;
     long	retval = 0L;
 
-    reg_tofree = NULL;
+    /* Creating regstack and backpos tables if they are not created yet.
+     * The tables will be growing arrays with dynamic grow size -
+     * doubling on each grow. */
+    if (regstack.ga_data == NULL)
+        ga_init3(&regstack, 1, REGSTACK_INITIAL, 100);
+    if (backpos.ga_data == NULL)
+        ga_init3(&backpos, sizeof(backpos_T), BACKPOS_INITIAL, 100);
 
-    /* Init the regstack empty.  Use an item size of 1 byte, since we push
-     * different things onto it.  Use a large grow size to avoid reallocating
-     * it too often. */
-    ga_init2(&regstack, 1, 10000);
-
-    /* Init the backpos table empty. */
-    ga_init2(&backpos, sizeof(backpos_T), 10);
-
     if (REG_MULTI)
     {
 	prog = reg_mmatch->regprog;
@@ -3524,9 +3527,18 @@
     }
 
 theend:
-    vim_free(reg_tofree);
-    ga_clear(&regstack);
-    ga_clear(&backpos);
+    /*
+     * Check regstack and backpos tables for their current size. If the size
+     * is higher than initial capacity - free the tables.
+     */
+    if (regstack.ga_maxlen > REGSTACK_INITIAL)
+    {
+        ga_clear(&regstack);
+    }
+    if (backpos.ga_maxlen > BACKPOS_INITIAL)
+    {
+        ga_clear(&backpos);
+    }
 
     return retval;
 }
@@ -3716,8 +3728,8 @@
 #define RA_MATCH	4	/* successful match */
 #define RA_NOMATCH	5	/* didn't match */
 
-  /* Init the regstack and backpos table empty.  They are initialized and
-   * freed in vim_regexec_both() to reduce malloc()/free() calls. */
+  /* Initialize tables regstack and backpos to empty state. They are
+   * managed in vim_regexec_both() to reduce malloc()/free() calls. */
   regstack.ga_len = 0;
   backpos.ga_len = 0;
 
@@ -7044,6 +7056,17 @@
     return (int)((dst - dest) + 1);
 }
 
+#if defined(EXITFREE) || defined(PROTO)
+    void
+free_regexp_stuff()
+{
+    ga_clear(&regstack);
+    ga_clear(&backpos);
+    vim_free(reg_tofree);
+    vim_free(reg_prev_sub);
+}
+#endif
+
 #ifdef FEAT_EVAL
 /*
  * Used for the submatch() function: get the string from tne n'th submatch in
Index: structs.h
===================================================================
--- structs.h	(revision 209)
+++ structs.h	(working copy)
@@ -59,6 +59,8 @@
     int	    ga_itemsize;	    /* sizeof(item) */
     int	    ga_growsize;	    /* number of items to grow each time */
     void    *ga_data;		    /* pointer to the first item */
+    int     ga_growaccel;	    /* factor of increasing the grow size on
+				       each array grow, in percents. */
 } garray_T;
 
 #define GA_EMPTY    {0, 0, 0, 0, NULL}
Index: misc2.c
===================================================================
--- misc2.c	(revision 209)
+++ misc2.c	(working copy)
@@ -1075,7 +1075,7 @@
     ResetRedobuff();
     ResetRedobuff();
 
-#ifdef FEAT_CLIENTSERVER
+#if defined(FEAT_CLIENTSERVER) && defined(FEAT_X11)
     vim_free(serverDelayedStartName);
 #endif
 
@@ -1867,7 +1867,7 @@
 
 /*
  * Initialize a growing array.	Don't forget to set ga_itemsize and
- * ga_growsize!  Or use ga_init2().
+ * ga_growsize!  Or use ga_init2()/ga_init3().
  */
     void
 ga_init(gap)
@@ -1876,6 +1876,7 @@
     gap->ga_data = NULL;
     gap->ga_maxlen = 0;
     gap->ga_len = 0;
+    gap->ga_growaccel = 0;
 }
 
     void
@@ -1885,11 +1886,29 @@
     int		growsize;
 {
     ga_init(gap);
-    gap->ga_itemsize = itemsize;
-    gap->ga_growsize = growsize;
+    gap->ga_itemsize  = itemsize;
+    gap->ga_growsize  = growsize;
 }
 
 /*
+ * Initialize growing array with accelerating grow size. On each grow the grow
+ * size will be increased by ga_growaccel percents. That is, setting
+ * grow acceleration to 100 means doubling the grow size on each grow; setting
+ * it to 50 means increasing grow size by 50% etc. Zero value means constant
+ * grow size - this is what you get in ga_init2 by default.
+ */
+    void
+ga_init3(gap, itemsize, growsize, growaccel)
+    garray_T	*gap;
+    int		itemsize;
+    int		growsize;
+    int		growaccel;
+{
+    ga_init2(gap, itemsize, growsize);
+    gap->ga_growaccel = growaccel;
+}
+
+/*
  * Make room in growing array "gap" for at least "n" items.
  * Return FAIL for failure, OK otherwise.
  */
@@ -1905,6 +1924,7 @@
     {
 	if (n < gap->ga_growsize)
 	    n = gap->ga_growsize;
+	gap->ga_growsize += gap->ga_growsize * gap->ga_growaccel / 100;
 	len = gap->ga_itemsize * (gap->ga_len + n);
 	pp = alloc_clear((unsigned)len);
 	if (pp == NULL)
Index: os_mswin.c
===================================================================
--- os_mswin.c	(revision 209)
+++ os_mswin.c	(working copy)
@@ -239,6 +239,11 @@
 
     if (gui.in_use)
 	gui_exit(r);
+
+#ifdef EXITFREE
+    free_all_mem();
+#endif
+
     exit(r);
 }
 
