]> git.eshelyaron.com Git - emacs.git/commitdiff
Guard against function redefinition during deferred load
authorAndrea Corallo <akrl@sdf.org>
Mon, 23 Mar 2020 15:57:48 +0000 (15:57 +0000)
committerAndrea Corallo <akrl@sdf.org>
Mon, 23 Mar 2020 20:37:59 +0000 (20:37 +0000)
lisp/emacs-lisp/comp.el
src/comp.c

index 273b41f54277c96d3d2b401a9e95548ca495756e..c6f2ca13aab904528bd84371903107757d1d9bad 100644 (file)
@@ -1160,12 +1160,15 @@ the annotation emission."
 (cl-defgeneric comp-emit-for-top-level (form for-late-load)
   "Emit the limple code for top level FORM.")
 
-(cl-defmethod comp-emit-for-top-level ((form byte-to-native-function) _)
+(cl-defmethod comp-emit-for-top-level ((form byte-to-native-function)
+                                       for-late-load)
   (let* ((name (byte-to-native-function-name form))
          (f (gethash name (comp-ctxt-funcs-h comp-ctxt)))
          (args (comp-func-args f)))
     (cl-assert (and name f))
-    (comp-emit (comp-call 'comp--register-subr
+    (comp-emit (comp-call (if for-late-load
+                              'comp--late-register-subr
+                            'comp--register-subr)
                           (make-comp-mvar :constant name)
                           (make-comp-mvar :constant (comp-args-base-min args))
                           (make-comp-mvar :constant (if (comp-args-p args)
@@ -2186,6 +2189,9 @@ display a message."
         (save-excursion
           (goto-char (point-max))
           (insert msg "\n")))
+      ;; `comp-deferred-pending-h' should be empty at this stage.
+      ;; Reset it anyway.
+      (setf comp-deferred-pending-h (make-hash-table :equal #'eq))
       (message msg))))
 
 \f
index b563f27da8ff923edbdd712215a838d49c090e37..3205a29a1040a815418bd227a5283d4c83836c13 100644 (file)
@@ -3401,14 +3401,16 @@ maybe_defer_native_compilation (Lisp_Object function_name,
   Lisp_Object src =
     concat2 (CALL1I (file-name-sans-extension, Vload_file_name),
             build_pure_c_string (".el"));
-  if (!NILP (Ffile_exists_p (src)))
-    {
-      comp_deferred_compilation = false;
-      Frequire (intern_c_string ("comp"), Qnil, Qnil);
-      comp_deferred_compilation = true;
-      CALLN (Ffuncall, intern_c_string ("native-compile-async"), src, Qnil,
-            Qlate);
-    }
+  if (NILP (Ffile_exists_p (src)))
+    return;
+
+  /* Really happening.  */
+  Fputhash (function_name, definition, Vcomp_deferred_pending_h);
+  comp_deferred_compilation = false;
+  Frequire (intern_c_string ("comp"), Qnil, Qnil);
+  comp_deferred_compilation = true;
+  CALLN (Ffuncall, intern_c_string ("native-compile-async"), src, Qnil,
+        Qlate);
 }
 
 \f
@@ -3584,6 +3586,21 @@ DEFUN ("comp--register-subr", Fcomp__register_subr, Scomp__register_subr,
   return Qnil;
 }
 
+DEFUN ("comp--late-register-subr", Fcomp__late_register_subr,
+       Scomp__late_register_subr, 7, 7, 0,
+       doc: /* This gets called by late_top_level_run during load
+              phase to register each exported subr.  */)
+     (Lisp_Object name, Lisp_Object minarg, Lisp_Object maxarg,
+      Lisp_Object c_name, Lisp_Object doc, Lisp_Object intspec,
+      Lisp_Object comp_u)
+{
+  if (!NILP (Fequal (Fsymbol_function (name),
+                    Fgethash (name, Vcomp_deferred_pending_h, Qnil))))
+    Fcomp__register_subr (name, minarg, maxarg, c_name, doc, intspec, comp_u);
+  Fremhash (name, Vcomp_deferred_pending_h);
+  return Qnil;
+}
+
 /* Load related routines.  */
 DEFUN ("native-elisp-load", Fnative_elisp_load, Snative_elisp_load, 1, 2, 0,
        doc: /* Load native elisp code FILE.
@@ -3714,6 +3731,7 @@ syms_of_comp (void)
   defsubr (&Scomp__release_ctxt);
   defsubr (&Scomp__compile_ctxt_to_file);
   defsubr (&Scomp__register_subr);
+  defsubr (&Scomp__late_register_subr);
   defsubr (&Snative_elisp_load);
 
   staticpro (&comp.exported_funcs_h);
@@ -3742,6 +3760,11 @@ syms_of_comp (void)
   DEFVAR_LISP ("comp-native-path-postfix", Vcomp_native_path_postfix,
               doc: /* Postifix to be added to the .eln compilation path.  */);
   Vcomp_native_path_postfix = Qnil;
+
+  DEFVAR_LISP ("comp-deferred-pending-h", Vcomp_deferred_pending_h,
+              doc: /* Hash table symbol-name -> function-value.  For
+                      internal use during  */);
+  Vcomp_deferred_pending_h = CALLN (Fmake_hash_table, QCtest, Qeq);
 }
 
 #endif /* HAVE_NATIVE_COMP */