[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: next_char inlining
From: |
Eric Blake |
Subject: |
Re: next_char inlining |
Date: |
Fri, 29 Feb 2008 16:43:05 +0000 (UTC) |
User-agent: |
Loom/3.14 (http://gmane.org/) |
Eric Blake <ebb9 <at> byu.net> writes:
> |
> |> ~ I'm also considering adding a placeholder input block that always results
> |> in CHAR_EOF, so that isp is guaranteed to be non-null and we have one less
> |> branch in this loop.
> |
> | Tried this already (see attached patch). It does not provide a noticeable
> | speedup: 41.0 sec instead of 41.1, that's less than 0.5%. You get more
> | speedup (about 1%) by use of __builtin_expect (also attached).
>
> __builtin_expect is gcc specific, while a dummy isp block is not. I'll
> probably make the change to a dummy block anyway. But adding
> __builtin_expect into m4 source code may have other benefits; I'll
> consider it.
I'm rebasing the argv_ref branch with the dummy isp block as follows; my
testing on cygwin with assertions enabled got the best-of-3 user times
on 'autoconf -f' on coreutils from 17.428 to 17.145, or 1.6% improvement
(better than your measured 0.5%, but we used different environments in our
testing).
I've also toyed with the idea of using char*start/char*end management in chains
rather than char*start/size_t len. Either way, there are three pieces of
information with one calculated from the other two (start, end, len). The
difference is that in next_char(), a len-based approach must twiddle two
variables (advance start and decrement len), while an end-based approach only
twiddles one (advance start, but end remains constant). But that patch would
be a bit more invasive to implement, and I'm not convinced it buys time yet,
particularly if I get the buf/consume interface working.
diff --git a/src/input.c b/src/input.c
index 443e053..d9d3551 100644
--- a/src/input.c
+++ b/src/input.c
@@ -74,7 +74,8 @@ enum input_type
{
INPUT_STRING, /* String resulting from macro expansion. */
INPUT_FILE, /* File from command line or include. */
- INPUT_CHAIN /* FIFO chain of separate strings, builtins, and $@ refs. */
+ INPUT_CHAIN, /* FIFO chain of separate strings, builtins, and $@ refs. */
+ INPUT_EOF /* Placeholder at bottom of input stack. */
};
typedef enum input_type input_type;
@@ -136,15 +137,19 @@ static struct obstack *current_input;
/* Bottom of token_stack, for obstack_free. */
static void *token_bottom;
-/* Pointer to top of current_input. */
+/* Pointer to top of current_input, never NULL. */
static input_block *isp;
-/* Pointer to top of wrapup_stack. */
+/* Pointer to top of wrapup_stack, never NULL. */
static input_block *wsp;
-/* Aux. for handling split push_string (). */
+/* Auxiliary for handling split push_string (), NULL if not pushing
+ text for rescanning. */
static input_block *next;
+/* Marker at the end of the input stack. */
+static input_block input_eof = { NULL, INPUT_EOF, "", 0 };
+
/* Flag for next_char () to increment current_line. */
static bool start_of_input_line;
@@ -321,7 +326,7 @@ push_string_init (void)
{
/* Free any memory occupied by completely parsed strings. */
assert (next == NULL);
- while (isp && pop_input (false));
+ while (pop_input (false));
/* Reserve the next location on the obstack. */
next = (input_block *) obstack_alloc (current_input, sizeof *next);
@@ -545,7 +550,7 @@ push_wrapup_init (void)
token_chain *chain;
assert (obstack_object_size (wrapup_stack) == 0);
- if (wsp)
+ if (wsp != &input_eof)
{
i = wsp;
if (i->type == INPUT_STRING)
@@ -745,6 +750,9 @@ pop_input (bool cleanup)
output_current_line = -1;
break;
+ case INPUT_EOF:
+ return false;
+
default:
assert (!"pop_input");
abort ();
@@ -771,7 +779,7 @@ pop_wrapup (void)
obstack_free (current_input, NULL);
free (current_input);
- if (wsp == NULL)
+ if (wsp == &input_eof)
{
/* End of the program. Free all memory even though we are about
to exit, since it makes leak detection easier. */
@@ -790,7 +798,7 @@ pop_wrapup (void)
obstack_init (wrapup_stack);
isp = wsp;
- wsp = NULL;
+ wsp = &input_eof;
input_change = true;
return true;
@@ -881,9 +889,7 @@ peek_input (bool allow_argv)
while (1)
{
- if (block == NULL)
- return CHAR_EOF;
-
+ assert (block);
switch (block->type)
{
case INPUT_STRING:
@@ -950,6 +956,9 @@ peek_input (bool allow_argv)
}
break;
+ case INPUT_EOF:
+ return CHAR_EOF;
+
default:
assert (!"peek_input");
abort ();
@@ -972,7 +981,7 @@ peek_input (bool allow_argv)
`-------------------------------------------------------------------*/
#define next_char(AQ) \
- (isp && isp->type == INPUT_STRING && isp->u.u_s.len && !input_change \
+ (isp->type == INPUT_STRING && isp->u.u_s.len && !input_change
\
? (isp->u.u_s.len--, to_uchar (*isp->u.u_s.str++)) \
: next_char_1 (AQ))
@@ -984,13 +993,7 @@ next_char_1 (bool allow_quote)
while (1)
{
- if (isp == NULL)
- {
- current_file = "";
- current_line = 0;
- return CHAR_EOF;
- }
-
+ assert (isp);
if (input_change)
{
current_file = isp->file;
@@ -1085,6 +1088,9 @@ next_char_1 (bool allow_quote)
}
break;
+ case INPUT_EOF:
+ return CHAR_EOF;
+
default:
assert (!"next_char_1");
abort ();
@@ -1360,8 +1366,8 @@ input_init (void)
obstack_init (&token_stack);
token_bottom = obstack_finish (&token_stack);
- isp = NULL;
- wsp = NULL;
+ isp = &input_eof;
+ wsp = &input_eof;
next = NULL;
start_of_input_line = false;
- M4 1.4.10b [beta] released, Eric Blake, 2008/02/25
- Message not available
- Re: M4 1.4.10b [beta] released, Eric Blake, 2008/02/26
- Re: M4 1.4.10b [beta] released, Bruno Haible, 2008/02/26
- Re: M4 1.4.10b [beta] released, Bruno Haible, 2008/02/28
- Re: M4 1.4.10b [beta] released, Eric Blake, 2008/02/28
- Re: next_char inlining (was: Re: M4 1.4.10b [beta] released), Bruno Haible, 2008/02/29
- Re: next_char inlining, Eric Blake, 2008/02/29
- Re: next_char inlining,
Eric Blake <=
- Re: next_char inlining (was: Re: M4 1.4.10b [beta] released), Bruno Haible, 2008/02/29