unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
* [RFC] inline DEFUNs
@ 2013-12-04  9:44 Dmitry Antipov
  2013-12-04 16:19 ` Eli Zaretskii
  0 siblings, 1 reply; 2+ messages in thread
From: Dmitry Antipov @ 2013-12-04  9:44 UTC (permalink / raw)
  To: Emacs development discussions

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

Recent discussion about dropping selected_window (started at
http://lists.gnu.org/archive/html/emacs-devel/2013-11/msg01090.html)
raises an interesting question.  In short, we want Fselected_window
fast (read: inline in C) but still accessible from Lisp.

Possible solution is to split DEFSUBR from DEFUN and use DEFINLINE in
.h to define inline function, with matching DEFSUBR somewhere in .c.
Attached patch converts Fcurrent_buffer to inline function.  On my
system, this effectively eliminates 63 calls to Fcurrent_buffer at the
cost of increasing .text with just 48 bytes (for default '-O2 -g3' build).
This feature also requires special support in make-docfile and Lisp code
responsible to find and jump to a function definition.

Dmitry

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #2: inline_defun.patch --]
[-- Type: text/x-patch; name="inline_defun.patch", Size: 7114 bytes --]

=== modified file 'lib-src/make-docfile.c'
--- lib-src/make-docfile.c	2013-10-10 01:29:30 +0000
+++ lib-src/make-docfile.c	2013-12-04 09:33:30 +0000
@@ -734,6 +734,7 @@
     {
       int doc_keyword = 0;
       int defunflag = 0;
+      int inlineflag = 0;
       int defvarperbufferflag = 0;
       int defvarflag = 0;
       enum global_type type = INVALID;
@@ -800,12 +801,13 @@
 	    continue;
 	  c = getc (infile);
 	  defunflag = c == 'U';
+	  inlineflag = c == 'I';
 	}
       else continue;
 
       if (generate_globals
 	  && (!defvarflag || defvarperbufferflag || type == INVALID)
-	  && !defunflag)
+	  && !defunflag && !inlineflag)
 	continue;
 
       while (c != '(')
@@ -860,7 +862,7 @@
 	commas = generate_globals ? 4 : 5;
       else if (defvarperbufferflag)
 	commas = 3;
-      else if (defvarflag)
+      else if (defvarflag || inlineflag)
 	commas = 1;
       else  /* For DEFSIMPLE and DEFPRED.  */
 	commas = 2;

=== modified file 'lisp/emacs-lisp/find-func.el'
--- lisp/emacs-lisp/find-func.el	2013-01-01 09:11:05 +0000
+++ lisp/emacs-lisp/find-func.el	2013-12-04 09:08:58 +0000
@@ -218,7 +218,7 @@
 		 (concat "DEFVAR[A-Z_]*[ \t\n]*([ \t\n]*\""
 			 (regexp-quote (symbol-name fun-or-var))
 			 "\"")
-	       (concat "DEFUN[ \t\n]*([ \t\n]*\""
+	       (concat "DEF\\(UN\\|INLINE\\)[ \t\n]*([ \t\n]*\""
 		       (regexp-quote (subr-name fun-or-var))
 		       "\""))
 	     nil t)
@@ -272,7 +272,7 @@
   ;; that defines something else.
   (while (and (symbolp symbol) (get symbol 'definition-name))
     (setq symbol (get symbol 'definition-name)))
-  (if (string-match "\\`src/\\(.*\\.\\(c\\|m\\)\\)\\'" library)
+  (if (string-match "\\`src/\\(.*\\.\\(h\\|c\\|m\\)\\)\\'" library)
       (find-function-C-source symbol (match-string 1 library) type)
     (when (string-match "\\.el\\(c\\)\\'" library)
       (setq library (substring library 0 (match-beginning 1))))

=== modified file 'lisp/help-fns.el'
--- lisp/help-fns.el	2013-06-15 01:12:05 +0000
+++ lisp/help-fns.el	2013-12-04 09:07:43 +0000
@@ -192,14 +192,15 @@
 		      (let ((pnt (search-forward (concat "\x1f" name "\n"))))
 			(re-search-backward "\x1fS\\(.*\\)")
 			(let ((file (match-string 1)))
-			  (if (member file build-files)
+			  (if (or (member file build-files)
+				  (string-match "\\.h$" file))
 			      (throw 'loop file)
 			    (goto-char pnt))))))))
 	(if (string-match "^ns.*\\(\\.o\\|obj\\)\\'" file)
 	    (setq file (replace-match ".m" t t file 1))
 	  (if (string-match "\\.\\(o\\|obj\\)\\'" file)
 	      (setq file (replace-match ".c" t t file))))
