much better solution: save tablep and hash value¹ in the struct tbl entry

① also saves time during texpand :D

XXX this doesn’t work well with the current indexed-array implementation
This commit is contained in:
tg 2009-08-28 20:30:59 +00:00
parent 7240c843ce
commit 4ccdfc8508
10 changed files with 108 additions and 110 deletions

5
edit.c
View File

@ -25,7 +25,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.174 2009/08/28 19:57:39 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/edit.c,v 1.175 2009/08/28 20:30:54 tg Exp $");
/* tty driver characters we are interested in */
typedef struct {
@ -4161,8 +4161,7 @@ vi_cmd(int argcnt, const char *cmd)
/* lookup letter in alias list... */
alias[1] = cmd[1];
ap = ktsearch(&aliases, alias, hash(alias),
NULL);
ap = ktsearch(&aliases, alias, hash(alias));
if (!cmd[1] || !ap || !(ap->flag & ISSET))
return (-1);
/* check if this is a recursive call... */

4
eval.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.65 2009/08/28 19:57:40 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/eval.c,v 1.66 2009/08/28 20:30:55 tg Exp $");
/*
* string expansion
@ -1425,7 +1425,7 @@ homedir(char *name)
{
struct tbl *ap;
ap = ktenter(&homedirs, name, hash(name), NULL);
ap = ktenter(&homedirs, name, hash(name));
if (!(ap->flag & ISSET)) {
struct passwd *pw;

27
exec.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.63 2009/08/28 19:57:40 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/exec.c,v 1.64 2009/08/28 20:30:55 tg Exp $");
static int comexec(struct op *, struct tbl *volatile, const char **,
int volatile, volatile int *);
@ -567,7 +567,7 @@ comexec(struct op *t, struct tbl *volatile tp, const char **ap,
rv = 127;
break;
}
if (!(ftp = findfunc(cp, hash(cp), false, NULL)) ||
if (!(ftp = findfunc(cp, hash(cp), false)) ||
!(ftp->flag & ISSET)) {
warningf(true,
"%s: function not defined by %s",
@ -789,7 +789,7 @@ shcomexec(const char **wp)
{
struct tbl *tp;
tp = ktsearch(&builtins, *wp, hash(*wp), NULL);
tp = ktsearch(&builtins, *wp, hash(*wp));
if (tp == NULL)
internal_errorf("shcomexec: %s", *wp);
return (call_builtin(tp, wp));
@ -800,17 +800,17 @@ shcomexec(const char **wp)
* is created if none is found.
*/
struct tbl *
findfunc(const char *name, uint32_t h, bool create, struct table_entry *pte)
findfunc(const char *name, uint32_t h, bool create)
{
struct block *l;
struct tbl *tp = NULL;
for (l = e->loc; l; l = l->next) {
tp = ktsearch(&l->funs, name, h, pte);
tp = ktsearch(&l->funs, name, h);
if (tp)
break;
if (!l->next && create) {
tp = ktenter(&l->funs, name, h, pte);
tp = ktenter(&l->funs, name, h);
tp->flag = DEFINED;
tp->type = CFUNC;
tp->val.t = NULL;
@ -828,11 +828,10 @@ int
define(const char *name, struct op *t)
{
struct tbl *tp;
struct table_entry te;
bool was_set = false;
while (1) {
tp = findfunc(name, hash(name), true, &te);
tp = findfunc(name, hash(name), true);
if (tp->flag & ISSET)
was_set = true;
@ -853,7 +852,7 @@ define(const char *name, struct op *t)
}
if (t == NULL) { /* undefine */
ktremove(&te);
ktdelete(tp);
return (was_set ? 0 : 1);
}
@ -886,7 +885,7 @@ builtin(const char *name, int (*func) (const char **))
break;
}
tp = ktenter(&builtins, name, hash(name), NULL);
tp = ktenter(&builtins, name, hash(name));
tp->flag = DEFINED | flag;
tp->type = CSHELL;
tp->val.f = func;
@ -912,14 +911,14 @@ findcom(const char *name, int flags)
flags &= ~FC_FUNC;
goto Search;
}
tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h, NULL) : NULL;
tbi = (flags & FC_BI) ? ktsearch(&builtins, name, h) : NULL;
/* POSIX says special builtins first, then functions, then
* POSIX regular builtins, then search path...
*/
if ((flags & FC_SPECBI) && tbi && (tbi->flag & SPEC_BI))
tp = tbi;
if (!tp && (flags & FC_FUNC)) {
tp = findfunc(name, h, false, NULL);
tp = findfunc(name, h, false);
if (tp && !(tp->flag & ISSET)) {
if ((fpath = str_val(global("FPATH"))) == null) {
tp->u.fpath = NULL;
@ -934,7 +933,7 @@ findcom(const char *name, int flags)
if (!tp && (flags & FC_UNREGBI) && tbi)
tp = tbi;
if (!tp && (flags & FC_PATH) && !(flags & FC_DEFPATH)) {
tp = ktsearch(&taliases, name, h, NULL);
tp = ktsearch(&taliases, name, h);
if (tp && (tp->flag & ISSET) && access(tp->val.s, X_OK) != 0) {
if (tp->flag & ALLOC) {
tp->flag &= ~ALLOC;
@ -949,7 +948,7 @@ findcom(const char *name, int flags)
(flags & FC_PATH)) {
if (!tp) {
if (insert && !(flags & FC_DEFPATH)) {
tp = ktenter(&taliases, name, h, NULL);
tp = ktenter(&taliases, name, h);
tp->type = CTALIAS;
} else {
tp = &temp;

4
expr.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.30 2009/08/08 13:08:50 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/expr.c,v 1.31 2009/08/28 20:30:55 tg Exp $");
/* The order of these enums is constrained by the order of opinfo[] */
enum token {
@ -608,6 +608,8 @@ tempvar(void)
vp->flag = ISSET|INTEGER;
vp->type = 0;
vp->areap = ATEMP;
vp->tablep = NULL;
vp->hval = 0;
vp->val.i = 0;
vp->name[0] = '\0';
return (vp);

16
funcs.c
View File

@ -25,7 +25,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.122 2009/08/28 19:57:40 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/funcs.c,v 1.123 2009/08/28 20:30:56 tg Exp $");
#if HAVE_KILLPG
/*
@ -637,11 +637,13 @@ c_whence(const char **wp)
fcflags &= ~(FC_BI | FC_FUNC);
while ((vflag || rv == 0) && (id = *wp++) != NULL) {
uint32_t h = 0;
tp = NULL;
if ((iam_whence || vflag) && !pflag)
tp = ktsearch(&keywords, id, hash(id), NULL);
tp = ktsearch(&keywords, id, h = hash(id));
if (!tp && !pflag) {
tp = ktsearch(&aliases, id, hash(id), NULL);
tp = ktsearch(&aliases, id, h ? h : hash(id));
if (tp && !(tp->flag & ISSET))
tp = NULL;
}
@ -879,7 +881,7 @@ c_typeset(const char **wp)
for (i = builtin_opt.optind; wp[i]; i++) {
if (func) {
f = findfunc(wp[i], hash(wp[i]),
(fset&UCASEV_AL) ? true : false, NULL);
(fset&UCASEV_AL) ? true : false);
if (!f) {
/* AT&T ksh does ++rv: bogus */
rv = 1;
@ -1138,7 +1140,7 @@ c_alias(const char **wp)
}
h = hash(alias);
if (val == NULL && !tflag && !xflag) {
ap = ktsearch(t, alias, h, NULL);
ap = ktsearch(t, alias, h);
if (ap != NULL && (ap->flag&ISSET)) {
if (pflag)
shf_puts("alias ", shl_stdout);
@ -1154,7 +1156,7 @@ c_alias(const char **wp)
}
continue;
}
ap = ktenter(t, alias, h, NULL);
ap = ktenter(t, alias, h);
ap->type = tflag ? CTALIAS : CALIAS;
/* Are we setting the value or just some flags? */
if ((val && !tflag) || (!val && tflag && !Uflag)) {
@ -1214,7 +1216,7 @@ c_unalias(const char **wp)
wp += builtin_opt.optind;
for (; *wp != NULL; wp++) {
ap = ktsearch(t, *wp, hash(*wp), NULL);
ap = ktsearch(t, *wp, hash(*wp));
if (ap == NULL) {
rv = 1; /* POSIX */
continue;

10
lex.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.91 2009/08/28 19:57:41 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/lex.c,v 1.92 2009/08/28 20:30:56 tg Exp $");
/*
* states while lexing word
@ -909,17 +909,15 @@ yylex(int cf)
if (*ident != '\0' && (cf&(KEYWORD|ALIAS))) {
struct tbl *p;
struct table_entry te;
uint32_t h = hash(ident);
/* { */
if ((cf & KEYWORD) &&
(p = ktsearch(&keywords, ident, h, NULL)) &&
if ((cf & KEYWORD) && (p = ktsearch(&keywords, ident, h)) &&
(!(cf & ESACONLY) || p->val.i == ESAC || p->val.i == '}')) {
afree(yylval.cp, ATEMP);
return (p->val.i);
}
if ((cf & ALIAS) && (p = ktsearch(&aliases, ident, h, &te)) &&
if ((cf & ALIAS) && (p = ktsearch(&aliases, ident, h)) &&
(p->flag & ISSET)) {
/*
* this still points to the same character as the
@ -946,7 +944,7 @@ yylex(int cf)
* delete alias upon encountering function
* definition
*/
ktremove(&te);
ktdelete(p);
else {
Source *s = source;

100
main.c
View File

@ -33,7 +33,7 @@
#include <locale.h>
#endif
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.139 2009/08/28 19:57:42 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/main.c,v 1.140 2009/08/28 20:30:57 tg Exp $");
extern char **environ;
@ -1236,6 +1236,8 @@ maketemp(Area *ap, Temp_type type, struct temp **tlist)
static void texpand(struct table *, size_t);
static int tnamecmp(const void *, const void *);
static struct tbl *ktscan(struct table *, const char *, uint32_t,
struct tbl ***);
/* Bob Jenkins' one-at-a-time hash */
uint32_t
@ -1276,7 +1278,7 @@ texpand(struct table *tp, size_t nsize)
for (i = 0; i < osize; i++)
if ((tblp = otblp[i]) != NULL) {
if ((tblp->flag & DEFINED)) {
for (p = &ntblp[hash(tblp->name) &
for (p = &ntblp[tblp->hval &
(tp->size - 1)]; *p != NULL; p--)
if (p == ntblp) /* wrap */
p += tp->size;
@ -1299,48 +1301,39 @@ ktinit(struct table *tp, Area *ap, size_t tsize)
texpand(tp, tsize);
}
void
ktremove(struct table_entry *pte)
/* table, name (key) to search for, hash(n) */
static struct tbl *
ktscan(struct table *tp, const char *n, uint32_t h, struct tbl ***ppp)
{
struct tbl *p;
struct tbl **pp, *p;
p = *(pte->ep);
*(pte->ep) = NULL;
++(pte->tp->nfree);
/* search for name in hashed table */
for (pp = &tp->tbls[h & (tp->size - 1)]; (p = *pp) != NULL; pp--) {
if (p->hval == h && !strcmp(p->name, n) && (p->flag & DEFINED))
goto found;
if (pp == tp->tbls)
/* wrap */
pp += tp->size;
}
/* not found */
p = NULL;
afree(p, p->areap);
found:
if (ppp)
*ppp = pp;
return (p);
}
/* table, name (key) to search for, hash(n) */
struct tbl *
ktsearch(struct table *tp, const char *n, uint32_t h, struct table_entry *pte)
ktsearch(struct table *tp, const char *n, uint32_t h)
{
struct tbl **pp, *p;
if (tp->size == 0)
return (NULL);
/* search for name in hashed table */
for (pp = &tp->tbls[h & (tp->size - 1)]; (p = *pp) != NULL; pp--) {
if (*p->name == *n && strcmp(p->name, n) == 0 &&
(p->flag & DEFINED)) {
/* found */
if (pte) {
pte->tp = tp;
pte->ep = pp;
}
return (p);
}
if (pp == tp->tbls) /* wrap */
pp += tp->size;
}
return (NULL);
return (tp->size ? ktscan(tp, n, h, NULL) : NULL);
}
/* table, name (key) to enter, hash(n) */
struct tbl *
ktenter(struct table *tp, const char *n, uint32_t h, struct table_entry *pte)
ktenter(struct table *tp, const char *n, uint32_t h)
{
struct tbl **pp, *p;
int len;
@ -1348,30 +1341,23 @@ ktenter(struct table *tp, const char *n, uint32_t h, struct table_entry *pte)
if (tp->size == 0)
texpand(tp, INIT_TBLS);
Search:
/* search for name in hashed table */
for (pp = &tp->tbls[h & (tp->size - 1)]; (p = *pp) != NULL; pp--) {
if (*p->name == *n && strcmp(p->name, n) == 0) {
/* found */
if (pte) {
pte->tp = tp;
pte->ep = pp;
}
return (p);
}
if (pp == tp->tbls) /* wrap */
pp += tp->size;
}
if ((p = ktscan(tp, n, h, &pp)))
return (p);
if (tp->nfree <= 0) { /* too full */
if (tp->nfree <= 0) {
/* too full */
texpand(tp, 2 * tp->size);
goto Search;
}
/* create new tbl entry */
len = strlen(n) + 1;
p = alloc(offsetof(struct tbl, name[0]) + len, tp->areap);
p->flag = 0;
p->type = 0;
p->areap = tp->areap;
p->tablep = tp;
p->hval = h;
p->u2.field = 0;
p->u.array = NULL;
memcpy(p->name, n, len);
@ -1379,13 +1365,27 @@ ktenter(struct table *tp, const char *n, uint32_t h, struct table_entry *pte)
/* enter in tp->tbls */
tp->nfree--;
*pp = p;
if (pte) {
pte->tp = tp;
pte->ep = pp;
}
return (p);
}
void
ktdelete(struct tbl *p)
{
struct tbl **pp;
if (p->tablep && p->tablep->size && ktscan(p->tablep, p->name,
p->hval, &pp) == p) {
/* ktremove p */
*pp = NULL;
p->tablep->nfree++;
/* get rid of p */
afree(p, p->areap);
} else {
/* mark p as free for garbage collection via texpand */
p->flag = 0;
}
}
void
ktwalk(struct tstate *ts, struct table *tp)
{

17
sh.h
View File

@ -134,7 +134,7 @@
#endif
#ifdef EXTERN
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.327 2009/08/28 19:57:42 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/sh.h,v 1.328 2009/08/28 20:30:58 tg Exp $");
#endif
#define MKSH_VERSION "R39 2009/08/08"
@ -851,11 +851,6 @@ struct table {
short size, nfree; /* hash size (always 2^^n), free entries */
};
struct table_entry {
struct table *tp; /* table this entry is in */
struct tbl **ep; /* entry pointer (&tp->tbls[i]) */
};
struct tbl { /* table item */
Area *areap; /* area to allocate from */
union {
@ -869,6 +864,7 @@ struct tbl { /* table item */
struct tbl *array; /* array values */
const char *fpath; /* temporary path to undef function */
} u;
struct table *tablep; /* table we're ktenter'd in */
union {
int field; /* field with for -L/-R/-Z */
int errno_; /* CEXEC/CTALIAS */
@ -876,6 +872,7 @@ struct tbl { /* table item */
int type; /* command type (see below), base (if INTEGER),
* or offset from val.s of value (if EXPORT) */
Tflag flag; /* flags */
uint32_t hval; /* hash(name) */
uint32_t index; /* index for an array */
char name[4]; /* name -- variable length */
};
@ -1376,7 +1373,7 @@ int glob_str(char *, XPtrV *, int);
/* exec.c */
int execute(struct op * volatile, volatile int, volatile int * volatile);
int shcomexec(const char **);
struct tbl *findfunc(const char *, uint32_t, bool, struct table_entry *);
struct tbl *findfunc(const char *, uint32_t, bool);
int define(const char *, struct op *);
void builtin(const char *, int (*)(const char **));
struct tbl *findcom(const char *, int);
@ -1545,9 +1542,9 @@ void coproc_cleanup(int);
struct temp *maketemp(Area *, Temp_type, struct temp **);
uint32_t hash(const char *);
void ktinit(struct table *, Area *, size_t);
struct tbl *ktsearch(struct table *, const char *, uint32_t, struct table_entry *);
struct tbl *ktenter(struct table *, const char *, uint32_t, struct table_entry *);
void ktremove(struct table_entry *);
struct tbl *ktsearch(struct table *, const char *, uint32_t);
struct tbl *ktenter(struct table *, const char *, uint32_t);
void ktdelete(struct tbl *);
void ktwalk(struct tstate *, struct table *);
struct tbl *ktnext(struct tstate *);
struct tbl **ktsort(struct table *);

4
syn.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.40 2009/08/28 19:57:43 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/syn.c,v 1.41 2009/08/28 20:30:59 tg Exp $");
struct nesting_state {
int start_token; /* token than began nesting (eg, FOR) */
@ -743,7 +743,7 @@ initkeywords(void)
/* must be 80% of 2^n (currently 20 keywords) */ 32);
for (tt = tokentab; tt->name; tt++) {
if (tt->reserved) {
p = ktenter(&keywords, tt->name, hash(tt->name), NULL);
p = ktenter(&keywords, tt->name, hash(tt->name));
p->flag |= DEFINED|ISSET;
p->type = CKEYWD;
p->val.i = tt->val;

31
var.c
View File

@ -22,7 +22,7 @@
#include "sh.h"
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.79 2009/08/28 19:57:43 tg Exp $");
__RCSID("$MirOS: src/bin/mksh/var.c,v 1.80 2009/08/28 20:30:59 tg Exp $");
/*
* Variables
@ -128,8 +128,7 @@ initvar(void)
ktinit(&specials, APERM,
/* must be 80% of 2^n (currently 12 specials) */ 16);
for (i = 0; names[i].name; i++) {
tp = ktenter(&specials, names[i].name, hash(names[i].name),
NULL);
tp = ktenter(&specials, names[i].name, hash(names[i].name));
tp->flag = DEFINED|ISSET;
tp->type = names[i].v;
}
@ -226,7 +225,7 @@ global(const char *n)
return (vp);
}
for (l = e->loc; ; l = l->next) {
vp = ktsearch(&l->vars, n, h, NULL);
vp = ktsearch(&l->vars, n, h);
if (vp != NULL) {
if (array)
return (arraysearch(vp, val));
@ -236,7 +235,7 @@ global(const char *n)
if (l->next == NULL)
break;
}
vp = ktenter(&l->vars, n, h, NULL);
vp = ktenter(&l->vars, n, h);
if (array)
vp = arraysearch(vp, val);
vp->flag |= DEFINED;
@ -266,13 +265,12 @@ local(const char *n, bool copy)
vp->areap = ATEMP;
return (vp);
}
vp = ktenter(&l->vars, n, h, NULL);
vp = ktenter(&l->vars, n, h);
if (copy && !(vp->flag & DEFINED)) {
struct block *ll = l;
struct tbl *vq = NULL;
while ((ll = ll->next) && !(vq = ktsearch(&ll->vars, n, h,
NULL)))
while ((ll = ll->next) && !(vq = ktsearch(&ll->vars, n, h)))
;
if (vq) {
vp->flag |= vq->flag &
@ -894,8 +892,7 @@ makenv(void)
/* unexport any redefined instances */
for (l2 = l->next; l2 != NULL; l2 = l2->next) {
vp2 = ktsearch(&l2->vars, vp->name, h,
NULL);
vp2 = ktsearch(&l2->vars, vp->name, h);
if (vp2 != NULL)
vp2->flag &= ~EXPORT;
}
@ -1029,7 +1026,7 @@ special(const char *name)
{
struct tbl *tp;
tp = ktsearch(&specials, name, hash(name), NULL);
tp = ktsearch(&specials, name, hash(name));
return (tp && (tp->flag & ISSET) ? tp->type : V_NONE);
}
@ -1037,11 +1034,11 @@ special(const char *name)
static void
unspecial(const char *name)
{
struct table_entry te = { NULL, NULL };
struct tbl *tp;
ktsearch(&specials, name, hash(name), &te);
if (te.ep)
ktremove(&te);
tp = ktsearch(&specials, name, hash(name));
if (tp)
ktdelete(tp);
}
static time_t seconds; /* time SECONDS last set */
@ -1269,6 +1266,10 @@ arraysearch(struct tbl *vp, uint32_t val)
new->areap = vp->areap;
new->u2.field = vp->u2.field;
new->index = val;
/* XXX array indices must not be ktdelete'd, for now */
new->tablep = NULL;
new->hval = vp->hval;
if (curr != new) { /* not reusing old array entry */
prev->u.array = new;
new->u.array = curr;