Compiler: Use hash table for global name lookups.
Imported from SM: https://bugs.alliedmods.net/show_bug.cgi?id=4496.
This commit is contained in:
@ -29,6 +29,7 @@
|
||||
#if defined LINUX || defined __FreeBSD__ || defined __OpenBSD__ || defined __APPLE__
|
||||
#include <sclinux.h>
|
||||
#endif
|
||||
#include "sp_symhash.h"
|
||||
|
||||
#if defined FORTIFY
|
||||
#include "fortify.h"
|
||||
@ -2370,6 +2371,7 @@ SC_FUNC int ishex(char c)
|
||||
static symbol *add_symbol(symbol *root,symbol *entry,int sort)
|
||||
{
|
||||
symbol *newsym;
|
||||
int global = root==&glbtab;
|
||||
|
||||
if (sort)
|
||||
while (root->next!=NULL && strcmp(entry->name,root->next->name)>0)
|
||||
@ -2382,6 +2384,8 @@ static symbol *add_symbol(symbol *root,symbol *entry,int sort)
|
||||
memcpy(newsym,entry,sizeof(symbol));
|
||||
newsym->next=root->next;
|
||||
root->next=newsym;
|
||||
if (global)
|
||||
AddToHashTable(sp_Globals, newsym);
|
||||
return newsym;
|
||||
}
|
||||
|
||||
@ -2426,6 +2430,7 @@ static void free_symbol(symbol *sym)
|
||||
|
||||
SC_FUNC void delete_symbol(symbol *root,symbol *sym)
|
||||
{
|
||||
symbol *origRoot = root;
|
||||
/* find the symbol and its predecessor
|
||||
* (this function assumes that you will never delete a symbol that is not
|
||||
* in the table pointed at by "root")
|
||||
@ -2436,6 +2441,9 @@ SC_FUNC void delete_symbol(symbol *root,symbol *sym)
|
||||
assert(root!=NULL);
|
||||
} /* while */
|
||||
|
||||
if (origRoot==&glbtab)
|
||||
RemoveFromHashTable(sp_Globals, sym);
|
||||
|
||||
/* unlink it, then free it */
|
||||
root->next=sym->next;
|
||||
free_symbol(sym);
|
||||
@ -2453,6 +2461,7 @@ SC_FUNC int get_actual_compound(symbol *sym)
|
||||
|
||||
SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_functions)
|
||||
{
|
||||
symbol *origRoot=root;
|
||||
symbol *sym,*parent_sym;
|
||||
constvalue *stateptr;
|
||||
int mustdelete=0;
|
||||
@ -2506,6 +2515,8 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_
|
||||
break;
|
||||
} /* switch */
|
||||
if (mustdelete) {
|
||||
if (origRoot == &glbtab)
|
||||
RemoveFromHashTable(sp_Globals, sym);
|
||||
root->next=sym->next;
|
||||
free_symbol(sym);
|
||||
} else {
|
||||
@ -2530,24 +2541,10 @@ SC_FUNC void delete_symbols(symbol *root,int level,int delete_labels,int delete_
|
||||
} /* if */
|
||||
}
|
||||
|
||||
/* The purpose of the hash is to reduce the frequency of a "name"
|
||||
* comparison (which is costly). There is little interest in avoiding
|
||||
* clusters in similar names, which is why this function is plain simple.
|
||||
*/
|
||||
SC_FUNC uint32_t namehash(const char *name)
|
||||
{
|
||||
const unsigned char *ptr=(const unsigned char *)name;
|
||||
int len=strlen(name);
|
||||
if (len==0)
|
||||
return 0L;
|
||||
assert(len<256);
|
||||
return (len<<24Lu) + (ptr[0]<<16Lu) + (ptr[len-1]<<8Lu) + (ptr[len>>1Lu]);
|
||||
}
|
||||
|
||||
static symbol *find_symbol(const symbol *root,const char *name,int fnumber,int includechildren)
|
||||
{
|
||||
symbol *ptr=root->next;
|
||||
unsigned long hash=namehash(name);
|
||||
unsigned long hash=NameHash(name);
|
||||
while (ptr!=NULL) {
|
||||
if (hash==ptr->hash && strcmp(name,ptr->name)==0
|
||||
&& (ptr->parent==NULL || includechildren)
|
||||
@ -2661,7 +2658,7 @@ SC_FUNC symbol *findconst(const char *name)
|
||||
|
||||
sym=find_symbol(&loctab,name,-1,TRUE); /* try local symbols first */
|
||||
if (sym==NULL || sym->ident!=iCONSTEXPR) /* not found, or not a constant */
|
||||
sym=find_symbol(&glbtab,name,fcurrent,TRUE);
|
||||
sym=FindInHashTable(sp_Globals,name,fcurrent);
|
||||
if (sym==NULL || sym->ident!=iCONSTEXPR)
|
||||
return NULL;
|
||||
assert(sym->parent==NULL || (sym->usage & uENUMFIELD)!=0);
|
||||
@ -2702,7 +2699,7 @@ SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,i
|
||||
|
||||
/* first fill in the entry */
|
||||
strcpy(entry.name,name);
|
||||
entry.hash=namehash(name);
|
||||
entry.hash=NameHash(name);
|
||||
entry.addr=addr;
|
||||
entry.codeaddr=code_idx;
|
||||
entry.vclass=(char)vclass;
|
||||
@ -2723,8 +2720,7 @@ SC_FUNC symbol *addsym(const char *name,cell addr,int ident,int vclass,int tag,i
|
||||
/* then insert it in the list */
|
||||
if (vclass==sGLOBAL)
|
||||
return add_symbol(&glbtab,&entry,TRUE);
|
||||
else
|
||||
return add_symbol(&loctab,&entry,FALSE);
|
||||
return add_symbol(&loctab, &entry, FALSE);
|
||||
}
|
||||
|
||||
SC_FUNC symbol *addvariable(const char *name,cell addr,int ident,int vclass,int tag,
|
||||
|
Reference in New Issue
Block a user