unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Paul Eggert <eggert@cs.ucla.edu>
To: Stefan Monnier <monnier@iro.umontreal.ca>
Cc: emacs-devel@gnu.org
Subject: Re: inlinable functions instead of macros
Date: Fri, 24 Aug 2012 14:37:21 -0700	[thread overview]
Message-ID: <5037F411.4010905@cs.ucla.edu> (raw)
In-Reply-To: <jwvsjbfxapf.fsf-monnier+emacs@gnu.org>

On 08/22/2012 07:31 AM, Stefan Monnier wrote:
> It was working simply and effectively

It's simple to put easserts into macros, but as you know this has
problems that make the macros hard to use.  They cannot be invoked
from GDB, which complicates debugging.  More important, callers
sometimes cannot specify arguments with side effects, and this
restriction makes callers error-prone.  We've tried to address some of
the side-effect issues with this hack:

   /* The IDX==IDX tries to detect when the macro argument is side-effecting.  */
   #define ASET(ARRAY, IDX, VAL)	\
	 (eassert ((IDX) == (IDX)),				\
	  eassert ((IDX) >= 0 && (IDX) < ASIZE (ARRAY)),	\
	  XVECTOR (ARRAY)->contents[IDX] = (VAL))

but even this hack doesn't catch the side-effect problem reliably,
and anyway it's better to not introduce further problems like this.

Here's how I'd like to address this issue:

 1. Revert the setters and getters (e.g., bset_filename, BVAR)
    and go back to ordinary field accesses, as described in
    <http://bugs.gnu.org/12215#61>.  This will simplify the problem
    by reducing the number of functions/macros affected.
    We're still working on the details here but it's clear that
    most of these functions will go.

 2. Revert the easserts recently added to Emacs that are contributing
    to this problem.  We went without these easserts for years, and
    there's no particular reason to add them now if they cause problems.

 3. Assuming (1) and (2), only two problematic easserts remain: in
    blv_found and set_blv_found.  Address them with the simple solution
    that Sam Steingold proposed in
    <http://lists.gnu.org/archive/html/emacs-devel/2012-08/msg00641.html>,
    combined with an externally-visible wrapper for GDB's sake.

 4. After 24.3, look into fixing the side-effect problem for ASET and
    other macros too, as described in Bug#11935.  That's a bigger
    project, but it will have other benefits too.

Here's a patch to implement (2) and (3); it assumes the patch
mentioned in (1).  This patch makes Emacs a tiny bit smaller with
the default build, so it should be OK on efficiency grounds.

=== modified file 'src/ChangeLog'
--- src/ChangeLog	2012-08-24 04:43:52 +0000
+++ src/ChangeLog	2012-08-24 21:24:45 +0000
@@ -1,5 +1,17 @@
 2012-08-24  Paul Eggert  <eggert@cs.ucla.edu>
 
