unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* Enabling --enable-check-lisp-object-type by default on x86 and AMD64 (was: Re: bug#26597: 25.1; Compilation error on master with --enable-check-lisp-object-type)
       [not found]     ` <83a878r2d0.fsf@gnu.org>
@ 2017-05-01 11:32       ` Philipp Stephani
  2017-05-02 22:14         ` Enabling --enable-check-lisp-object-type by default on x86 and AMD64 Paul Eggert
  0 siblings, 1 reply; 11+ messages in thread
From: Philipp Stephani @ 2017-05-01 11:32 UTC (permalink / raw)
  To: Eli Zaretskii, Emacs developers

[-- Attachment #1: Type: text/plain, Size: 1151 bytes --]

Eli Zaretskii <eliz@gnu.org> schrieb am Sa., 22. Apr. 2017 um 15:35 Uhr:

> > From: Philipp Stephani <p.stephani2@gmail.com>
> > Date: Sat, 22 Apr 2017 11:57:11 +0000
> >
> >  > (Tangentially, is there any reason not to define Lisp_Object as struct
> >  > unconditionally, to avoid such coding errors?)
> >
> >  Yes, it produces slower code.
> >
> > Are you sure that's still the case? I've just diffed the assembly output
> for editfns.c with and without
> > --enable-check-lisp-object-type, they seem identical (apart from minor
> diffs due to different register allocation
> > and instruction ordering). Replacing a primitive value with a struct
> containing such a value should never
> > degrade performance; that would be a compiler bug.
>
> On what OS/architecture, and with what compiler options?
>

On macOS, with configure called e.g. as

./configure  '--without-xml2' '--with-modules' '--without-pop'
'--with-mailutils' --enable-check-lisp-object-type 'CFLAGS=-O2 -save-temps'
'MAKEINFO=/usr/local/opt/texinfo/bin/makeinfo'


>
> in any case, if you want to raise this issue, please post to
> emacs-devel, not here.
>

Moved to emacs-devel.

[-- Attachment #2: Type: text/html, Size: 1918 bytes --]

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Enabling --enable-check-lisp-object-type by default on x86 and AMD64
  2017-05-01 11:32       ` Enabling --enable-check-lisp-object-type by default on x86 and AMD64 (was: Re: bug#26597: 25.1; Compilation error on master with --enable-check-lisp-object-type) Philipp Stephani
@ 2017-05-02 22:14         ` Paul Eggert
  2017-05-03  2:38           ` Eli Zaretskii
  0 siblings, 1 reply; 11+ messages in thread
From: Paul Eggert @ 2017-05-02 22:14 UTC (permalink / raw)
  To: Philipp Stephani; +Cc: Emacs developers

[-- Attachment #1: Type: text/plain, Size: 1426 bytes --]

Originally, the Lisp_Object type was a struct containing bitfields. This 
was significantly slower than using integer shifting and masking on many 
platforms, so long ago the default Lisp_Object type was changed to be an 
integer. Nowadays Lisp_Object no longer contains bitfields even when 
--enable-check-lisp-object-type is used, so this old motivation is no 
longer relevant.

For x86-64 there should be little difference nowadays when 
--enable-check-lisp-object-type is used. For other platforms (e.g., 
x86), however, I suppose there can still be a significant (though small) 
difference. So when compiling emacs for production, it makes sense to 
omit --enable-check-lisp-object-type, for the benefit of x86 and similar 
platforms.

When developing, the advantages of --enable-check-lisp-object-type 
outweigh the small increase in runtime cost, particularly considering 
that x86-64 is the most common development platform nowadays and there 
the runtime cost is insignificant.  So it makes sense to default 
--enable-check-lisp-object-type to "yes" if --enable-gcc-warnings is 
also enabled (which it is by default, in developer builds). I did this 
by installing the attached patch; comments welcome.

As a result, if you build master from a developer (Git-based) directory, 
--enable-check-lisp-object-type should now be the default. If you don't 
build from Git, I suggest configuring with --enable-gcc-warnings.

[-- Attachment #2: 0001-Check-list-object-type-if-enable-gcc-warnings.txt --]
[-- Type: text/plain, Size: 8434 bytes --]

From f1550f70a1e139022e6238c3c5c22cb7bd6923a1 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Tue, 2 May 2017 14:52:21 -0700
Subject: [PATCH] Check list object type if --enable-gcc-warnings
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* configure.ac (--enable-check-lisp-object-type):
Default to "yes" if --enable-gcc-warnings is not "no".
* etc/NEWS: Mention this.
* src/eval.c (internal_lisp_condition_case): Fix some glitches
with 'volatile' uncovered by the above: in particular, 'clauses'
should be a pointer to volatile storage on the stack, and need not
be volatile itself.  Use an int, not ptrdiff_t, to count clauses.
Don’t bother gathering binding count if VAR is nil.  Use
more-specific local names to try to clarify what’s going on.
---
 configure.ac |  25 +++++++-------
 etc/NEWS     |   5 ++-
 src/eval.c   | 105 ++++++++++++++++++++++++++++++-----------------------------
 3 files changed, 69 insertions(+), 66 deletions(-)

diff --git a/configure.ac b/configure.ac
index 45cfdfc..d6b8001 100644
--- a/configure.ac
+++ b/configure.ac
@@ -507,16 +507,6 @@ AC_DEFUN
 [Define this to enable glyphs debugging code.])
 fi
 
-AC_ARG_ENABLE(check-lisp-object-type,
-[AS_HELP_STRING([--enable-check-lisp-object-type],
-                [enable compile time checks for the Lisp_Object data type.
-		This is useful for development for catching certain types of bugs.])],
-if test "${enableval}" != "no"; then
-   AC_DEFINE(CHECK_LISP_OBJECT_TYPE, 1,
-   [Define this to enable compile time checks for the Lisp_Object data type.])
-fi)
-
-
 dnl The name of this option is unfortunate.  It predates, and has no
 dnl relation to, the "sampling-based elisp profiler" added in 24.3.
 dnl Actually, it stops it working.
@@ -877,9 +867,18 @@ AC_DEFUN
    # just a release imported into Git for patch management.
    gl_gcc_warnings=no
    if test -e "$srcdir"/.git && test ! -f "$srcdir"/.tarball-version; then
-     gl_GCC_VERSION_IFELSE([5], [3], [gl_gcc_warnings=warn-only])]
-   fi
-)
+     gl_GCC_VERSION_IFELSE([5], [3], [gl_gcc_warnings=warn-only])
+   fi])
+
+AC_ARG_ENABLE([check-lisp-object-type],
+  [AS_HELP_STRING([--enable-check-lisp-object-type],
+     [Enable compile-time checks for the Lisp_Object data type,
+      which can catch some bugs during development.
+      The default is "no" if --enable-gcc-warnings is "no".])])
+if test "${enable_check_lisp_object_type-$gl_gcc_warnings}" != "no"; then
+  AC_DEFINE([CHECK_LISP_OBJECT_TYPE], 1,
+    [Define to enable compile-time checks for the Lisp_Object data type.])
+fi
 
 # clang is unduly picky about some things.
 AC_CACHE_CHECK([whether the compiler is clang], [emacs_cv_clang],
diff --git a/etc/NEWS b/etc/NEWS
index 173c4e4..410e681 100644
--- a/etc/NEWS
+++ b/etc/NEWS
@@ -42,6 +42,9 @@ now the default in developer builds.  As before, use
 '--disable-gcc-warnings' to suppress GCC's warnings, and
 '--enable-gcc-warnings' to stop the build if GCC issues warnings.
 
+** When GCC warnings are enabled, '--enable-check-lisp-object-type' is
+now enabled by default when configuring.
+
 +++
 ** The Emacs server now has socket-launching support.  This allows
 socket based activation, where an external process like systemd can
@@ -393,7 +396,7 @@ procedure and therefore obeys saving hooks.
 * Changes in Specialized Modes and Packages in Emacs 26.1
 
 *** Info menu and index completion uses substring completion by default.
-This can be customized via the `info-menu` category in
+This can be customized via the info-menu category in
 completion-category-override.
 
 +++
diff --git a/src/eval.c b/src/eval.c
index af0912f..0030271 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1225,18 +1225,17 @@ usage: (condition-case VAR BODYFORM &rest HANDLERS)  */)
    rather than passed in a list.  Used by Fbyte_code.  */
 
 Lisp_Object
-internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
+internal_lisp_condition_case (Lisp_Object var, Lisp_Object bodyform,
 			      Lisp_Object handlers)
 {
-  Lisp_Object val;
   struct handler *oldhandlerlist = handlerlist;
-  int clausenb = 0;
+  ptrdiff_t clausenb = 0;
 
   CHECK_SYMBOL (var);
 
-  for (val = handlers; CONSP (val); val = XCDR (val))
+  for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail))
     {
-      Lisp_Object tem = XCAR (val);
+      Lisp_Object tem = XCAR (tail);
       clausenb++;
       if (! (NILP (tem)
 	     || (CONSP (tem)
@@ -1246,55 +1245,57 @@ internal_lisp_condition_case (volatile Lisp_Object var, Lisp_Object bodyform,
 	       SDATA (Fprin1_to_string (tem, Qt)));
     }
 
-  { /* The first clause is the one that should be checked first, so it should
-       be added to handlerlist last.  So we build in `clauses' a table that
-       contains `handlers' but in reverse order.  SAFE_ALLOCA won't work
-       here due to the setjmp, so impose a MAX_ALLOCA limit.  */
-    if (MAX_ALLOCA / word_size < clausenb)
-      memory_full (SIZE_MAX);
-    Lisp_Object *clauses = alloca (clausenb * sizeof *clauses);
-    Lisp_Object *volatile clauses_volatile = clauses;
-    int i = clausenb;
-    for (val = handlers; CONSP (val); val = XCDR (val))
-      clauses[--i] = XCAR (val);
-    for (i = 0; i < clausenb; i++)
-      {
-	Lisp_Object clause = clauses[i];
-	Lisp_Object condition = CONSP (clause) ? XCAR (clause) : Qnil;
-	if (!CONSP (condition))
-	  condition = Fcons (condition, Qnil);
-	struct handler *c = push_handler (condition, CONDITION_CASE);
-	if (sys_setjmp (c->jmp))
-	  {
-	    ptrdiff_t count = SPECPDL_INDEX ();
-	    Lisp_Object val = handlerlist->val;
-	    Lisp_Object *chosen_clause = clauses_volatile;
-	    for (c = handlerlist->next; c != oldhandlerlist; c = c->next)
-	      chosen_clause++;
-	    handlerlist = oldhandlerlist;
-	    if (!NILP (var))
-	      {
-		if (!NILP (Vinternal_interpreter_environment))
-		  specbind (Qinternal_interpreter_environment,
-			    Fcons (Fcons (var, val),
-				   Vinternal_interpreter_environment));
-		else
-		  specbind (var, val);
-	      }
-	    val = Fprogn (XCDR (*chosen_clause));
-	    /* Note that this just undoes the binding of var; whoever
-	       longjumped to us unwound the stack to c.pdlcount before
-	       throwing.  */
-	    if (!NILP (var))
-	      unbind_to (count, Qnil);
-	    return val;
-	  }
-      }
-  }
+  /* The first clause is the one that should be checked first, so it
+     should be added to handlerlist last.  So build in CLAUSES a table
+     that contains HANDLERS but in reverse order.  CLAUSES is pointer
+     to volatile to avoid issues with setjmp and local storage.
+     SAFE_ALLOCA won't work here due to the setjmp, so impose a
+     MAX_ALLOCA limit.  */
+  if (MAX_ALLOCA / word_size < clausenb)
+    memory_full (SIZE_MAX);
+  Lisp_Object volatile *clauses = alloca (clausenb * sizeof *clauses);
+  clauses += clausenb;
+  for (Lisp_Object tail = handlers; CONSP (tail); tail = XCDR (tail))
+    *--clauses = XCAR (tail);
+  for (ptrdiff_t i = 0; i < clausenb; i++)
+    {
+      Lisp_Object clause = clauses[i];
+      Lisp_Object condition = CONSP (clause) ? XCAR (clause) : Qnil;
+      if (!CONSP (condition))
+	condition = list1 (condition);
+      struct handler *c = push_handler (condition, CONDITION_CASE);
+      if (sys_setjmp (c->jmp))
+	{
+	  Lisp_Object val = handlerlist->val;
+	  Lisp_Object volatile *chosen_clause = clauses;
+	  for (struct handler *h = handlerlist->next; h != oldhandlerlist;
+	       h = h->next)
+	    chosen_clause++;
+	  Lisp_Object handler_body = XCDR (*chosen_clause);
+	  handlerlist = oldhandlerlist;
+
+	  if (NILP (var))
+	    return Fprogn (handler_body);
+
+	  if (!NILP (Vinternal_interpreter_environment))
+	    {
+	      val = Fcons (Fcons (var, val),
+			   Vinternal_interpreter_environment);
+	      var = Qinternal_interpreter_environment;
+	    }
+
+	  /* Bind VAR to VAL while evaluating HANDLER_BODY.  The
+	     unbind_to just undoes VAR's binding; whoever longjumped
+	     to us unwound the stack to C->pdlcount before throwing.  */
+	  ptrdiff_t count = SPECPDL_INDEX ();
+	  specbind (var, val);
+	  return unbind_to (count, Fprogn (handler_body));
+	}
+    }
 
-  val = eval_sub (bodyform);
+  Lisp_Object result = eval_sub (bodyform);
   handlerlist = oldhandlerlist;
-  return val;
+  return result;
 }
 
 /* Call the function BFUN with no arguments, catching errors within it
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: Enabling --enable-check-lisp-object-type by default on x86 and AMD64
  2017-05-02 22:14         ` Enabling --enable-check-lisp-object-type by default on x86 and AMD64 Paul Eggert
@ 2017-05-03  2:38           ` Eli Zaretskii
  2017-05-03  3:24             ` Paul Eggert
  0 siblings, 1 reply; 11+ messages in thread
From: Eli Zaretskii @ 2017-05-03  2:38 UTC (permalink / raw)
  To: Paul Eggert; +Cc: p.stephani2, emacs-devel

> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Tue, 2 May 2017 15:14:17 -0700
> Cc: Emacs developers <emacs-devel@gnu.org>
> 
> For x86-64 there should be little difference nowadays when 
> --enable-check-lisp-object-type is used. For other platforms (e.g., 
> x86), however, I suppose there can still be a significant (though small) 
> difference. So when compiling emacs for production, it makes sense to 
> omit --enable-check-lisp-object-type, for the benefit of x86 and similar 
> platforms.
> 
> When developing, the advantages of --enable-check-lisp-object-type 
> outweigh the small increase in runtime cost, particularly considering 
> that x86-64 is the most common development platform nowadays and there 
> the runtime cost is insignificant.  So it makes sense to default 
> --enable-check-lisp-object-type to "yes" if --enable-gcc-warnings is 
> also enabled (which it is by default, in developer builds). I did this 
> by installing the attached patch; comments welcome.

One difficulty this adds in developing is that backtraces are much
less readable, as Lisp_Object values are not shown.



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Enabling --enable-check-lisp-object-type by default on x86 and AMD64
  2017-05-03  2:38           ` Eli Zaretskii
@ 2017-05-03  3:24             ` Paul Eggert
  2017-05-03 14:48               ` Eli Zaretskii
  0 siblings, 1 reply; 11+ messages in thread
From: Paul Eggert @ 2017-05-03  3:24 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: p.stephani2, emacs-devel

Eli Zaretskii wrote:
> One difficulty this adds in developing is that backtraces are much
> less readable, as Lisp_Object values are not shown.

Do you mean the C backtrace? Would it help to add a line "set print 
frame-arguments all" to src/.gdbinit?



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Enabling --enable-check-lisp-object-type by default on x86 and AMD64
  2017-05-03  3:24             ` Paul Eggert
@ 2017-05-03 14:48               ` Eli Zaretskii
  2017-05-03 18:08                 ` Paul Eggert
  0 siblings, 1 reply; 11+ messages in thread
From: Eli Zaretskii @ 2017-05-03 14:48 UTC (permalink / raw)
  To: Paul Eggert; +Cc: p.stephani2, emacs-devel

> Cc: p.stephani2@gmail.com, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Tue, 2 May 2017 20:24:18 -0700
> 
> Eli Zaretskii wrote:
> > One difficulty this adds in developing is that backtraces are much
> > less readable, as Lisp_Object values are not shown.
> 
> Do you mean the C backtrace?

Yes.

> Would it help to add a line "set print frame-arguments all" to
> src/.gdbinit?

Only partially.  People who report backtraces seldom bother to start
GDB from the Emacs's src directory, let alone source .gdbinit by hand.
Moreover, latest versions of GDB refuse to auto-load .gdbinit files
from random directories, unless you put some magic in your ~/.gdbinit
(which most people don't).  Finally, this setting doesn't affect only
Lisp_Object, it affects any non-scalar arguments, so it has
non-trivial downsides of its own (which I guess is why it is not the
default).



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Enabling --enable-check-lisp-object-type by default on x86 and AMD64
  2017-05-03 14:48               ` Eli Zaretskii
@ 2017-05-03 18:08                 ` Paul Eggert
  2017-05-03 18:22                   ` Eli Zaretskii
  0 siblings, 1 reply; 11+ messages in thread
From: Paul Eggert @ 2017-05-03 18:08 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: p.stephani2, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 1107 bytes --]

On 05/03/2017 07:48 AM, Eli Zaretskii wrote:
>> Would it help to add a line "set print frame-arguments all" to
>> src/.gdbinit?
> Only partially.  People who report backtraces seldom bother to start
> GDB from the Emacs's src directory, let alone source .gdbinit by hand.
> Moreover, latest versions of GDB refuse to auto-load .gdbinit files
> from random directories, unless you put some magic in your ~/.gdbinit
> (which most people don't).

This problem is not new. It should be OK to continue ask developers to 
source .gdbinit, to compile with -O0, etc. If we can't assume that, the 
backtrace is already problematic, and the recent change doesn't make it 
much worse.

> this setting doesn't affect only
> Lisp_Object, it affects any non-scalar arguments, so it has
> non-trivial downsides of its own (which I guess is why it is not the
> default).

True. How about using GDB pretty-printers instead?  E.g., add something 
like the attached file as src/gdb-pretty.py, and add the line "source 
gdb-pretty.py" to src/.gdbinit. That way, only Lisp_Object values are 
affected, rather than all structs.


[-- Attachment #2: gdb-pretty.py --]
[-- Type: text/x-python, Size: 524 bytes --]

import gdb
import gdb.printing

class Lisp_Object_Printer:
    def __init__(self, val):
        self.val = val

    def to_string(self):
        return str (self.val["i"]) + "L"

def build_pretty_printer ():
    pp = gdb.printing.RegexpCollectionPrettyPrinter ("Emacs")
    pp.add_printer ('Lisp_Object', '^Lisp_Object$', Lisp_Object_Printer)
    return pp

gdb.printing.register_pretty_printer (gdb.current_objfile (),
                                      build_pretty_printer (),
                                      1)

^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Enabling --enable-check-lisp-object-type by default on x86 and AMD64
  2017-05-03 18:08                 ` Paul Eggert
@ 2017-05-03 18:22                   ` Eli Zaretskii
  2017-05-04 14:33                     ` Eli Zaretskii
  2017-05-05 23:23                     ` Paul Eggert
  0 siblings, 2 replies; 11+ messages in thread
From: Eli Zaretskii @ 2017-05-03 18:22 UTC (permalink / raw)
  To: Paul Eggert; +Cc: p.stephani2, emacs-devel

> Cc: p.stephani2@gmail.com, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Wed, 3 May 2017 11:08:23 -0700
> 
> > Only partially.  People who report backtraces seldom bother to start
> > GDB from the Emacs's src directory, let alone source .gdbinit by hand.
> > Moreover, latest versions of GDB refuse to auto-load .gdbinit files
> > from random directories, unless you put some magic in your ~/.gdbinit
> > (which most people don't).
> 
> This problem is not new.

It isn't new, but previously it only affected displaying Lisp data in
human-readable form.  Now it will also affect backtraces.

> How about using GDB pretty-printers instead?

This is better, but how sure we are people's GDB is built with Python
support?

> E.g., add something like the attached file as src/gdb-pretty.py, and
> add the line "source gdb-pretty.py" to src/.gdbinit.

Why not make this part of .gdbinit itself?



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Enabling --enable-check-lisp-object-type by default on x86 and AMD64
  2017-05-03 18:22                   ` Eli Zaretskii
@ 2017-05-04 14:33                     ` Eli Zaretskii
  2017-05-05 23:23                     ` Paul Eggert
  1 sibling, 0 replies; 11+ messages in thread
From: Eli Zaretskii @ 2017-05-04 14:33 UTC (permalink / raw)
  To: eggert; +Cc: p.stephani2, emacs-devel

> Date: Wed, 03 May 2017 21:22:09 +0300
> From: Eli Zaretskii <eliz@gnu.org>
> Cc: p.stephani2@gmail.com, emacs-devel@gnu.org
> 
> > How about using GDB pretty-printers instead?
> 
> This is better, but how sure we are people's GDB is built with Python
> support?

Also, the Python script should be a bit smarter, to support also the
compilation without --enable-check-lisp-object-type.  When I try this
script in such a build, GDB crashes when displaying a backtrace.



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Enabling --enable-check-lisp-object-type by default on x86 and AMD64
  2017-05-03 18:22                   ` Eli Zaretskii
  2017-05-04 14:33                     ` Eli Zaretskii
@ 2017-05-05 23:23                     ` Paul Eggert
  2017-05-06  7:07                       ` Eli Zaretskii
  1 sibling, 1 reply; 11+ messages in thread
From: Paul Eggert @ 2017-05-05 23:23 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: p.stephani2, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 950 bytes --]

On 05/03/2017 11:22 AM, Eli Zaretskii wrote:
> This is better, but how sure we are people's GDB is built with Python
> support?

We can ask developers to upgrade. GDB pretty-printing has worked with 
embedded Python for several years (since GDB 7.3 in 2011, I believe). We 
are not talking about general Emacs users here, only developers who are 
building bleeding-edge Emacs from Git. It's reasonable to expect these 
folks to have reasonably modern tools, especially since the only problem 
here is that the backtrace will be a bit harder to read if they use an 
old GDB.

> Why not make this part of .gdbinit itself? 

Sure, we can do that.

> Also, the Python script should be a bit smarter, to support also the
> compilation without --enable-check-lisp-object-type.  When I try this
> script in such a build, GDB crashes when displaying a backtrace.
Also doable.

I installed the attached, which I hope addresses the above issues well 
enough.


[-- Attachment #2: 0001-Pretty-print-Lisp_Object-values-in-GDB.patch --]
[-- Type: text/x-patch, Size: 2878 bytes --]

From f46a91a7811c359fae9c1c2a7f9374f9c5303209 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Fri, 5 May 2017 15:59:24 -0700
Subject: [PATCH] Pretty-print Lisp_Object values in GDB

* src/.gdbinit: Add a pretty-printer for Lisp_Object values.  Now,
GDB displays them as "XIL(0xXXX)" rather than displaying them
as "..." when CHECK_LISP_OBJECT_TYPE is in effect and as "DDDDD"
otherwise.
---
 src/.gdbinit | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 57 insertions(+)

diff --git a/src/.gdbinit b/src/.gdbinit
index 6d7476d..0596188 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1264,3 +1264,60 @@ commands
   end
   continue
 end
+
+
+# Put the Python code at the end of .gdbinit so that if GDB does not
+# support Python, GDB will do all the above initializations before
+# reporting an error.
+
+python
+
+# Omit pretty-printing in older (pre-7.3) GDBs that lack it.
+if hasattr(gdb, 'printing'):
+
+  class Emacs_Pretty_Printers (gdb.printing.RegexpCollectionPrettyPrinter):
+    """A collection of pretty-printers.  This is like GDB's
+       RegexpCollectionPrettyPrinter except when printing Lisp_Object."""
+    def __call__ (self, val):
+      """Look up the pretty-printer for the provided value."""
+      type = val.type
+      typename = type.tag or type.name
+      basic_type = gdb.types.get_basic_type (type)
+      basic_typename = basic_type.tag or basic_type.name
+      for printer in self.subprinters:
+        if (printer.enabled
+            and ((printer.regexp == '^Lisp_Object$'
+                  and typename == 'Lisp_Object')
+                 or (basic_typename
+                     and printer.compiled_re.search (basic_typename)))):
+          return printer.gen_printer (val)
+      return None
+
+  class Lisp_Object_Printer:
+    "A printer for Lisp_Object values."
+    def __init__ (self, val):
+      self.val = val
+
+    def to_string (self):
+      "Yield a string that can be fed back into GDB."
+      val = self.val
+      basic_type = gdb.types.get_basic_type (val.type)
+      if (basic_type.code == gdb.TYPE_CODE_STRUCT
+          and gdb.types.has_field (basic_type, "i")):
+        val = val["i"]
+      # Yield "XIL(N)", where N is a C integer.  This helps humans
+      # distinguish Lisp_Object values from ordinary integers even
+      # when Lisp_Object is an integer.  Perhaps some day the
+      # pretty-printing could be fancier.
+      if not val:
+        return "XIL(0)" # Easier to read than "XIL(0x0)".
+      return "XIL(0x%x)" % val
+
+  def build_pretty_printer ():
+    pp = Emacs_Pretty_Printers ("Emacs")
+    pp.add_printer ('Lisp_Object', '^Lisp_Object$', Lisp_Object_Printer)
+    return pp
+
+  gdb.printing.register_pretty_printer (gdb.current_objfile (),
+                                        build_pretty_printer (), True)
+end
-- 
2.9.3


^ permalink raw reply related	[flat|nested] 11+ messages in thread

* Re: Enabling --enable-check-lisp-object-type by default on x86 and AMD64
  2017-05-05 23:23                     ` Paul Eggert
@ 2017-05-06  7:07                       ` Eli Zaretskii
  2017-05-06 23:23                         ` Paul Eggert
  0 siblings, 1 reply; 11+ messages in thread
From: Eli Zaretskii @ 2017-05-06  7:07 UTC (permalink / raw)
  To: Paul Eggert; +Cc: p.stephani2, emacs-devel

> Cc: p.stephani2@gmail.com, emacs-devel@gnu.org
> From: Paul Eggert <eggert@cs.ucla.edu>
> Date: Fri, 5 May 2017 16:23:52 -0700
> 
> On 05/03/2017 11:22 AM, Eli Zaretskii wrote:
> > This is better, but how sure we are people's GDB is built with Python
> > support?
> 
> We can ask developers to upgrade. GDB pretty-printing has worked with 
> embedded Python for several years (since GDB 7.3 in 2011, I believe). We 
> are not talking about general Emacs users here, only developers who are 
> building bleeding-edge Emacs from Git.

We are talking about anyone who could submit backtraces from the Git
master builds.  I don't know who that might be (e.g., aren't there
snapshots of master provided by the various GNU/Linux distros?), but
even if we only consider people who are on this list, I'm not sure how
many of them have GDB built with Python support.  Maybe we should poll
this list about this, it cannot be that hard.

> It's reasonable to expect these folks to have reasonably modern
> tools

The GDB version is not the issue here, because even the latest GDB can
be built without Python.  It's a configure-time option.

> > Why not make this part of .gdbinit itself? 
> 
> Sure, we can do that.
> 
> > Also, the Python script should be a bit smarter, to support also the
> > compilation without --enable-check-lisp-object-type.  When I try this
> > script in such a build, GDB crashes when displaying a backtrace.
> Also doable.

Thanks.

> +    def to_string (self):
> +      "Yield a string that can be fed back into GDB."
> +      val = self.val
> +      basic_type = gdb.types.get_basic_type (val.type)
> +      if (basic_type.code == gdb.TYPE_CODE_STRUCT
> +          and gdb.types.has_field (basic_type, "i")):
> +        val = val["i"]
> +      # Yield "XIL(N)", where N is a C integer.  This helps humans
> +      # distinguish Lisp_Object values from ordinary integers even
> +      # when Lisp_Object is an integer.  Perhaps some day the
> +      # pretty-printing could be fancier.
> +      if not val:
> +        return "XIL(0)" # Easier to read than "XIL(0x0)".
> +      return "XIL(0x%x)" % val

I'm not sure I like this XIL(something) feature.  For starters, it
deviates from the format I'm used to, and takes precious screen
estate.  It also might confuse people who know GDB but won't
immediately grasp what "XIL" is.  It also introduces certain
inconsistencies, e.g. (in a build without --enable-check-lisp-object-type):

  (gdb) fr 28
  #28 0x011586e2 in command_loop_2 (ignore=XIL(0)) at keyboard.c:1112
  1112        val = internal_condition_case (command_loop_1, Qerror, cmd_error);
  (gdb) p ignore == Qnil
  $1 = 1
  (gdb) p Qnil
  $2 = 0
  (gdb) p ignore
  $3 = XIL(0)

So something whose value is zero is numerically equal to something
whose value is XIL(0).

As for "some day the pretty-printing could be fancier": what exactly
did you want to implement?  Guile has a pretty elaborate GDB support
for printing Scheme values, perhaps you could look there for
inspiration.



^ permalink raw reply	[flat|nested] 11+ messages in thread

* Re: Enabling --enable-check-lisp-object-type by default on x86 and AMD64
  2017-05-06  7:07                       ` Eli Zaretskii
@ 2017-05-06 23:23                         ` Paul Eggert
  0 siblings, 0 replies; 11+ messages in thread
From: Paul Eggert @ 2017-05-06 23:23 UTC (permalink / raw)
  To: Eli Zaretskii; +Cc: p.stephani2, emacs-devel

[-- Attachment #1: Type: text/plain, Size: 2328 bytes --]

Eli Zaretskii wrote:

> Maybe we should poll this list about this

In effect we've already probed about it in this thread. Others are welcome to 
chime in.

> even the latest GDB can be built without Python. It's a configure-time option.

The configure-time option defaults to "yes" if Python is installed, which it 
typically is nowadays. It's been "yes" in the major GNU/Linux distributions for 
years, and even MinGW now ships a Python-enabled GDB. So this should not be a 
major problem for developers in practice.

> I'm not sure I like this XIL(something) feature.  For starters, it
> deviates from the format I'm used to, and takes precious screen
> estate.

One gets used to it, and it has the advantage of easily distinguishing 
Lisp_Object from integer values when debugging, which is worth some screen real 
estate.

> It also might confuse people who know GDB but won't
> immediately grasp what "XIL" is.

The confusion won't last long, and any confusion is outweighed by the clarity 
caused by GDB's now distinguishing Lisp_Object values from C integers. I don't 
see this as turning into a real problem, but if I'm wrong I suppose we can 
rename XIL to something more mnemonic.

>   (gdb) p Qnil
>   $2 = 0
>   (gdb) p ignore
>   $3 = XIL(0)

Ah, I didn't think about pretty-printing constants. I fixed that by installing 
the first attached patch. I also tried out a somewhat-older GDB implementation 
(Ubuntu LTS) and fixed some other glitches in the second attached patch. 
However, we shouldn't need to spend a lot of time worrying about glitches with 
ancient debuggers, as we can expect developers to be reasonably up-to-date.

> something whose value is zero is numerically equal to something
> whose value is XIL(0).

Sure, because XIL(0) == 0 when --enable-lisp-object-types=no. Pretty-printing 
doesn't change that.

> As for "some day the pretty-printing could be fancier": what exactly
> did you want to implement?

I wasn't planning anything exactly. The general principle is that the GDB 
pretty-printer should output a string that you can paste back into GDB. (In 
contrast, the long-established "pp" command should output a string that you can 
paste into Elisp.) GDB could pretty-print the Lisp integer 27 as 
"make_number(27)", for example.

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: 0001-Pretty-print-const-Lisp_Objects-in-.gdbinit.patch --]
[-- Type: text/x-diff; name="0001-Pretty-print-const-Lisp_Objects-in-.gdbinit.patch", Size: 1233 bytes --]

From 7cd7f5b4032092389a00e23af3ab435628febed3 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sat, 6 May 2017 14:24:12 -0700
Subject: [PATCH 1/2] Pretty-print const Lisp_Objects in .gdbinit
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

* src/.gdbinit (Emacs_Pretty_Printers.__call__):
Compare unqualified type to Lisp_Object, to do the right thing
when the expression has type ‘Lisp_Object const’.
Problem reported by Eli Zaretskii in:
http://lists.gnu.org/archive/html/emacs-devel/2017-05/msg00138.html
---
 src/.gdbinit | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/.gdbinit b/src/.gdbinit
index 0596188..29689e2 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1280,7 +1280,7 @@ if hasattr(gdb, 'printing'):
        RegexpCollectionPrettyPrinter except when printing Lisp_Object."""
     def __call__ (self, val):
       """Look up the pretty-printer for the provided value."""
-      type = val.type
+      type = val.type.unqualified ()
       typename = type.tag or type.name
       basic_type = gdb.types.get_basic_type (type)
       basic_typename = basic_type.tag or basic_type.name
-- 
2.7.4


[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #3: 0002-Port-.gdbinit-to-GDB-7.11.1-Python-2.7.12.patch --]
[-- Type: text/x-diff; name="0002-Port-.gdbinit-to-GDB-7.11.1-Python-2.7.12.patch", Size: 1395 bytes --]

From f31689c803a13836ef3528d6e2b4c98c767c42c7 Mon Sep 17 00:00:00 2001
From: Paul Eggert <eggert@cs.ucla.edu>
Date: Sat, 6 May 2017 15:29:16 -0700
Subject: [PATCH 2/2] Port .gdbinit to GDB 7.11.1 + Python 2.7.12

* src/.gdbinit (Lisp_Object_Printer.to_string):
Explicitly convert integer val to 'int', so that
older GDBs do not complain about the conversion.
* src/lisp.h (Lisp_Object) [CHECK_LISP_OBJECT_TYPE]:
Give the struct a tag, so that older GDB pretty-printers have a
tag to hang their hat on.
---
 src/.gdbinit | 2 +-
 src/lisp.h   | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/.gdbinit b/src/.gdbinit
index 29689e2..80aa95b 100644
--- a/src/.gdbinit
+++ b/src/.gdbinit
@@ -1311,7 +1311,7 @@ if hasattr(gdb, 'printing'):
       # pretty-printing could be fancier.
       if not val:
         return "XIL(0)" # Easier to read than "XIL(0x0)".
-      return "XIL(0x%x)" % val
+      return "XIL(0x%x)" % int(val)
 
   def build_pretty_printer ():
     pp = Emacs_Pretty_Printers ("Emacs")
diff --git a/src/lisp.h b/src/lisp.h
index 5d4c64a..de3a548 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -546,7 +546,7 @@ enum Lisp_Fwd_Type
 
 #ifdef CHECK_LISP_OBJECT_TYPE
 
-typedef struct { EMACS_INT i; } Lisp_Object;
+typedef struct Lisp_Object { EMACS_INT i; } Lisp_Object;
 
 #define LISP_INITIALLY(i) {i}
 
-- 
2.7.4


^ permalink raw reply related	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2017-05-06 23:23 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <m2shl134rd.fsf@gmail.com>
     [not found] ` <83mvb8riq0.fsf@gnu.org>
     [not found]   ` <CAArVCkQoeBwHspkUUih_9EdwnBQ5HWaYHD87Rcyduc8DsooXRg@mail.gmail.com>
     [not found]     ` <83a878r2d0.fsf@gnu.org>
2017-05-01 11:32       ` Enabling --enable-check-lisp-object-type by default on x86 and AMD64 (was: Re: bug#26597: 25.1; Compilation error on master with --enable-check-lisp-object-type) Philipp Stephani
2017-05-02 22:14         ` Enabling --enable-check-lisp-object-type by default on x86 and AMD64 Paul Eggert
2017-05-03  2:38           ` Eli Zaretskii
2017-05-03  3:24             ` Paul Eggert
2017-05-03 14:48               ` Eli Zaretskii
2017-05-03 18:08                 ` Paul Eggert
2017-05-03 18:22                   ` Eli Zaretskii
2017-05-04 14:33                     ` Eli Zaretskii
2017-05-05 23:23                     ` Paul Eggert
2017-05-06  7:07                       ` Eli Zaretskii
2017-05-06 23:23                         ` Paul Eggert

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).