emacs-diffs
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Emacs-diffs] scratch/raeburn-startup 913592c 14/17: Optimize reading of


From: Ken Raeburn
Subject: [Emacs-diffs] scratch/raeburn-startup 913592c 14/17: Optimize reading of ASCII symbols from a .elc file.
Date: Thu, 15 Dec 2016 11:33:19 +0000 (UTC)

branch: scratch/raeburn-startup
commit 913592ce9b9b879dfedefd803035112de84dee32
Author: Ken Raeburn <address@hidden>
Commit: Ken Raeburn <address@hidden>

    Optimize reading of ASCII symbols from a .elc file.
    
    Normally, for each character read by read1, readchar is called, which
    determines the kind of input function and selects a function to call
    to read a byte, possibly calling it multiple times for multibyte
    characters.  If the input function is the symbol get-file-char,
    readbyte_from_file must block input temporarily while reading.  The
    called function must also support a "pushback" operation.
    
    This is a lot of work per byte and per character.  Manually expanding
    inline for this case lets us reduce redundant or unneeded checks.  We
    can also reduce the block/unblock calls, letting input normally stay
    blocked from one getc call to the next.
    
    * src/lread.c (read1): When reading a symbol name, if readcharfun is
    Qget_file_char, use a separate do loop.  Expand the main READCHAR
    invocation into the relevant parts of readchar().  Expand the main
    readbyte call of readchar used for ASCII characters into the relevant
    parts of readbyte_from_file.  Block input in this version of the loop,
    unblocking temporarily only when needed.
---
 src/lread.c |  160 +++++++++++++++++++++++++++++++++++++++++++++++++++--------
 1 file changed, 139 insertions(+), 21 deletions(-)

diff --git a/src/lread.c b/src/lread.c
index c9dc222..62a55e7 100644
--- a/src/lread.c
+++ b/src/lread.c
@@ -185,6 +185,8 @@ static int readbyte_from_string (int, Lisp_Object);
    means that there's no unread character.  */
 static int unread_char;
 
+/* Note that this is expanded inline by hand in a branch of read1 for
+   performance reasons.  */
 static int
 readchar (Lisp_Object readcharfun, bool *multibyte)
 {
@@ -462,6 +464,8 @@ readbyte_for_lambda (int c, Lisp_Object readcharfun)
 }
 
 
