]> git.eshelyaron.com Git - emacs.git/commitdiff
Keep a stack reference to bytecode objects being executed (Bug#33014)
authorGemini Lasswell <gazally@runbox.com>
Sun, 14 Oct 2018 19:12:04 +0000 (12:12 -0700)
committerGemini Lasswell <gazally@runbox.com>
Mon, 29 Oct 2018 18:05:00 +0000 (11:05 -0700)
* src/eval.c (Ffuncall): Make local variable 'fun' volatile.
* test/src/eval-tests.el
(eval-tests-byte-code-being-evaluated-is-protected-from-gc):
Add regression test for Bug#33014.
(eval-tests-33014-var): New variable.
(eval-tests-33014-func, eval-tests-33014-redefine): New functions.

src/eval.c
test/src/eval-tests.el

index a51d0c90831fd8ae74b6f042a334a9a16466bb2d..32cfda24d8c417981efac92b1816f190b9cc3772 100644 (file)
@@ -2820,8 +2820,11 @@ Thus, (funcall \\='cons \\='x \\='y) returns (x . y).
 usage: (funcall FUNCTION &rest ARGUMENTS)  */)
   (ptrdiff_t nargs, Lisp_Object *args)
 {
-  Lisp_Object fun, original_fun;
-  Lisp_Object funcar;
+  /* Use 'volatile' here to cause optimizing compilers to keep a
+     reference on the stack to the function's bytecode object.  See
+     Bug#33014.  */
+  Lisp_Object volatile fun;
+  Lisp_Object original_fun, funcar;
   ptrdiff_t numargs = nargs - 1;
   Lisp_Object val;
   ptrdiff_t count;
index 281d959b5306bebee60b440ef1d66c3288c2da89..0c242913e7a5902a37f8641a9f269f7966c19d41 100644 (file)
@@ -139,4 +139,34 @@ crash/abort/malloc assert failure on the next test."
                   (defvaralias 'eval-tests--foo-alias 'eval-tests--foo)
                   'no-warning)))))
 
+(ert-deftest eval-tests-byte-code-being-evaluated-is-protected-from-gc ()
+  "Regression test for Bug#33014.
+Check that byte-compiled objects being executed by exec-byte-code
+are found on the stack and therefore not garbage collected."
+  (should (string= (eval-tests-33014-func)
+                   "before after: ok foo: (e) bar: (a b c d e) baz: a bop: c")))
+
+(defvar eval-tests-33014-var "ok")
+(defun eval-tests-33014-func ()
+  "A function which has a non-trivial constants vector when byte-compiled."
+  (let ((result "before "))
+    (eval-tests-33014-redefine)
+    (garbage-collect)
+    (setq result (concat result (format "after: %s" eval-tests-33014-var)))
+    (let ((vals '(0 1 2 3))
+          (things '(a b c d e)))
+      (dolist (val vals)
+        (setq result
+              (concat result " "
+                      (cond
+                       ((= val 0) (format "foo: %s" (last things)))
+                       ((= val 1) (format "bar: %s" things))
+                       ((= val 2) (format "baz: %s" (car things)))
+                       (t (format "bop: %s" (nth 2 things))))))))
+    result))
+
+(defun eval-tests-33014-redefine ()
+  "Remove the Lisp reference to the byte-compiled object."
+  (setf (symbol-function #'eval-tests-33014-func) nil))
+
 ;;; eval-tests.el ends here