unofficial mirror of emacs-devel@gnu.org 
 help / color / mirror / code / Atom feed
From: Dmitry Antipov <dmantipov@yandex.ru>
To: Emacs development discussions <emacs-devel@gnu.org>
Subject: [RFC] inline DEFUNs
Date: Wed, 04 Dec 2013 13:44:47 +0400	[thread overview]
Message-ID: <529EF98F.6050903@yandex.ru> (raw)

[-- 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.  */


             reply	other threads:[~2013-12-04  9:44 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-12-04  9:44 Dmitry Antipov [this message]
2013-12-04 16:19 ` [RFC] inline DEFUNs Eli Zaretskii

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

  List information: https://www.gnu.org/software/emacs/

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=529EF98F.6050903@yandex.ru \
    --to=dmantipov@yandex.ru \
    --cc=emacs-devel@gnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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).