+/* Note that this is expanded inline by hand in a branch of read1 for
+   performance reasons.  */
 static int
 readbyte_from_file (int c, Lisp_Object readcharfun)
 {
@@ -3330,34 +3334,148 @@ read1 (Lisp_Object readcharfun, int *pch, bool 
first_in_list)
        {
          char *end = read_buffer + read_buffer_size;
 
-         do
+         if (EQ (readcharfun, Qget_file_char))
            {
-             if (end - p < MAX_MULTIBYTE_LENGTH)
+             /* This is the below "do" loop with changes:
+
+                Some calls to READCHAR and readbyte_from_file are
+                expanded inline with irrelevant branches including
+                MULE support pruned.
+
+                Instead of blocking and unblocking input around each
+                getc call, we block input at the start and unblock at
+                the end, and make the "normal" state in this loop to
+                have input being blocked.  Calls to functions that
+                may signal errors are wrapped in unblock/block calls.
+
+                This keeps us from constantly fiddling with input
+                blocking in the common case of scanning additional
+                ASCII symbol name characters (other than backslash)
+                without interrupted reads.
+
+                This is done for performance reasons.  */
+             block_input ();
+             do
                {
-                 ptrdiff_t offset = p - read_buffer;
-                 grow_read_buffer ();
-                 p = read_buffer + offset;
-                 end = read_buffer + read_buffer_size;
-               }
+                 if (end - p < MAX_MULTIBYTE_LENGTH)
+                   {
+                     ptrdiff_t offset = p - read_buffer;
+                     unblock_input ();
+                     grow_read_buffer ();
+                     block_input ();
+                     p = read_buffer + offset;
+                     end = read_buffer + read_buffer_size;
+                   }
+
+                 if (c == '\\')
+                   {
+                     unblock_input ();
+                     c = READCHAR;
+                     if (c == -1)
+                       end_of_file_error ();
+                     quoted = 1;
+                     block_input ();
+                   }
+
+                 if (multibyte)
+                   p += CHAR_STRING (c, (unsigned char *) p);
+                 else
+                   *p++ = c;
+                 /* c = READCHAR; expanded below:  */
+                 readchar_count++;
+                 if (unread_char >= 0)
+                   {
+                     c = unread_char;
+                     unread_char = -1;
+                   }
+                 else
+                   {
+                     unsigned char buf[MAX_MULTIBYTE_LENGTH];
+                     int i, len;
+
+                     /* c = readbyte_from_file (-1, readcharfun);  */
+                     /* expands into:  */
+                     c = getc_unlocked (instream);
+
+                     /* Interrupted reads have been observed while
+                        reading over the network.  */
+                     while (c == EOF && ferror (instream) && errno == EINTR)
+                       {
+                         unblock_input ();
+                         QUIT;
+                         block_input ();
+                         clearerr (instream);
+                         c = getc_unlocked (instream);
+                       }
 
-             if (c == '\\')
+                     if (c == EOF)
+                       c = -1;
+
+                     if (c < 0)
+                       goto have_char_from_file;
+                     if (ASCII_CHAR_P (c))
+                       goto have_char_from_file;
+                     i = 0;
+                     buf[i++] = c;
+                     len = BYTES_BY_CHAR_HEAD (c);
+                     while (i < len)
+                       {
+                         unblock_input ();
+                         c = readbyte_from_file (-1, readcharfun);
+                         if (c < 0 || ! TRAILING_CODE_P (c))
+                           {
+                             while (--i > 1)
+                               readbyte_from_file (buf[i], readcharfun);
+                             c = BYTE8_TO_CHAR (buf[0]);
+                             block_input ();
+                             goto have_char_from_file;
+                           }
+                         buf[i++] = c;
+                       }
+                     c = STRING_CHAR (buf);
+                     /* fall through */
+                   have_char_from_file:
+                     /* Input should be blocked at this point.  */
+                     ;
+                   }
+               }
+             while (c > 040
+                    && c != NO_BREAK_SPACE
+                    && (c >= 0200
+                        || strchr ("\"';()[]#`,", c) == NULL));
+             unblock_input ();
+           }
+         else
+           {
+             do
                {
+                 if (end - p < MAX_MULTIBYTE_LENGTH)
+                   {
+                     ptrdiff_t offset = p - read_buffer;
+                     grow_read_buffer ();
+                     p = read_buffer + offset;
+                     end = read_buffer + read_buffer_size;
+                   }
+
+                 if (c == '\\')
+                   {
+                     c = READCHAR;
+                     if (c == -1)
+                       end_of_file_error ();
+                     quoted = 1;
+                   }
+
+                 if (multibyte)
+                   p += CHAR_STRING (c, (unsigned char *) p);
+                 else
+                   *p++ = c;
                  c = READCHAR;
-                 if (c == -1)
-                   end_of_file_error ();
-                 quoted = 1;
                }
-
-             if (multibyte)
-               p += CHAR_STRING (c, (unsigned char *) p);
-             else
-               *p++ = c;
-             c = READCHAR;
+             while (c > 040
+                    && c != NO_BREAK_SPACE
+                    && (c >= 0200
+                        || strchr ("\"';()[]#`,", c) == NULL));
            }
-         while (c > 040
-                && c != NO_BREAK_SPACE
-                && (c >= 0200
-                    || strchr ("\"';()[]#`,", c) == NULL));
 
          if (p == end)
            {



reply via email to

[Prev in Thread] Current Thread [Next in Thread]