specbind (Qcommand_debug_status, Qnil);
Lisp_Object val = Ffuncall (nargs, args);
- SAFE_FREE ();
- return unbind_to (speccount, val);
+ return SAFE_FREE_UNBIND_TO (speccount, val);
}
DEFUN ("prefix-numeric-value", Fprefix_numeric_value, Sprefix_numeric_value,
Lisp_Object volatile coding_systems_volatile = coding_systems;
Lisp_Object volatile current_dir_volatile = current_dir;
bool volatile display_p_volatile = display_p;
- bool volatile sa_must_free_volatile = sa_must_free;
int volatile fd_error_volatile = fd_error;
int volatile filefd_volatile = filefd;
ptrdiff_t volatile count_volatile = count;
coding_systems = coding_systems_volatile;
current_dir = current_dir_volatile;
display_p = display_p_volatile;
- sa_must_free = sa_must_free_volatile;
fd_error = fd_error_volatile;
filefd = filefd_volatile;
count = count_volatile;
when exiting. */
synch_process_pid = 0;
- SAFE_FREE ();
- unbind_to (count, Qnil);
+ SAFE_FREE_UNBIND_TO (count, Qnil);
if (!wait_ok)
return build_unibyte_string ("internal error");
}
obj = Fconcat (i, args);
- SAFE_FREE ();
+
+ /* No need to call SAFE_FREE, since signaling does that for us. */
+ (void) sa_count;
+
xsignal2 (Qerror, obj, wrong);
}
int offset;
EMACS_INT position;
Lisp_Object file, tem, pos;
- ptrdiff_t count;
+ ptrdiff_t count = SPECPDL_INDEX ();
USE_SAFE_ALLOCA;
if (INTEGERP (filepos))
return concat3 (cannot_open, file, quote_nl);
}
}
- count = SPECPDL_INDEX ();
record_unwind_protect_int (close_file_unwind, fd);
/* Seek only to beginning of disk block. */
}
p += nread;
}
- unbind_to (count, Qnil);
- SAFE_FREE ();
+ SAFE_FREE_UNBIND_TO (count, Qnil);
/* Sanity checking. */
if (CONSP (filepos))
memmove (buf, end, filled);
}
- SAFE_FREE ();
- return unbind_to (count, Qnil);
+ return SAFE_FREE_UNBIND_TO (count, Qnil);
}
\f
/* Return true if text quoting style should default to quote `like this'. */
return Qnil;
}
+ ptrdiff_t count = SPECPDL_INDEX ();
+
/* FIXME: It is not documented how to initialize the contents of the
context structure. This code cargo-cults from the existing
caller in src/analyze.c of GNU Diffutils, which appears to
eassert (! early_abort);
Fundo_boundary ();
- ptrdiff_t count = SPECPDL_INDEX ();
record_unwind_protect_excursion ();
ptrdiff_t i = size_a;
--i;
--j;
}
- unbind_to (count, Qnil);
- SAFE_FREE ();
- return Qnil;
+ return SAFE_FREE_UNBIND_TO (count, Qnil);
}
static void
if (buf == initial_buffer)
{
buf = xmalloc (bufsize);
- sa_must_free = true;
buf_save_value_index = SPECPDL_INDEX ();
record_unwind_protect_ptr (xfree, buf);
memcpy (buf, initial_buffer, used);
}
emacs_value ret = func->subr (env, nargs, args, func->data);
- SAFE_FREE ();
eassert (&priv == env->private_members);
maybe_quit ();
module_signal_or_throw (&priv);
- return unbind_to (count, value_to_lisp (ret));
+ return SAFE_FREE_UNBIND_TO (count, value_to_lisp (ret));
}
Lisp_Object
specbind (Qinternal_interpreter_environment, lexenv);
elt = Fprogn (XCDR (args));
- SAFE_FREE ();
- return unbind_to (count, elt);
+ return SAFE_FREE_UNBIND_TO (count, elt);
}
DEFUN ("while", Fwhile, Swhile, 1, UNEVALLED, 0,
#define USE_SAFE_ALLOCA \
ptrdiff_t sa_avail = MAX_ALLOCA; \
- ptrdiff_t sa_count = SPECPDL_INDEX (); bool sa_must_free = false
+ ptrdiff_t sa_count = SPECPDL_INDEX ()
#define AVAIL_ALLOCA(size) (sa_avail -= (size), alloca (size))
#define SAFE_ALLOCA(size) ((size) <= sa_avail \
? AVAIL_ALLOCA (size) \
- : (sa_must_free = true, record_xmalloc (size)))
+ : record_xmalloc (size))
/* SAFE_NALLOCA sets BUF to a newly allocated array of MULTIPLIER *
NITEMS items, each of the same type as *BUF. MULTIPLIER must
else \
{ \
(buf) = xnmalloc (nitems, sizeof *(buf) * (multiplier)); \
- sa_must_free = true; \
record_unwind_protect_ptr (xfree, buf); \
} \
} while (false)
memcpy (ptr, SDATA (string), SBYTES (string) + 1); \
} while (false)
-/* SAFE_FREE frees xmalloced memory and enables GC as needed. */
+/* Free xmalloced memory and enable GC as needed. */
-#define SAFE_FREE() \
- do { \
- if (sa_must_free) { \
- sa_must_free = false; \
- unbind_to (sa_count, Qnil); \
- } \
- } while (false)
+#define SAFE_FREE() safe_free (sa_count)
+
+INLINE void
+safe_free (ptrdiff_t sa_count)
+{
+ while (specpdl_ptr != specpdl + sa_count)
+ {
+ specpdl_ptr--;
+ eassert (specpdl_ptr->kind == SPECPDL_UNWIND_PTR
+ && specpdl_ptr->unwind_ptr.func == xfree);
+ xfree (specpdl_ptr->unwind_ptr.arg);
+ }
+}
+
+/* Pop the specpdl stack back to COUNT, and return VAL.
+ Prefer this to { SAFE_FREE (); unbind_to (COUNT, VAL); }
+ when COUNT predates USE_SAFE_ALLOCA, as it is a bit more efficient
+ and also lets callers intermix SAFE_ALLOCA calls with other calls
+ that grow the specpdl stack. */
+
+#define SAFE_FREE_UNBIND_TO(count, val) \
+ safe_free_unbind_to (count, sa_count, val)
+
+INLINE Lisp_Object
+safe_free_unbind_to (ptrdiff_t count, ptrdiff_t sa_count, Lisp_Object val)
+{
+ eassert (count <= sa_count);
+ return unbind_to (count, val);
+}
/* Set BUF to point to an allocated array of NELT Lisp_Objects,
immediately followed by EXTRA spare bytes. */
{ \
(buf) = xmalloc (alloca_nbytes); \
record_unwind_protect_array (buf, nelt); \
- sa_must_free = true; \
} \
} while (false)
else
create_pty (proc);
- SAFE_FREE ();
- return unbind_to (count, proc);
+ return SAFE_FREE_UNBIND_TO (count, proc);
}
/* If PROC doesn't have its pid set, then an error was signaled and
/* Like USE_SAFE_ALLOCA, but use emacs_re_safe_alloca. */
# define REGEX_USE_SAFE_ALLOCA \
ptrdiff_t sa_avail = emacs_re_safe_alloca; \
- ptrdiff_t sa_count = SPECPDL_INDEX (); bool sa_must_free = false
+ ptrdiff_t sa_count = SPECPDL_INDEX ()
# define REGEX_SAFE_FREE() SAFE_FREE ()
# define REGEX_ALLOCATE SAFE_ALLOCA
tty_menu_end:
- SAFE_FREE ();
- unbind_to (specpdl_count, Qnil);
- return entry;
+ return SAFE_FREE_UNBIND_TO (specpdl_count, entry);
}
#endif /* !MSDOS */
so there is no possibility of wanting to redisplay. */
val = internal_condition_case_n (Ffuncall, nargs, args, Qt,
safe_eval_handler);
- SAFE_FREE ();
- val = unbind_to (count, val);
+ val = SAFE_FREE_UNBIND_TO (count, val);
}
return val;
return_entry:
unblock_input ();
- SAFE_FREE ();
- return unbind_to (specpdl_count, entry);
+ return SAFE_FREE_UNBIND_TO (specpdl_count, entry);
}
#endif /* not USE_X_TOOLKIT */