1 Subject: Use a hashtable for the global symbols
5 source/interpret.c | 137 +++++++++++++++++++++++++++++++++++++----------------
7 source/interpret.c | 137 +++++++++++++++++++++++++++++++++++++----------------
9 2 files changed, 99 insertions(+), 39 deletions(-)
11 diff --quilt old/source/interpret.c new/source/interpret.c
12 --- old/source/interpret.c
13 +++ new/source/interpret.c
14 @@ -93,11 +93,14 @@ static int namedArg1orN(Boolean isFirst)
16 static int callSubroutineFromSymbol(Symbol *sym, int nArgs);
17 static int concatenateNwithSep(int nVals, const char *sep, char **result,
19 static int makeArrayKeyFromArgs(int nArgs, char **keyString, int leaveParams);
20 -static void freeSymbolTable(Symbol *symTab);
21 +static void freeSymbolList(Symbol *symList);
22 +static void addToGlobalSymTab(Symbol *sym);
23 +static unsigned int hashNameWith(unsigned int hash, const char *name);
24 +static unsigned int hashName(const char *name);
25 static int errCheck(const char *s);
26 static int execError(const char *s1, const char *s2);
27 static rbTreeNode *arrayEmptyAllocator(void);
28 static rbTreeNode *arrayAllocateNode(rbTreeNode *src);
29 static int arrayEntryCopyToNode(rbTreeNode *dst, rbTreeNode *src);
30 @@ -136,12 +139,15 @@ static void stackdumpInternal(int n, int
31 #else /* #ifndef DEBUG_STACK */
32 #define STACKDUMP(n, x)
33 #define DISASM_RT(i, n)
34 #endif /* #ifndef DEBUG_STACK */
36 -/* Global symbols and function definitions */
37 -static Symbol *GlobalSymList = NULL;
38 +/* Global symbols and function definitions, is null initialized */
39 +#define GLOBAL_SYMTAB_SHIFT 8
40 +#define GLOBAL_SYMTAB_SIZE (1u << (GLOBAL_SYMTAB_SHIFT))
41 +#define GLOBAL_SYMTAB_MASK ((GLOBAL_SYMTAB_SIZE) - 1)
42 +static Symbol *GlobalSymTab[GLOBAL_SYMTAB_SIZE];
44 /* List of all memory allocated for strings */
45 static char *AllocatedStrings = NULL;
47 typedef struct SparseArrayEntryWrapperTag {
48 @@ -313,11 +319,11 @@ Program *FinishCreatingProgram(Accumulat
51 void FreeProgram(Program *prog)
53 if (--prog->refcount == 0) {
54 - freeSymbolTable(prog->localSymList);
55 + freeSymbolList(prog->localSymList);
56 XtFree((char *)prog->code);
61 @@ -710,18 +716,18 @@ void SetMacroFocusWindow(WindowInfo *win
64 ** install an array iteration symbol
65 ** it is tagged as an integer but holds an array node pointer
67 -#define ARRAY_ITER_SYM_PREFIX "aryiter "
68 +#define ARRAY_ITER_SYM_PREFIX "aryiter #"
69 Symbol *InstallIteratorSymbol(void)
71 char symbolName[sizeof(ARRAY_ITER_SYM_PREFIX) + TYPE_INT_STR_SIZE(int)];
73 - static int interatorNameIndex = 0;
74 + static int interatorNameIndex;
76 - sprintf(symbolName, ARRAY_ITER_SYM_PREFIX "#%d", interatorNameIndex);
77 + sprintf(symbolName, ARRAY_ITER_SYM_PREFIX "%d", interatorNameIndex);
80 value.val.arrayPtr = NULL;
81 return(InstallSymbol(symbolName, LOCAL_SYM, value));
83 @@ -730,54 +736,80 @@ Symbol *InstallIteratorSymbol(void)
84 ** Lookup a constant string by its value. This allows reuse of string
85 ** constants and fixing a leak in the interpreter.
87 Symbol *LookupStringConstSymbol(const char *value)
92 - for (s = GlobalSymList; s != NULL; s = s->next) {
93 - if (s->type == CONST_SYM &&
94 - s->value.tag == STRING_TAG &&
95 - !strcmp(s->value.val.str.rep, value)) {
97 + for (idx = 0; idx < GLOBAL_SYMTAB_SIZE; idx++) {
98 + for (s = GlobalSymTab[idx]; s != NULL; s = s->next) {
99 + if (s->type == CONST_SYM
100 + && s->value.tag == STRING_TAG
101 + && !strcmp(s->value.val.str.rep, value)) {
111 ** install string str in the global symbol table with a string name
113 +#define STRING_CONST_SYM_PREFIX "string #"
114 Symbol *InstallStringConstSymbol(const char *str)
116 - static int stringConstIndex = 0;
117 - char stringName[35];
118 + static int stringConstIndex;
119 + char stringName[sizeof(STRING_CONST_SYM_PREFIX) + TYPE_INT_STR_SIZE(int)];
122 Symbol *sym = LookupStringConstSymbol(str);
127 - sprintf(stringName, "string #%d", stringConstIndex++);
128 + sprintf(stringName, STRING_CONST_SYM_PREFIX "%d", stringConstIndex++);
129 value.tag = STRING_TAG;
130 AllocNStringCpy(&value.val.str, str);
131 return(InstallSymbol(stringName, CONST_SYM, value));
134 +static Symbol *lookupSymbol(const Symbol *symlist, const char *name,
137 + while (NULL != symlist) {
138 + if (hash == symlist->hash && strcmp(symlist->name, name) == 0)
140 + symlist = symlist->next;
147 ** find a symbol in the symbol table
149 Symbol *LookupSymbol(const char *name)
154 - for (s = LocalSymList; s != NULL; s = s->next)
155 - if (strcmp(s->name, name) == 0)
157 - for (s = GlobalSymList; s != NULL; s = s->next)
158 - if (strcmp(s->name, name) == 0)
160 + /* calculate hash for name */
161 + hash = hashName(name);
163 + /* search in local symbols */
164 + s = lookupSymbol(LocalSymList, name, hash);
168 + /* search in global symbols */
169 + s = lookupSymbol(GlobalSymTab[hash & GLOBAL_SYMTAB_MASK], name, hash);
177 ** install symbol name in symbol table
178 @@ -790,16 +822,16 @@ Symbol *InstallSymbol(const char *name,
179 s = malloc(sizeof(Symbol) + strlen(name));
180 strcpy(s->name, name);
184 + s->hash = hashName(s->name);
185 if (type == LOCAL_SYM) {
186 s->next = LocalSymList;
189 - s->next = GlobalSymList;
191 + addToGlobalSymTab(s);
197 @@ -859,12 +891,11 @@ Symbol *PromoteToGlobal(Symbol *sym)
198 Don't use MACRO_FUNCTION_SYM as type, because in
199 macro.c:readCheckMacroString() we use ProgramFree() for the .val.prog,
200 but this symbol has no program attached and ProgramFree() is not NULL
202 sym->type = GLOBAL_SYM;
203 - sym->next = GlobalSymList;
204 - GlobalSymList = sym;
205 + addToGlobalSymTab(sym);
211 @@ -1083,10 +1114,11 @@ static void MarkArrayContentsAsUsed(Spar
212 void GarbageCollectStrings(void)
214 SparseArrayEntryWrapper *nextAP, *thisAP;
219 /* mark all strings as unreferenced */
220 for (p = AllocatedStrings; p != NULL; p = *((char **)p)) {
221 *(p + sizeof(char *)) = 0;
223 @@ -1096,19 +1128,21 @@ void GarbageCollectStrings(void)
227 /* Sweep the global symbol list, marking which strings are still
229 - for (s = GlobalSymList; s != NULL; s = s->next) {
230 - if (s->value.tag == STRING_TAG) {
231 - /* test first because it may be read-only static string */
232 - if (!(*(s->value.val.str.rep - 1))) {
233 - *(s->value.val.str.rep - 1) = 1;
234 + for (idx = 0; idx < GLOBAL_SYMTAB_SIZE; idx++) {
235 + for (s = GlobalSymTab[idx]; s != NULL; s = s->next) {
236 + if (s->value.tag == STRING_TAG) {
237 + /* test first because it may be read-only static string */
238 + if (!(*(s->value.val.str.rep - 1))) {
239 + *(s->value.val.str.rep - 1) = 1;
242 + else if (s->value.tag == ARRAY_TAG) {
243 + MarkArrayContentsAsUsed(s->value.val.arrayPtr);
246 - else if (s->value.tag == ARRAY_TAG) {
247 - MarkArrayContentsAsUsed(s->value.val.arrayPtr);
251 /* Collect all of the strings which remain unreferenced */
252 next = AllocatedStrings;
253 @@ -1171,21 +1205,46 @@ static void restoreContext(RestartData *
255 InitiatingWindow = context->runWindow;
256 FocusWindow = context->focusWindow;
259 -static void freeSymbolTable(Symbol *symTab)
260 +static void freeSymbolList(Symbol *symList)
264 - while(symTab != NULL) {
267 + while (symList != NULL) {
274 +static unsigned int hashNameWith(unsigned int hash, const char *name)
277 + unsigned int c = *name++;
278 + hash = (hash * 16777619u) + c;
284 +static unsigned int hashName(const char *name)
286 + return hashNameWith(2166136261u, name);
289 +static void addToGlobalSymTab(Symbol *sym)
293 + idx = sym->hash & GLOBAL_SYMTAB_MASK;
295 + sym->next = GlobalSymTab[idx];
296 + GlobalSymTab[idx] = sym;
299 /* true, if you can pop n values */
300 #define OK_TO_POP(n) \
301 ((StackP - (n)) >= TheStack)
303 #define POP_CHECK(n) \
304 @@ -4553,12 +4612,12 @@ static void disasmInternal(Inst *inst, i
305 if (inst[i].func == OpFns[j]) {
306 printd(" %*s", (int)opLen, opNames[j]);
307 if (j == OP_PUSH_SYM || j == OP_ASSIGN) {
308 Symbol *sym = inst[i+1].sym;
309 printd(" %s", sym->name);
310 - if (sym->value.tag == STRING_TAG &&
311 - strncmp(sym->name, "string #", 8) == 0) {
312 + if (sym->type == CONST_SYM
313 + && sym->value.tag == STRING_TAG) {
319 diff --quilt old/source/interpret.h new/source/interpret.h
320 --- old/source/interpret.h
321 +++ new/source/interpret.h
322 @@ -99,10 +99,11 @@ typedef struct SparseArrayEntryTag {
323 /* symbol table entry */
324 typedef struct SymbolRec {
329 struct SymbolRec *next; /* to link to another */
333 typedef struct ProgramTag {