-	(if (string-match "\\.\\(c\\|m\\)\\'" file)
+	(if (string-match "\\.\\(h\\|c\\|m\\)\\'" file)
 	    (concat "src/" file)
 	  file)))))
 

=== modified file 'src/Makefile.in'
--- src/Makefile.in	2013-11-27 18:25:44 +0000
+++ src/Makefile.in	2013-12-04 08:20:05 +0000
@@ -455,7 +455,7 @@
 $(etc)/DOC: $(libsrc)/make-docfile$(EXEEXT) $(obj) $(lisp)
 	$(MKDIR_P) $(etc)
 	-rm -f $(etc)/DOC
-	$(libsrc)/make-docfile -d $(srcdir) $(SOME_MACHINE_OBJECTS) $(obj) > $(etc)/DOC
+	$(libsrc)/make-docfile -d $(srcdir) $(notdir $(shell echo $(srcdir)/*.h)) $(SOME_MACHINE_OBJECTS) $(obj) > $(etc)/DOC
 	$(libsrc)/make-docfile -a $(etc)/DOC -d $(lispsource) `sed -n -e 's| \\\\||' -e 's|^[ 	]*$$(lispsource)/||p' $(srcdir)/lisp.mk`
 
 $(libsrc)/make-docfile$(EXEEXT):

=== modified file 'src/buffer.c'
--- src/buffer.c	2013-11-28 22:43:09 +0000
+++ src/buffer.c	2013-12-04 08:19:36 +0000
@@ -2079,14 +2079,8 @@
   return unbind_to (count, Qnil);
 }
 
-DEFUN ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0,
-       doc: /* Return the current buffer as a Lisp object.  */)
-  (void)
-{
-  register Lisp_Object buf;
-  XSETBUFFER (buf, current_buffer);
-  return buf;
-}
+/* Defined in buffer.h.  */
+DEFSUBR ("current-buffer", Fcurrent_buffer, Scurrent_buffer, 0, 0, 0);
 
 /* Set the current buffer to B, and do not set windows_or_buffers_changed.
    This is used by redisplay.  */

=== modified file 'src/buffer.h'
--- src/buffer.h	2013-12-01 22:33:13 +0000
+++ src/buffer.h	2013-12-04 09:20:38 +0000
@@ -1086,6 +1086,13 @@
 extern void restore_buffer (Lisp_Object);
 extern void set_buffer_if_live (Lisp_Object);
 
+DEFINLINE ("current-buffer", Fcurrent_buffer,
+  doc: /* Return the current buffer as a Lisp object.  */)
+  (void)
+{
+  return make_lisp_ptr (current_buffer, Lisp_Vectorlike);
+}
+
 /* Set the current buffer to B.
 
    We previously set windows_or_buffers_changed here to invalidate

=== modified file 'src/eval.c'
--- src/eval.c	2013-12-02 14:45:22 +0000
+++ src/eval.c	2013-12-04 08:19:36 +0000
@@ -27,6 +27,7 @@
 #include "keyboard.h"
 #include "dispextern.h"
 #include "frame.h"		/* For XFRAME.  */
+#include "buffer.h"
 
 #if HAVE_X_WINDOWS
 #include "xterm.h"

=== modified file 'src/lisp.h'
--- src/lisp.h	2013-11-30 09:25:31 +0000
+++ src/lisp.h	2013-12-04 09:23:18 +0000
@@ -2615,29 +2615,43 @@
 
 /* This version of DEFUN declares a function prototype with the right
    arguments, so we can catch errors with maxargs at compile-time.  */
+
 #ifdef _MSC_VER
-#define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc)	\
-   Lisp_Object fnname DEFUN_ARGS_ ## maxargs ;				\
+
+#define DEFSUBR(lname, fnname, sname, minargs, maxargs, intspec)	\
    static struct Lisp_Subr alignas (GCALIGNMENT) sname =		\
    { { (PVEC_SUBR << PSEUDOVECTOR_AREA_BITS)				\
        | (sizeof (struct Lisp_Subr) / sizeof (EMACS_INT)) },		\
       { (Lisp_Object (__cdecl *)(void))fnname },                        \
        minargs, maxargs, lname, intspec, 0};				\
-   Lisp_Object fnname
+
 #else  /* not _MSC_VER */
+
 # if __STDC_VERSION__ < 199901
 #  define DEFUN_FUNCTION_INIT(fnname, maxargs) (Lisp_Object (*) (void)) fnname
 # else
 #  define DEFUN_FUNCTION_INIT(fnname, maxargs) .a ## maxargs = fnname
 # endif
+
+#define DEFSUBR(lname, fnname, sname, minargs, maxargs, intspec)	\
+  static struct Lisp_Subr alignas (GCALIGNMENT) sname =			\
+  { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS },				\
+    { DEFUN_FUNCTION_INIT (fnname, maxargs) },				\
+    minargs, maxargs, lname, intspec, 0}				\
+
+#endif /* _MSC_VER */
+
 #define DEFUN(lname, fnname, sname, minargs, maxargs, intspec, doc)	\
    Lisp_Object fnname DEFUN_ARGS_ ## maxargs ;				\