+	Report better line numbers when assertions fail (Bug#12215).
+	* alloc.c, lisp.h (LISP_INLINE_EXTERNALLY_VISIBLE): New macro.
+	* buffer.h (buffer_intervals, set_buffer_intervals):
+	* lisp.h (gc_aset, vcopy): Remove recently-introduced easserts, as
+	they're not that useful in practice and they emit bogus line numbers.
+	* lisp.h (eassert, blv_found, set_blv_found):
+	Reimplement in terms of eassert_f, blv_found_f, set_blv_found_f.
+	(eassert_f, blv_found_f, set_blv_found_f): New macros or functions,
+	containing the guts of the old, but which let the caller specify
+	file and line number.
+	(blv_found, set_blv_found): Also define as a function, for GDB.
+
 	Remove setters like bset_keymap and getters like BVAR (Bug#12215).
 	They make the code harder to read, and for now they don't
 	bring anything to the table.  Open-code them instead.

=== modified file 'src/alloc.c'
--- src/alloc.c	2012-08-23 06:49:09 +0000
+++ src/alloc.c	2012-08-24 21:24:45 +0000
@@ -21,6 +21,7 @@
 #include <config.h>
 
 #define LISP_INLINE EXTERN_INLINE
+#define LISP_INLINE_EXTERNALLY_VISIBLE EXTERN_INLINE EXTERNALLY_VISIBLE
 
 #include <stdio.h>
 #include <limits.h>		/* For CHAR_BIT.  */

=== modified file 'src/buffer.h'
--- src/buffer.h	2012-08-24 04:43:52 +0000
+++ src/buffer.h	2012-08-24 21:24:45 +0000
@@ -948,7 +948,6 @@
 BUFFER_INLINE INTERVAL
 buffer_intervals (struct buffer *b)
 {
-  eassert (b->text != NULL);
   return b->text->intervals;
 }
 
@@ -957,7 +956,6 @@
 BUFFER_INLINE void
 set_buffer_intervals (struct buffer *b, INTERVAL i)
 {
-  eassert (b->text != NULL);
   b->text->intervals = i;
 }
 

=== modified file 'src/lisp.h'
--- src/lisp.h	2012-08-24 04:43:52 +0000
+++ src/lisp.h	2012-08-24 21:24:45 +0000
@@ -32,6 +32,7 @@
 INLINE_HEADER_BEGIN
 #ifndef LISP_INLINE
 # define LISP_INLINE INLINE
+# define LISP_INLINE_EXTERNALLY_VISIBLE INLINE
 #endif
 
 /* The ubiquitous max and min macros.  */
@@ -110,8 +111,13 @@
 /* Define an Emacs version of 'assert (COND)', since some
    system-defined 'assert's are flaky.  COND should be free of side
    effects; it may or may not be evaluated.  */
+
+#define eassert(cond) eassert_f (cond, __FILE__, __LINE__)
+
 #ifndef ENABLE_CHECKING
-# define eassert(X) ((void) (0 && (X))) /* Check that X compiles.  */
+  /* Do nothing, but check that args compile. */
+# define eassert_f(cond, file, line) \
+    ((void) (0 && (cond) && (file)[(line) >> 31]))
 #else /* ENABLE_CHECKING */
 
 extern _Noreturn void die (const char *, const char *, int);
@@ -126,10 +132,10 @@
    testing that STRINGP (x) is true, making the test redundant.  */
 extern bool suppress_checking EXTERNALLY_VISIBLE;
 
-# define eassert(cond)						\
+# define eassert_f(cond, file, line)				\
    ((cond) || suppress_checking					\
     ? (void) 0							\
-    : die ("assertion failed: " # cond, __FILE__, __LINE__))
+    : die ("assertion failed: " # cond, file, line))
 #endif /* ENABLE_CHECKING */
 \f
 /* Use the configure flag --enable-check-lisp-object-type to make
@@ -2335,7 +2341,6 @@
 {
   /* Like ASET, but also can be used in the garbage collector:
      sweep_weak_table calls set_hash_key etc. while the table is marked.  */
-  eassert (0 <= idx && idx < (ASIZE (array) & ~ARRAY_MARK_FLAG));
   XVECTOR (array)->contents[idx] = val;
 }
 
@@ -2344,7 +2349,6 @@
 LISP_INLINE void
 vcopy (Lisp_Object v, ptrdiff_t offset, Lisp_Object *args, ptrdiff_t count)
 {
-  eassert (0 <= offset && 0 <= count && offset + count <= ASIZE (v));
   memcpy (XVECTOR (v)->contents + offset, args, count * sizeof *args);
 }
 
@@ -2383,18 +2387,33 @@
 /* Buffer-local (also frame-local) variable access functions.  */
 
 LISP_INLINE int
-blv_found (struct Lisp_Buffer_Local_Value *blv)
+blv_found_f (struct Lisp_Buffer_Local_Value *blv, char const *file, int line)
 {
-  eassert (blv->found == !EQ (blv->defcell, blv->valcell));
+  eassert_f (blv->found == !EQ (blv->defcell, blv->valcell), file, line);
   return blv->found;
 }
+#define blv_found(blv) \
+     blv_found_f (blv, __FILE__, __LINE__)
+LISP_INLINE_EXTERNALLY_VISIBLE int
+(blv_found) (struct Lisp_Buffer_Local_Value *blv)
+{
+  return blv_found (blv);
+}
 
 LISP_INLINE void
-set_blv_found (struct Lisp_Buffer_Local_Value *blv, int found)
+set_blv_found_f (struct Lisp_Buffer_Local_Value *blv, int found,
+		 char const *file, int line)
 {
-  eassert (found == !EQ (blv->defcell, blv->valcell));
+  eassert_f (found == !EQ (blv->defcell, blv->valcell), file, line);
   blv->found = found;
 }
+#define set_blv_found(blv, found) \
+     set_blv_found_f (blv, found, __FILE__, __LINE__)
+LISP_INLINE_EXTERNALLY_VISIBLE void
+(set_blv_found) (struct Lisp_Buffer_Local_Value *blv, int found)
+{
+  set_blv_found (blv, found);
+}
 
 LISP_INLINE Lisp_Object
 blv_value (struct Lisp_Buffer_Local_Value *blv)




  reply	other threads:[~2012-08-24 21:37 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2012-08-17 23:48 inlinable functions instead of macros Stefan Monnier
2012-08-17 23:59 ` Paul Eggert
2012-08-18 22:15   ` Daniel Colascione
2012-08-18 22:55     ` John Yates
2012-08-19  4:22       ` Richard Stallman
2012-08-21 17:50   ` Stefan Monnier
2012-08-22  9:24     ` C backtraces for Emacs Paul Eggert
2012-08-22 16:01       ` Eli Zaretskii
2012-08-22 16:39         ` Paul Eggert
2012-08-23  0:40         ` Daniel Colascione
2012-08-23 16:55           ` Eli Zaretskii
2012-08-24 10:48       ` Paul Eggert
2012-08-25  4:41         ` Paul Eggert
2012-08-25  5:57           ` Eli Zaretskii
2012-08-22  9:28     ` inlinable functions instead of macros Paul Eggert
2012-08-22  9:48       ` Andreas Schwab
2012-08-22 14:31       ` Stefan Monnier
2012-08-24 21:37         ` Paul Eggert [this message]
2012-08-25  1:38           ` Tom Tromey
2012-08-25  2:58             ` Paul Eggert
2012-08-25  5:35               ` Eli Zaretskii
2012-08-25 20:13                 ` Tom Tromey
2012-08-26  4:42                   ` Paul Eggert
2012-08-25  2:05           ` Stefan Monnier
2012-08-26  5:31             ` Paul Eggert
2012-08-22 16:03       ` Eli Zaretskii
2012-08-18 19:08 ` Richard Stallman
2012-08-18 20:57   ` Paul Eggert
2012-08-18 21:03     ` Eli Zaretskii
2012-08-18 21:31       ` Paul Eggert
2012-08-19  2:45         ` Eli Zaretskii
2012-08-18 21:14   ` Óscar Fuentes
2012-08-19 17:28 ` Florian Weimer
2012-08-20 20:38 ` Sam Steingold

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=5037F411.4010905@cs.ucla.edu \
    --to=eggert@cs.ucla.edu \
    --cc=emacs-devel@gnu.org \
    --cc=monnier@iro.umontreal.ca \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
Code repositories for project(s) associated with this public inbox

	https://git.savannah.gnu.org/cgit/emacs.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).