diff options
author | Eric Blake <ebb9@byu.net> | 2008-06-19 07:20:32 -0600 |
---|---|---|
committer | Eric Blake <ebb9@byu.net> | 2008-06-19 07:20:32 -0600 |
commit | ea86620b156b2b008bcedacf1eeb9696f21bfa3a (patch) | |
tree | 59c88127c55e2bccfec31978130a878186a717ae | |
parent | 488e0594caac30004bad8ec4e6ad61b749a8bd20 (diff) | |
download | m4-ea86620b156b2b008bcedacf1eeb9696f21bfa3a.tar.gz |
Revert speed regression from 2008-06-16.
* m4/output.c (m4_shipout_int): Avoid obstack_printf in hot path.
* modules/m4.c (numb_obstack): Likewise.
* m4/input.c (MATCH): Use fewer conditionals, and factor
adjustment of S...
(match_input): ...here for smaller code size.
* m4/syntax.c (m4_reset_syntax, m4_set_quotes, m4_set_comment):
Supply trailing NUL to delimiters, to meet contract of faster
MATCH.
Signed-off-by: Eric Blake <ebb9@byu.net>
-rw-r--r-- | ChangeLog | 14 | ||||
-rw-r--r-- | m4/input.c | 36 | ||||
-rw-r--r-- | m4/output.c | 18 | ||||
-rw-r--r-- | m4/syntax.c | 20 | ||||
-rw-r--r-- | modules/m4.c | 10 |
5 files changed, 71 insertions, 27 deletions
@@ -1,3 +1,15 @@ +2008-06-19 Eric Blake <ebb9@byu.net> + + Revert speed regression from 2008-06-16. + * m4/output.c (m4_shipout_int): Avoid obstack_printf in hot path. + * modules/m4.c (numb_obstack): Likewise. + * m4/input.c (MATCH): Use fewer conditionals, and factor + adjustment of S... + (match_input): ...here for smaller code size. + * m4/syntax.c (m4_reset_syntax, m4_set_quotes, m4_set_comment): + Supply trailing NUL to delimiters, to meet contract of faster + MATCH. + 2008-06-18 Eric Blake <ebb9@byu.net> Whitespace cleanup. @@ -38,7 +50,7 @@ rather than hand-rolled equivalents. Ensure that embedded NUL in trace output does not truncate the trace string. Memory impact: none. - Speed impact: none noticed. + Speed impact: noticeable penalty, from obstack_printf overhead. * ltdl/m4/gnulib-cache.m4: Import obstack-printf-posix module. * m4/macro.c (trace_format): Delete; use obstack_printf instead. (trace_header, trace_pre, trace_post): All callers updated. @@ -1353,10 +1353,11 @@ m4_skip_line (m4 *context, const m4_call_info *caller) /* If the string S of length LEN matches the next characters of the - input stream, return true. If CONSUME is true and a match is - found, the input is discarded; otherwise any characters read are - pushed back again. The function is used only when multicharacter - quotes or comment delimiters are used. + input stream, return true. If CONSUME, the first byte has already + been matched. If a match is found and CONSUME is true, the input + is discarded; otherwise any characters read are pushed back again. + The function is used only when multicharacter quotes or comment + delimiters are used. All strings herein should be unsigned. Otherwise sign-extension of individual chars might break quotes with 8-bit chars in it. @@ -1373,6 +1374,11 @@ match_input (m4 *context, const char *s, size_t len, bool consume) m4_obstack *st; bool result = false; + if (consume) + { + s++; + len--; + } assert (len); ch = peek_char (context, false); if (ch != to_uchar (*s)) @@ -1407,17 +1413,19 @@ match_input (m4 *context, const char *s, size_t len, bool consume) return result; } -/* The macro MATCH() is used to match an unsigned char string S of - length LEN against the input. The first character is handled - inline, for speed. Hopefully, this will not hurt efficiency too - much when single character quotes and comment delimiters are used. - If CONSUME, then CH is the result of next_char, and a successful - match will discard the matched string. Otherwise, CH is the result - of peek_char, and the input stream is effectively unchanged. */ +/* The macro MATCH() is used to match a string S of length LEN against + the input. The first character is handled inline for speed, and + S[LEN] must be safe to dereference (it is faster to do character + comparison prior to length checks). This improves efficiency for + the common case of single character quotes and comment delimiters, + while being safe for disabled delimiters as well as longer + delimiters. If CONSUME, then CH is the result of next_char, and a + successful match will discard the matched string. Otherwise, CH is + the result of peek_char, and the input stream is effectively + unchanged. */ #define MATCH(C, ch, s, len, consume) \ - ((len) && to_uchar ((s)[0]) == (ch) \ - && ((len) == 1 \ - || match_input (C, (s) + (consume), (len) - (consume), consume))) + (to_uchar ((s)[0]) == (ch) \ + && ((len) >> 1 ? match_input (C, s, len, consume) : (len))) /* While the current input character has the given SYNTAX, append it to OBS. Take care not to pop input source unless the next source diff --git a/m4/output.c b/m4/output.c index f86f913b..7f6f9c12 100644 --- a/m4/output.c +++ b/m4/output.c @@ -575,7 +575,23 @@ m4_divert_text (m4 *context, m4_obstack *obs, const char *text, size_t length, void m4_shipout_int (m4_obstack *obs, int val) { - obstack_printf (obs, "%d", val); + /* Using obstack_printf (obs, "%d", val) has too much overhead. */ + unsigned int uval; + char buf[INT_BUFSIZE_BOUND (unsigned int)]; + char *p = buf + INT_STRLEN_BOUND (unsigned int); + + if (val < 0) + { + obstack_1grow (obs, '-'); + uval = -(unsigned int) val; + } + else + uval = val; + *p = '\0'; + do + *--p = '0' + uval % 10; + while (uval /= 10); + obstack_grow (obs, p, strlen (p)); } /* Output the text S, of length LEN, to OBS. If QUOTED, also output diff --git a/m4/syntax.c b/m4/syntax.c index 3bba0a8b..8dda94ea 100644 --- a/m4/syntax.c +++ b/m4/syntax.c @@ -21,6 +21,7 @@ #include <config.h> #include "m4private.h" +#include "xmemdup0.h" /* Define this to see runtime debug info. Implied by DEBUG. */ /*#define DEBUG_SYNTAX */ @@ -393,13 +394,14 @@ m4_reset_syntax (m4_syntax_table *syntax) free (syntax->comm.str1); free (syntax->comm.str2); - syntax->quote.str1 = xmemdup (DEF_LQUOTE, 1); + /* The use of xmemdup0 is exploited by input.c. */ + syntax->quote.str1 = xmemdup0 (DEF_LQUOTE, 1); syntax->quote.len1 = 1; - syntax->quote.str2 = xmemdup (DEF_RQUOTE, 1); + syntax->quote.str2 = xmemdup0 (DEF_RQUOTE, 1); syntax->quote.len2 = 1; - syntax->comm.str1 = xmemdup (DEF_BCOMM, 1); + syntax->comm.str1 = xmemdup0 (DEF_BCOMM, 1); syntax->comm.len1 = 1; - syntax->comm.str2 = xmemdup (DEF_ECOMM, 1); + syntax->comm.str2 = xmemdup0 (DEF_ECOMM, 1); syntax->comm.len2 = 1; add_syntax_attribute (syntax, to_uchar (syntax->quote.str2[0]), @@ -619,9 +621,10 @@ m4_set_quotes (m4_syntax_table *syntax, const char *lq, size_t lq_len, free (syntax->quote.str1); free (syntax->quote.str2); - syntax->quote.str1 = xmemdup (lq, lq_len); + /* The use of xmemdup0 is exploited by input.c. */ + syntax->quote.str1 = xmemdup0 (lq, lq_len); syntax->quote.len1 = lq_len; - syntax->quote.str2 = xmemdup (rq, rq_len); + syntax->quote.str2 = xmemdup0 (rq, rq_len); syntax->quote.len2 = rq_len; /* changequote overrides syntax_table, but be careful when it is @@ -692,9 +695,10 @@ m4_set_comment (m4_syntax_table *syntax, const char *bc, size_t bc_len, free (syntax->comm.str1); free (syntax->comm.str2); - syntax->comm.str1 = xmemdup (bc, bc_len); + /* The use of xmemdup0 is exploited by input.c. */ + syntax->comm.str1 = xmemdup0 (bc, bc_len); syntax->comm.len1 = bc_len; - syntax->comm.str2 = xmemdup (ec, ec_len); + syntax->comm.str2 = xmemdup0 (ec, ec_len); syntax->comm.len2 = ec_len; /* changecom overrides syntax_table, but be careful when it is used diff --git a/modules/m4.c b/modules/m4.c index 1857d6f4..c46b3af3 100644 --- a/modules/m4.c +++ b/modules/m4.c @@ -1207,9 +1207,13 @@ numb_obstack (m4_obstack *obs, number value, int radix, int min) s++; } len = strlen (s); - if (min < len) - min = len; - obstack_printf (obs, "%.*d%s", min - len, 0, s); + if (len < min) + { + min -= len; + obstack_blank (obs, min); + memset ((char *) obstack_next_free (obs) - min, '0', min); + } + obstack_grow (obs, s, len); } |