emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

feature/soc-bytecode-in-traceback e5734be: Experiment giving bytecode in


From: Rocky Bernstein
Subject: feature/soc-bytecode-in-traceback e5734be: Experiment giving bytecode in traceback...
Date: Mon, 27 Apr 2020 15:15:17 -0400 (EDT)

branch: feature/soc-bytecode-in-traceback
commit e5734bef9074fa8b1c80c35aa9bf528e31d966a4
Author: rocky <address@hidden>
Commit: rocky <address@hidden>

    Experiment giving bytecode in traceback...
    
    This commit only changes the behavior when `(cdr)` when it is not
    given a `cons` node, in order to give some quick idea of how adding
    more traceback information might work.
    
    Here's how to see/use. Build this code.
    
    Byte-compile this buggy function in `/tmp/foo.el`
    with (byte-compile-file)
    ```lisp
    (defun foo()
      (setq x 5)
      (cdr 'b)
      )
    ```
    
    ```
    (load-file "/tmp/foo.elc")
    (foo)
    ```
    
    You should see:
    
    ```
    Debugger entered--Lisp error: (wrong-type-argument listp b 3)
                                            this is the offset ^
      foo()
      eval((foo) nil)
      elisp--eval-last-sexp(nil)
      eval-last-sexp(nil)
      funcall-interactively(eval-last-sexp nil)
      call-interactively(eval-last-sexp nil nil)
      command-execute(eval-last-sexp)
    ```
    
    Compare against disassembly:
    
    ```
    byte code for foo:
      args: nil
    0   constant  5
    1   varset    x
    2   constant  b
    3   cdr
    ^^^ offset from above
    4   return
    ```
    
    You can try with other offsets such as by removing the `(setq x 5)`
    and you'll see offset 1 instead.
    
    Right now, we just pass to `signal` bytecode offset. More elaborate would be
    to pass the code object and its offset. Even more elaborate schemes
    could be imagined.
---
 src/bytecode.c | 8 +++++---
 src/data.c     | 8 ++++++++
 src/eval.c     | 6 ++++++
 src/lisp.h     | 5 +++++
 4 files changed, 24 insertions(+), 3 deletions(-)

diff --git a/src/bytecode.c b/src/bytecode.c
index 3c90544..8ef8468 100644
--- a/src/bytecode.c
+++ b/src/bytecode.c
@@ -286,12 +286,13 @@ enum byte_code_op
 
 /* Fetch the next byte from the bytecode stream.  */
 
-#define FETCH (*pc++)
+#define FETCH (last_pc = pc, *pc++)
+#define FETCH_NORECORD (*pc++)
 
 /* Fetch two bytes from the bytecode stream and make a 16-bit number
    out of them.  */
 
-#define FETCH2 (op = FETCH, op + (FETCH << 8))
+#define FETCH2 (op = FETCH, op + (FETCH_NORECORD << 8))
 
 /* Push X onto the execution stack.  The expression X should not
    contain TOP, to avoid competing side effects.  */
@@ -375,6 +376,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, 
Lisp_Object maxdepth,
   bytestr_data = ptr_bounds_clip (bytestr_data + item_bytes, bytestr_length);
   memcpy (bytestr_data, SDATA (bytestr), bytestr_length);
   unsigned char const *pc = bytestr_data;
+  unsigned char const *last_pc = pc;
   ptrdiff_t count = SPECPDL_INDEX ();
 
   if (!NILP (args_template))
@@ -535,7 +537,7 @@ exec_byte_code (Lisp_Object bytestr, Lisp_Object vector, 
Lisp_Object maxdepth,
            if (CONSP (TOP))
              TOP = XCDR (TOP);
            else if (!NILP (TOP))
-             wrong_type_argument (Qlistp, TOP);
+             wrong_type_argument_new (Qlistp, TOP, last_pc - bytestr_data);
            NEXT;
          }
 
diff --git a/src/data.c b/src/data.c
index bce2e53..0ebdd67 100644
--- a/src/data.c
+++ b/src/data.c
@@ -149,6 +149,14 @@ wrong_type_argument (Lisp_Object predicate, Lisp_Object 
value)
   xsignal2 (Qwrong_type_argument, predicate, value);
 }
 
+AVOID
+wrong_type_argument_new (Lisp_Object predicate, Lisp_Object value,
+                        int bytecode_offset)
+{
+  eassert (!TAGGEDP (value, Lisp_Type_Unused0));
+  xsignal2_new (Qwrong_type_argument, predicate, value, bytecode_offset);
+}
+
 void
 pure_write_error (Lisp_Object obj)
 {
diff --git a/src/eval.c b/src/eval.c
index 014905c..4251c3e 100644
--- a/src/eval.c
+++ b/src/eval.c
@@ -1714,6 +1714,12 @@ xsignal2 (Lisp_Object error_symbol, Lisp_Object arg1, 
Lisp_Object arg2)
 }
 
 void
+xsignal2_new (Lisp_Object error_symbol, Lisp_Object arg1, Lisp_Object arg2, 
int bytecode_offset)
+{
+  xsignal (error_symbol, list3 (arg1, arg2, make_fixnum(bytecode_offset)));
+}
+
+void
 xsignal3 (Lisp_Object error_symbol, Lisp_Object arg1, Lisp_Object arg2, 
Lisp_Object arg3)
 {
   xsignal (error_symbol, list3 (arg1, arg2, arg3));
diff --git a/src/lisp.h b/src/lisp.h
index b4ac017..c9b069b 100644
--- a/src/lisp.h
+++ b/src/lisp.h
@@ -603,6 +603,7 @@ extern void char_table_set (Lisp_Object, int, Lisp_Object);
 /* Defined in data.c.  */
 extern AVOID args_out_of_range_3 (Lisp_Object, Lisp_Object, Lisp_Object);
 extern AVOID wrong_type_argument (Lisp_Object, Lisp_Object);
+extern AVOID wrong_type_argument_new (Lisp_Object, Lisp_Object, int 
bytecode_offset);
 extern Lisp_Object default_value (Lisp_Object symbol);
 
 
@@ -3284,6 +3285,9 @@ struct handler
   enum nonlocal_exit nonlocal_exit;
   Lisp_Object val;
 
+  /* The bytecode offset where the error occurred. */
+  int bytecode_offset;
+
   struct handler *next;
   struct handler *nextfree;
 
@@ -4107,6 +4111,7 @@ xsignal (Lisp_Object error_symbol, Lisp_Object data)
 extern AVOID xsignal0 (Lisp_Object);
 extern AVOID xsignal1 (Lisp_Object, Lisp_Object);
 extern AVOID xsignal2 (Lisp_Object, Lisp_Object, Lisp_Object);
+extern AVOID xsignal2_new (Lisp_Object, Lisp_Object, Lisp_Object, int 
bytecode_offset);
 extern AVOID xsignal3 (Lisp_Object, Lisp_Object, Lisp_Object, Lisp_Object);
 extern AVOID signal_error (const char *, Lisp_Object);
 extern AVOID overflow_error (void);



reply via email to

[Prev in Thread] Current Thread [Next in Thread]