]> git.eshelyaron.com Git - emacs.git/commitdiff
Experiment giving bytecode in traceback...
authorrocky <rocky@gnu.org>
Mon, 27 Apr 2020 19:14:12 +0000 (15:14 -0400)
committerrocky <rocky@gnu.org>
Mon, 27 Apr 2020 19:14:12 +0000 (15:14 -0400)
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
src/data.c
src/eval.c
src/lisp.h

index 3c90544f3f2bc59ae890063ac818b58020fd4ba3..8ef84682035e9b55c0ae9ceb9399022c21260e4b 100644 (file)
@@ -286,12 +286,13 @@ enum byte_code_op
 \f
 /* 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;
          }
 
index bce2e53cfb678804a79fee425b9081f12f961c4a..0ebdd6726790c15c30d978eb85280cd97d56cdb3 100644 (file)
@@ -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)
 {
index 014905ce6df03e2992c8e59b4e4666479ccfc144..4251c3e330422345d26bcbc49ff36f152da39271 100644 (file)
@@ -1713,6 +1713,12 @@ xsignal2 (Lisp_Object error_symbol, Lisp_Object arg1, Lisp_Object arg2)
   xsignal (error_symbol, list2 (arg1, 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)
 {
index b4ac017dcf50927f246b5dab76e68f87aa83f815..c9b069b56cac4b0580efda92e7128962e4f9bb66 100644 (file)
@@ -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);