ash: speed up NOFORK code in ash by eliminating second find_applet().

some code reduction along the way.

function                                             old     new   delta
run_list                                            1971    1981     +10
run_nofork_applet_prime                              181     182      +1
unsetcmd                                              97      96      -1
delete_cmd_entry                                      54      53      -1
describe_command                                     399     397      -2
cmdlookup                                            152     150      -2
evaltreenr                                           602     599      -3
evaltree                                             602     599      -3
clearcmdentry                                        101      98      -3
cdcmd                                                675     672      -3
hashcmd                                              305     301      -4
find_command                                         933     910     -23
evalcommand                                         1371    1229    -142
------------------------------------------------------------------------------
(add/remove: 0/0 grow/shrink: 2/11 up/down: 11/-187)         Total: -176 bytes
This commit is contained in:
Denis Vlasenko 2008-04-13 02:25:53 +00:00
parent f78a656f7c
commit 7465dbcf2a
3 changed files with 34 additions and 23 deletions

View File

@ -146,6 +146,15 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **
memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0])); memcpy(tmp_argv, argv, (argc+1) * sizeof(tmp_argv[0]));
/* Finally we can call NOFORK applet's main() */ /* Finally we can call NOFORK applet's main() */
rc = applet_main[applet_no](argc, tmp_argv); rc = applet_main[applet_no](argc, tmp_argv);
/* The whole reason behind nofork_save_area is that <applet>_main
* may exit non-locally! For example, in hush Ctrl-Z tries to
* (modulo bugs) to dynamically create child (backgrounded task)
* if it detects that Ctrl-Z was pressed when a NOFORK was running!
* Testcase: interactive "rm -i".
* Don't fool yourself into thinking "and <applet>_main() returns
* quickly here" and removing "useless" nofork_save_area code. */
} else { /* xfunc died in NOFORK applet */ } else { /* xfunc died in NOFORK applet */
/* in case they meant to return 0... */ /* in case they meant to return 0... */
if (rc == -2222) if (rc == -2222)
@ -154,7 +163,7 @@ int run_nofork_applet_prime(struct nofork_save_area *old, int applet_no, char **
/* Restoring globals */ /* Restoring globals */
restore_nofork_data(old); restore_nofork_data(old);
return rc; return rc & 0xff; /* don't confuse people with "exitcodes" >255 */
} }
int run_nofork_applet(int applet_no, char **argv) int run_nofork_applet(int applet_no, char **argv)

View File