-   static struct Lisp_Subr alignas (GCALIGNMENT) sname =		\
-     { { PVEC_SUBR << PSEUDOVECTOR_AREA_BITS },				\
-       { DEFUN_FUNCTION_INIT (fnname, maxargs) },			\
-       minargs, maxargs, lname, intspec, 0};				\
+   DEFSUBR (lname, fnname, sname, minargs, maxargs, intspec);		\
    Lisp_Object fnname
-#endif
+
+/* Special form to define inline function which is also accessible
+   from Lisp.  Note that corresponding Lisp_Subr should be defined
+   with DEFSUBR separately.  */
+
+#define DEFINLINE(lname, fnname, doc) \
+  INLINE Lisp_Object fnname
 
 /* Note that the weird token-substitution semantics of ANSI C makes
    this work for MANY and UNEVALLED.  */


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

* Re: [RFC] inline DEFUNs
  2013-12-04  9:44 [RFC] inline DEFUNs Dmitry Antipov
@ 2013-12-04 16:19 ` Eli Zaretskii
  0 siblings, 0 replies; 2+ messages in thread
From: Eli Zaretskii @ 2013-12-04 16:19 UTC (permalink / raw)
  To: Dmitry Antipov; +Cc: emacs-devel

> Date: Wed, 04 Dec 2013 13:44:47 +0400
> From: Dmitry Antipov <dmantipov@yandex.ru>
> 
> Recent discussion about dropping selected_window (started at
> http://lists.gnu.org/archive/html/emacs-devel/2013-11/msg01090.html)
> raises an interesting question.  In short, we want Fselected_window
> fast (read: inline in C) but still accessible from Lisp.
> 
> Possible solution is to split DEFSUBR from DEFUN and use DEFINLINE in
> .h to define inline function, with matching DEFSUBR somewhere in .c.
> Attached patch converts Fcurrent_buffer to inline function.  On my
> system, this effectively eliminates 63 calls to Fcurrent_buffer at the
> cost of increasing .text with just 48 bytes (for default '-O2 -g3' build).
> This feature also requires special support in make-docfile and Lisp code
> responsible to find and jump to a function definition.

Perhaps I don't understand some subtlety here, but the usual way of
dealing with this is to have an inline C function, which can then be
called from C, and have Fcurrent_buffer that calls that inline
function.

Am I missing something?



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

end of thread, other threads:[~2013-12-04 16:19 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-12-04  9:44 [RFC] inline DEFUNs Dmitry Antipov
2013-12-04 16:19 ` Eli Zaretskii

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