1 Subject: Use a hashtable for the global symbols
5 source/interpret.c | 137 +++++++++++++++++++++++++++++++++++++----------------
7 source/interpret.c | 135 +++++++++++++++++++++++++++++++++++++----------------
8 source/interpret.h | 3 -
9 2 files changed, 98 insertions(+), 40 deletions(-)
11 diff --quilt old/source/interpret.c new/source/interpret.c
12 --- old/source/interpret.c
13 +++ new/source/interpret.c
14 @@ -95,7 +95,10 @@ static int callSubroutineFromSymbol(Symb
15 static int concatenateNwithSep(int nVals, const char *sep, char **result,
17 static int makeArrayKeyFromArgs(int nArgs, char **keyString, int leaveParams);
18 -static void freeSymbolTable(Symbol *symTab);
19 +static void freeSymbolList(Symbol *symList);
20 +static void addToGlobalSymTab(Symbol *sym);
21 +static unsigned int hashNameWith(unsigned int hash, const char *name);
22 +static unsigned int hashName(const char *name);
23 static int errCheck(const char *s);
24 static int execError(const char *s1, const char *s2);
25 static rbTreeNode *arrayEmptyAllocator(void);
26 @@ -138,8 +141,11 @@ static void stackdumpInternal(int n, int
27 #define DISASM_RT(i, n)
28 #endif /* #ifndef DEBUG_STACK */
30 -/* Global symbols and function definitions */
31 -static Symbol *GlobalSymList = NULL;
32 +/* Global symbols and function definitions, is null initialized */
33 +#define GLOBAL_SYMTAB_SHIFT 8
34 +#define GLOBAL_SYMTAB_SIZE (1u << (GLOBAL_SYMTAB_SHIFT))
35 +#define GLOBAL_SYMTAB_MASK ((GLOBAL_SYMTAB_SIZE) - 1)
36 +static Symbol *GlobalSymTab[GLOBAL_SYMTAB_SIZE];
38 /* List of all memory allocated for strings */
39 static char *AllocatedStrings = NULL;
40 @@ -316,7 +322,7 @@ Program *FinishCreatingProgram(Accumulat
41 void FreeProgram(Program *prog)
43 if (--prog->refcount == 0) {
44 - freeSymbolTable(prog->localSymList);
45 + freeSymbolList(prog->localSymList);
46 XtFree((char *)prog->code);
47 XtFree((char *)prog->name);
49 @@ -761,14 +767,14 @@ Symbol *InstallMultiAssignExpr(void)
50 ** install an array iteration symbol
51 ** it is tagged as an integer but holds an array node pointer
53 -#define ARRAY_ITER_SYM_PREFIX "aryiter "
54 +#define ARRAY_ITER_SYM_PREFIX "aryiter #"
55 Symbol *InstallIteratorSymbol(void)
57 char symbolName[sizeof(ARRAY_ITER_SYM_PREFIX) + TYPE_INT_STR_SIZE(int)];
59 - static int interatorNameIndex = 0;
60 + static int interatorNameIndex;
62 - sprintf(symbolName, ARRAY_ITER_SYM_PREFIX "#%d", interatorNameIndex);
63 + sprintf(symbolName, ARRAY_ITER_SYM_PREFIX "%d", interatorNameIndex);
66 value.val.arrayPtr = NULL;
67 @@ -781,15 +787,19 @@ Symbol *InstallIteratorSymbol(void)
69 Symbol *LookupStringConstSymbol(const char *value)
74 - for (s = GlobalSymList; s != NULL; s = s->next) {
75 - if (s->type == CONST_SYM &&
76 - s->value.tag == STRING_TAG &&
77 - !strcmp(s->value.val.str.rep, value)) {
79 + for (idx = 0; idx < GLOBAL_SYMTAB_SIZE; idx++) {
80 + for (s = GlobalSymTab[idx]; s != NULL; s = s->next) {
81 + if (s->type == CONST_SYM
82 + && s->value.tag == STRING_TAG
83 + && !strcmp(s->value.val.str.rep, value)) {
92 @@ -812,19 +822,39 @@ Symbol *InstallStringConstSymbol(const c
93 return(InstallSymbol(stringName, CONST_SYM, value));
96 +static Symbol *lookupSymbol(Symbol *symlist, const char *name,
99 + while (NULL != symlist) {
100 + if (hash == symlist->hash && strcmp(symlist->name, name) == 0)
102 + symlist = symlist->next;
109 ** find a symbol in the symbol table
111 Symbol *LookupSymbol(const char *name)
116 - for (s = LocalSymList; s != NULL; s = s->next)
117 - if (strcmp(s->name, name) == 0)
119 - for (s = GlobalSymList; s != NULL; s = s->next)
120 - if (strcmp(s->name, name) == 0)
122 + /* calculate hash for name */
123 + hash = hashName(name);
125 + /* search in local symbols */
126 + s = lookupSymbol(LocalSymList, name, hash);
130 + /* search in global symbols */
131 + s = lookupSymbol(GlobalSymTab[hash & GLOBAL_SYMTAB_MASK], name, hash);
138 @@ -835,17 +865,17 @@ Symbol *InstallSymbol(const char *name,
142 - s = (Symbol *)malloc(sizeof(Symbol));
143 - s->name = (char *)malloc(strlen(name)+1); /* +1 for '\0' */
145 + s->name = (char *)XtMalloc(strlen(name) + 1); /* +1 for '\0' */
146 strcpy(s->name, name);
149 + s->hash = hashName(s->name);
150 if (type == LOCAL_SYM) {
151 s->next = LocalSymList;
154 - s->next = GlobalSymList;
156 + addToGlobalSymTab(s);
160 @@ -909,8 +939,7 @@ Symbol *PromoteToGlobal(Symbol *sym)
161 but this symbol has no program attached and ProgramFree() is not NULL
163 sym->type = GLOBAL_SYM;
164 - sym->next = GlobalSymList;
165 - GlobalSymList = sym;
166 + addToGlobalSymTab(sym);
170 @@ -1133,6 +1162,7 @@ void GarbageCollectStrings(void)
171 SparseArrayEntryWrapper *nextAP, *thisAP;
176 /* mark all strings as unreferenced */
177 for (p = AllocatedStrings; p != NULL; p = *((char **)p)) {
178 @@ -1146,15 +1176,17 @@ void GarbageCollectStrings(void)
180 /* Sweep the global symbol list, marking which strings are still
182 - for (s = GlobalSymList; s != NULL; s = s->next) {
183 - if (s->value.tag == STRING_TAG) {
184 - /* test first because it may be read-only static string */
185 - if (!(*(s->value.val.str.rep - 1))) {
186 - *(s->value.val.str.rep - 1) = 1;
187 + for (idx = 0; idx < GLOBAL_SYMTAB_SIZE; idx++) {
188 + for (s = GlobalSymTab[idx]; s != NULL; s = s->next) {
189 + if (s->value.tag == STRING_TAG) {
190 + /* test first because it may be read-only static string */
191 + if (!(*(s->value.val.str.rep - 1))) {
192 + *(s->value.val.str.rep - 1) = 1;
195 + else if (s->value.tag == ARRAY_TAG) {
196 + MarkArrayContentsAsUsed(s->value.val.arrayPtr);
199 - else if (s->value.tag == ARRAY_TAG) {
200 - MarkArrayContentsAsUsed(s->value.val.arrayPtr);
204 @@ -1221,16 +1253,41 @@ static void restoreContext(RestartData *
205 FocusWindow = context->focusWindow;
208 -static void freeSymbolTable(Symbol *symTab)
209 +static void freeSymbolList(Symbol *symList)
213 - while(symTab != NULL) {
219 + while (symList != NULL) {
222 + XtFree((char *)s->name);
227 +static unsigned int hashNameWith(unsigned int hash, const char *name)
230 + unsigned int c = *name++;
231 + hash = (hash * 16777619u) + c;
237 +static unsigned int hashName(const char *name)
239 + return hashNameWith(2166136261u, name);
242 +static void addToGlobalSymTab(Symbol *sym)
246 + idx = sym->hash & GLOBAL_SYMTAB_MASK;
248 + sym->next = GlobalSymTab[idx];
249 + GlobalSymTab[idx] = sym;
252 /* true, if you can pop n values */
253 diff --quilt old/source/interpret.h new/source/interpret.h
254 --- old/source/interpret.h
255 +++ new/source/interpret.h
256 @@ -101,7 +101,8 @@ typedef struct SymbolRec {
260 - struct SymbolRec *next; /* to link to another */
262 + struct SymbolRec *next; /* to link to another */
265 typedef struct ProgramTag {