@ -6828,9 +6828,13 @@ struct builtincmd {
#define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4) #define IS_BUILTIN_ASSIGN(b) ((b)->name[0] & 4)
struct cmdentry { struct cmdentry {
int cmdtype; smallint cmdtype; /* CMDxxx */
union param { union param {
int index; int index;
/* index >= 0 for commands without path (slashes) */
/* (TODO: what exactly does the value mean? PATH position?) */
/* index == -1 for commands with slashes */
/* index == (-2 - applet_no) for NOFORK applets */
const struct builtincmd *cmd; const struct builtincmd *cmd;
struct funcnode *func; struct funcnode *func;
} u; } u;
@ -6867,7 +6871,7 @@ static void find_command(char *, struct cmdentry *, int, const char *);
struct tblentry { struct tblentry {
struct tblentry *next; /* next entry in hash chain */ struct tblentry *next; /* next entry in hash chain */
union param param; /* definition of builtin function */ union param param; /* definition of builtin function */
short cmdtype; /* index identifying command */ smallint cmdtype; /* CMDxxx */
char rehash; /* if set, cd done since entry created */ char rehash; /* if set, cd done since entry created */
char cmdname[ARB]; /* name of command */ char cmdname[ARB]; /* name of command */
}; };
@ -7355,7 +7359,7 @@ describe_command(char *command, int describe_command_verbose)
case CMDNORMAL: { case CMDNORMAL: {
int j = entry.u.index; int j = entry.u.index;
char *p; char *p;
if (j == -1) { if (j < 0) {
p = command; p = command;
} else { } else {
do { do {
@ -8747,22 +8751,17 @@ evalcommand(union node *cmd, int flags)
/* Execute the command. */ /* Execute the command. */
switch (cmdentry.cmdtype) { switch (cmdentry.cmdtype) {
default: default:
#if ENABLE_FEATURE_SH_NOFORK #if ENABLE_FEATURE_SH_NOFORK
{ {
/* TODO: don't rerun find_applet_by_name, find_command /* find_command() encodes applet_no as (-2 - applet_no) */
* already did it. Make it save applet_no somewhere */ int applet_no = (- cmdentry.u.index - 2);
int applet_no = find_applet_by_name(argv[0]);
if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) { if (applet_no >= 0 && APPLET_IS_NOFORK(applet_no)) {
struct nofork_save_area nofork_save;
listsetvar(varlist.list, VEXPORT|VSTACK); listsetvar(varlist.list, VEXPORT|VSTACK);
save_nofork_data(&nofork_save); /* run <applet>_main() */
/* run <applet>_main(), then restore nofork_save_area */ exitstatus = run_nofork_applet(applet_no, argv);
exitstatus = run_nofork_applet_prime(&nofork_save, applet_no, argv) & 0xff;
break; break;
} }
} }
#endif #endif
/* Fork off a child process if necessary. */ /* Fork off a child process if necessary. */
@ -11618,10 +11617,13 @@ find_command(char *name, struct cmdentry *entry, int act, const char *path)
} }
#if ENABLE_FEATURE_SH_STANDALONE #if ENABLE_FEATURE_SH_STANDALONE
if (find_applet_by_name(name) >= 0) { {
entry->cmdtype = CMDNORMAL; int applet_no = find_applet_by_name(name);
entry->u.index = -1; if (applet_no >= 0) {
return; entry->cmdtype = CMDNORMAL;
entry->u.index = -2 - applet_no;
return;
}
} }
#endif #endif
@ -12691,7 +12693,7 @@ is_right_associativity(operator prec)
|| prec == PREC(TOK_CONDITIONAL)); || prec == PREC(TOK_CONDITIONAL));
} }
typedef struct ARITCH_VAR_NUM { typedef struct {
arith_t val; arith_t val;
arith_t contidional_second_val; arith_t contidional_second_val;
char contidional_second_val_initialized; char contidional_second_val_initialized;
@ -12699,9 +12701,9 @@ typedef struct ARITCH_VAR_NUM {
else is variable name */ else is variable name */
} v_n_t; } v_n_t;
typedef struct CHK_VAR_RECURSIVE_LOOPED { typedef struct chk_var_recursive_looped_t {
const char *var; const char *var;
struct CHK_VAR_RECURSIVE_LOOPED *next; struct chk_var_recursive_looped_t *next;
} chk_var_recursive_looped_t; } chk_var_recursive_looped_t;
static chk_var_recursive_looped_t *prev_chk_var_recursive; static chk_var_recursive_looped_t *prev_chk_var_recursive;

View File

@ -1861,7 +1861,7 @@ static int run_pipe(struct pipe *pi)
//sp: if (child->sp) //sp: if (child->sp)
argv_expanded = expand_strvec_to_strvec(argv + i); argv_expanded = expand_strvec_to_strvec(argv + i);
debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]); debug_printf_exec(": run_nofork_applet '%s' '%s'...\n", argv_expanded[0], argv_expanded[1]);
rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded) & 0xff; rcode = run_nofork_applet_prime(&nofork_save, a, argv_expanded);
free(argv_expanded); free(argv_expanded);
restore_redirects(squirrel); restore_redirects(squirrel);
debug_printf_exec("run_pipe return %d\n", rcode); debug_printf_exec("run_pipe return %d\n", rcode);