summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/eval.c8
-rw-r--r--src/getchar.c34
-rw-r--r--src/globals.h13
-rw-r--r--src/main.c10
-rw-r--r--src/version.c2
5 files changed, 56 insertions, 11 deletions
diff --git a/src/eval.c b/src/eval.c
index 162cdf4c..5b5bfbc7 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -6074,6 +6074,10 @@ garbage_collect()
tabpage_T *tp;
#endif
+ /* Only do this once. */
+ want_garbage_collect = FALSE;
+ may_garbage_collect = FALSE;
+
/*
* 1. Go through all accessible variables and mark all lists and dicts
* with copyID.
@@ -9636,7 +9640,9 @@ f_garbagecollect(argvars, rettv)
typval_T *argvars;
typval_T *rettv;
{
- garbage_collect();
+ /* This is postponed until we are back at the toplevel, because we may be
+ * using Lists and Dicts internally. E.g.: ":echo [garbagecollect()]". */
+ want_garbage_collect = TRUE;
}
/*
diff --git a/src/getchar.c b/src/getchar.c
index 7d2cfd78..f840e0bd 100644
--- a/src/getchar.c
+++ b/src/getchar.c
@@ -1451,7 +1451,8 @@ before_blocking()
{
updatescript(0);
#ifdef FEAT_EVAL
- garbage_collect();
+ if (may_garbage_collect)
+ garbage_collect();
#endif
}
@@ -1502,6 +1503,13 @@ vgetc()
int i;
#endif
+#ifdef FEAT_EVAL
+ /* Do garbage collection when garbagecollect() was called previously and
+ * we are now at the toplevel. */
+ if (may_garbage_collect && want_garbage_collect)
+ garbage_collect();
+#endif
+
/*
* If a character was put back with vungetc, it was already processed.
* Return it directly.
@@ -1511,13 +1519,13 @@ vgetc()
c = old_char;
old_char = -1;
mod_mask = old_mod_mask;
- return c;
}
-
- mod_mask = 0x0;
- last_recorded_len = 0;
- for (;;) /* this is done twice if there are modifiers */
+ else
{
+ mod_mask = 0x0;
+ last_recorded_len = 0;
+ for (;;) /* this is done twice if there are modifiers */
+ {
if (mod_mask) /* no mapping after modifier has been read */
{
++no_mapping;
@@ -1695,8 +1703,20 @@ vgetc()
}
#endif
- return c;
+ break;
+ }
}
+
+#ifdef FEAT_EVAL
+ /*
+ * In the main loop "may_garbage_collect" can be set to do garbage
+ * collection in the first next vgetc(). It's disabled after that to
+ * avoid internally used Lists and Dicts to be freed.
+ */
+ may_garbage_collect = FALSE;
+#endif
+
+ return c;
}
/*
diff --git a/src/globals.h b/src/globals.h
index 4106742a..b768127f 100644
--- a/src/globals.h
+++ b/src/globals.h
@@ -300,9 +300,16 @@ EXTERN except_T *caught_stack INIT(= NULL);
#endif
#ifdef FEAT_EVAL
-EXTERN scid_T current_SID INIT(= 0); /* ID of script being sourced or
- was sourced to define the
- current function. */
+/* Garbage collection can only take place when we are sure there are no Lists
+ * or Dictionaries being used internally. This is flagged with
+ * "may_garbage_collect" when we are at the toplevel.
+ * "want_garbage_collect" is set by the garbagecollect() function, which means
+ * we do garbage collection before waiting for a char at the toplevel. */
+EXTERN int may_garbage_collect INIT(= FALSE);
+EXTERN int want_garbage_collect INIT(= FALSE);
+
+/* ID of script being sourced or was sourced to define the current function. */
+EXTERN scid_T current_SID INIT(= 0);
#endif
#if defined(FEAT_EVAL) || defined(FEAT_SYN_HL)
diff --git a/src/main.c b/src/main.c
index 5051adbf..f903d06e 100644
--- a/src/main.c
+++ b/src/main.c
@@ -1130,6 +1130,16 @@ main_loop(cmdwin, noexmode)
*/
update_curswant();
+#ifdef FEAT_EVAL
+ /*
+ * May perform garbage collection when waiting for a character, but
+ * only at the very toplevel. Otherwise we may be using a List or
+ * Dict internally somewhere.
+ * "may_garbage_collect" is reset in vgetc() which is invoked through
+ * do_exmode() and normal_cmd().
+ */
+ may_garbage_collect = (!cmdwin && !noexmode);
+#endif
/*
* If we're invoked as ex, do a round of ex commands.
* Otherwise, get and execute a normal mode command.
diff --git a/src/version.c b/src/version.c
index aeab51e4..cac03679 100644
--- a/src/version.c
+++ b/src/version.c
@@ -667,6 +667,8 @@ static char *(features[]) =
static int included_patches[] =
{ /* Add new patch number below this line */
/**/
+ 84,
+/**/
83,
/**/
82,