summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Blake <ebb9@byu.net>2008-06-19 07:20:32 -0600
committerEric Blake <ebb9@byu.net>2008-06-19 07:20:32 -0600
commitea86620b156b2b008bcedacf1eeb9696f21bfa3a (patch)
tree59c88127c55e2bccfec31978130a878186a717ae
parent488e0594caac30004bad8ec4e6ad61b749a8bd20 (diff)
downloadm4-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--ChangeLog14
-rw-r--r--m4/input.c36
-rw-r--r--m4/output.c18
-rw-r--r--m4/syntax.c20
-rw-r--r--modules/m4.c10
5 files changed, 71 insertions, 27 deletions
diff --git a/ChangeLog b/ChangeLog
index 7dc8277f..c838a8b8 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -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.
diff --git a/m4/input.c b/m4/input.c
index ea59b44a..4306613c 100644
--- a/m4/input.c
+++ b/m4/input.c
@@ -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);
}