optimisations: hash table for include file search, pool for symbol allocation - sympler token string allocation - '-b' fix with '-run' option

This commit is contained in:
bellard 2004-11-07 15:45:19 +00:00
parent 398e22c541
commit 48c85f1b15

185
tcc.c
View File

@ -289,10 +289,13 @@ typedef struct TokenString {
inclusion if the include file is protected by #ifndef ... #endif */ inclusion if the include file is protected by #ifndef ... #endif */
typedef struct CachedInclude { typedef struct CachedInclude {
int ifndef_macro; int ifndef_macro;
int hash_next; /* -1 if none */
char type; /* '"' or '>' to give include type */ char type; /* '"' or '>' to give include type */
char filename[1]; /* path specified in #include */ char filename[1]; /* path specified in #include */
} CachedInclude; } CachedInclude;
#define CACHED_INCLUDES_HASH_SIZE 512
/* parser */ /* parser */
static struct BufferedFile *file; static struct BufferedFile *file;
static int ch, tok; static int ch, tok;
@ -319,7 +322,9 @@ static int parse_flags;
static Section *text_section, *data_section, *bss_section; /* predefined sections */ static Section *text_section, *data_section, *bss_section; /* predefined sections */
static Section *cur_text_section; /* current section where function code is static Section *cur_text_section; /* current section where function code is
generated */ generated */
#ifdef CONFIG_TCC_ASM
static Section *last_text_section; /* to handle .previous asm directive */ static Section *last_text_section; /* to handle .previous asm directive */
#endif
/* bound check related sections */ /* bound check related sections */
static Section *bounds_section; /* contains global data bound description */ static Section *bounds_section; /* contains global data bound description */
static Section *lbounds_section; /* contains local data bound description */ static Section *lbounds_section; /* contains local data bound description */
@ -352,6 +357,9 @@ static char *funcname;
static Sym *global_stack, *local_stack; static Sym *global_stack, *local_stack;
static Sym *define_stack; static Sym *define_stack;
static Sym *global_label_stack, *local_label_stack; static Sym *global_label_stack, *local_label_stack;
/* symbol allocator */
#define SYM_POOL_NB (8192 / sizeof(Sym))
static Sym *sym_free_first;
static SValue vstack[VSTACK_SIZE], *vtop; static SValue vstack[VSTACK_SIZE], *vtop;
/* some predefined types */ /* some predefined types */
@ -473,6 +481,9 @@ struct TCCState {
/* see ifdef_stack_ptr */ /* see ifdef_stack_ptr */
int ifdef_stack[IFDEF_STACK_SIZE]; int ifdef_stack[IFDEF_STACK_SIZE];
/* see cached_includes */
int cached_includes_hash[CACHED_INCLUDES_HASH_SIZE];
}; };
/* The current value can be: */ /* The current value can be: */
@ -1048,6 +1059,41 @@ static void dynarray_add(void ***ptab, int *nb_ptr, void *data)
*nb_ptr = nb; *nb_ptr = nb;
} }
/* symbol allocator */
static Sym *__sym_malloc(void)
{
Sym *sym_pool, *sym, *last_sym;
int i;
sym_pool = tcc_malloc(SYM_POOL_NB * sizeof(Sym));
last_sym = sym_free_first;
sym = sym_pool;
for(i = 0; i < SYM_POOL_NB; i++) {
sym->next = last_sym;
last_sym = sym;
sym++;
}
sym_free_first = last_sym;
return last_sym;
}
static inline Sym *sym_malloc(void)
{
Sym *sym;
sym = sym_free_first;
if (!sym)
sym = __sym_malloc();
sym_free_first = sym->next;
return sym;
}
static inline void sym_free(Sym *sym)
{
sym->next = sym_free_first;
sym_free_first = sym;
}
Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags) Section *new_section(TCCState *s1, const char *name, int sh_type, int sh_flags)
{ {
Section *sec; Section *sec;
@ -1433,7 +1479,7 @@ static void cstr_realloc(CString *cstr, int new_size)
} }
/* add a byte */ /* add a byte */
static void cstr_ccat(CString *cstr, int ch) static inline void cstr_ccat(CString *cstr, int ch)
{ {
int size; int size;
size = cstr->size + 1; size = cstr->size + 1;
@ -1480,21 +1526,6 @@ static void cstr_free(CString *cstr)
#define cstr_reset(cstr) cstr_free(cstr) #define cstr_reset(cstr) cstr_free(cstr)
static CString *cstr_dup(CString *cstr1)
{
CString *cstr;
int size;
cstr = tcc_malloc(sizeof(CString));
size = cstr1->size;
cstr->size = size;
cstr->size_allocated = size;
cstr->data_allocated = tcc_malloc(size);
cstr->data = cstr->data_allocated;
memcpy(cstr->data_allocated, cstr1->data_allocated, size);
return cstr;
}
/* XXX: unicode ? */ /* XXX: unicode ? */
static void add_char(CString *cstr, int c) static void add_char(CString *cstr, int c)
{ {
@ -1618,7 +1649,7 @@ char *get_tok_str(int v, CValue *cv)
static Sym *sym_push2(Sym **ps, int v, int t, int c) static Sym *sym_push2(Sym **ps, int v, int t, int c)
{ {
Sym *s; Sym *s;
s = tcc_malloc(sizeof(Sym)); s = sym_malloc();
s->v = v; s->v = v;
s->type.t = t; s->type.t = t;
s->c = c; s->c = c;
@ -1726,7 +1757,7 @@ static void sym_pop(Sym **ptop, Sym *b)
ps = &ts->sym_identifier; ps = &ts->sym_identifier;
*ps = s->prev_tok; *ps = s->prev_tok;
} }
tcc_free(s); sym_free(s);
s = ss; s = ss;
} }
*ptop = b; *ptop = b;
@ -2194,11 +2225,13 @@ static inline int tok_ext_size(int t)
case TOK_CUINT: case TOK_CUINT:
case TOK_CCHAR: case TOK_CCHAR:
case TOK_LCHAR: case TOK_LCHAR:
case TOK_STR:
case TOK_LSTR:
case TOK_CFLOAT: case TOK_CFLOAT:
case TOK_LINENUM: case TOK_LINENUM:
return 1;
case TOK_STR:
case TOK_LSTR:
case TOK_PPNUM: case TOK_PPNUM:
error("unsupported token");
return 1; return 1;
case TOK_CDOUBLE: case TOK_CDOUBLE:
case TOK_CLLONG: case TOK_CLLONG:
@ -2223,48 +2256,6 @@ static inline void tok_str_new(TokenString *s)
static void tok_str_free(int *str) static void tok_str_free(int *str)
{ {
const int *p;
CString *cstr;
int t;
p = str;
for(;;) {
t = *p;
/* NOTE: we test zero separately so that GCC can generate a
table for the following switch */
if (t == 0)
break;
switch(t) {
case TOK_CINT:
case TOK_CUINT:
case TOK_CCHAR:
case TOK_LCHAR:
case TOK_CFLOAT:
case TOK_LINENUM:
p += 2;
break;
case TOK_PPNUM:
case TOK_STR:
case TOK_LSTR:
/* XXX: use a macro to be portable on 64 bit ? */
cstr = (CString *)p[1];
cstr_free(cstr);
tcc_free(cstr);
p += 2;
break;
case TOK_CDOUBLE:
case TOK_CLLONG:
case TOK_CULLONG:
p += 3;
break;
case TOK_CLDOUBLE:
p += 1 + (LDOUBLE_SIZE / 4);
break;
default:
p++;
break;
}
}
tcc_free(str); tcc_free(str);
} }
@ -2320,7 +2311,22 @@ static void tok_str_add2(TokenString *s, int t, CValue *cv)
case TOK_PPNUM: case TOK_PPNUM:
case TOK_STR: case TOK_STR:
case TOK_LSTR: case TOK_LSTR:
str[len++] = (int)cstr_dup(cv->cstr); {
int nb_words;
CString *cstr;
nb_words = (sizeof(CString) + cv->cstr->size + 3) >> 2;
while ((len + nb_words) > s->allocated_len)
str = tok_str_realloc(s);
cstr = (CString *)(str + len);
cstr->data = NULL;
cstr->size = cv->cstr->size;
cstr->data_allocated = NULL;
cstr->size_allocated = cstr->size;
memcpy((char *)cstr + sizeof(CString),
cv->cstr->data, cstr->size);
len += nb_words;
}
break; break;
case TOK_CDOUBLE: case TOK_CDOUBLE:
case TOK_CLLONG: case TOK_CLLONG:
@ -2386,10 +2392,14 @@ static void tok_str_add_tok(TokenString *s)
case TOK_LCHAR: \ case TOK_LCHAR: \
case TOK_CFLOAT: \ case TOK_CFLOAT: \
case TOK_LINENUM: \ case TOK_LINENUM: \
cv.tab[0] = *p++; \
break; \
case TOK_STR: \ case TOK_STR: \
case TOK_LSTR: \ case TOK_LSTR: \
case TOK_PPNUM: \ case TOK_PPNUM: \
cv.tab[0] = *p++; \ cv.cstr = (CString *)p; \
cv.cstr->data = (char *)p + sizeof(CString);\
p += (sizeof(CString) + cv.cstr->size + 3) >> 2;\
break; \ break; \
case TOK_CDOUBLE: \ case TOK_CDOUBLE: \
case TOK_CLLONG: \ case TOK_CLLONG: \
@ -2450,7 +2460,7 @@ static void free_defines(Sym *b)
v = top->v; v = top->v;
if (v >= TOK_IDENT && v < tok_ident) if (v >= TOK_IDENT && v < tok_ident)
table_ident[v - TOK_IDENT]->sym_define = NULL; table_ident[v - TOK_IDENT]->sym_define = NULL;
tcc_free(top); sym_free(top);
top = top1; top = top1;
} }
define_stack = b; define_stack = b;
@ -2503,7 +2513,7 @@ static void label_pop(Sym **ptop, Sym *slast)
} }
/* remove label */ /* remove label */
table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok; table_ident[s->v - TOK_IDENT]->sym_label = s->prev_tok;
tcc_free(s); sym_free(s);
} }
*ptop = slast; *ptop = slast;
} }
@ -2619,17 +2629,37 @@ static void parse_define(void)
define_push(v, t, str.str, first); define_push(v, t, str.str, first);
} }
static inline int hash_cached_include(int type, const char *filename)
{
const unsigned char *s;
unsigned int h;
h = TOK_HASH_INIT;
h = TOK_HASH_FUNC(h, type);
s = filename;
while (*s) {
h = TOK_HASH_FUNC(h, *s);
s++;
}
h &= (CACHED_INCLUDES_HASH_SIZE - 1);
return h;
}
/* XXX: use a token or a hash table to accelerate matching ? */ /* XXX: use a token or a hash table to accelerate matching ? */
static CachedInclude *search_cached_include(TCCState *s1, static CachedInclude *search_cached_include(TCCState *s1,
int type, const char *filename) int type, const char *filename)
{ {
CachedInclude *e; CachedInclude *e;
int i; int i, h;
h = hash_cached_include(type, filename);
for(i = 0;i < s1->nb_cached_includes; i++) { i = s1->cached_includes_hash[h];
e = s1->cached_includes[i]; for(;;) {
if (i == 0)
break;
e = s1->cached_includes[i - 1];
if (e->type == type && !strcmp(e->filename, filename)) if (e->type == type && !strcmp(e->filename, filename))
return e; return e;
i = e->hash_next;
} }
return NULL; return NULL;
} }
@ -2638,6 +2668,7 @@ static inline void add_cached_include(TCCState *s1, int type,
const char *filename, int ifndef_macro) const char *filename, int ifndef_macro)
{ {
CachedInclude *e; CachedInclude *e;
int h;
if (search_cached_include(s1, type, filename)) if (search_cached_include(s1, type, filename))
return; return;
@ -2651,6 +2682,10 @@ static inline void add_cached_include(TCCState *s1, int type,
strcpy(e->filename, filename); strcpy(e->filename, filename);
e->ifndef_macro = ifndef_macro; e->ifndef_macro = ifndef_macro;
dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e); dynarray_add((void ***)&s1->cached_includes, &s1->nb_cached_includes, e);
/* add in hash table */
h = hash_cached_include(type, filename);
e->hash_next = s1->cached_includes_hash[h];
s1->cached_includes_hash[h] = s1->nb_cached_includes;
} }
/* is_bof is true if first non space token at beginning of file */ /* is_bof is true if first non space token at beginning of file */
@ -3989,7 +4024,7 @@ static int macro_subst_tok(TokenString *tok_str,
while (sa) { while (sa) {
sa1 = sa->prev; sa1 = sa->prev;
tok_str_free((int *)sa->c); tok_str_free((int *)sa->c);
tcc_free(sa); sym_free(sa);
sa = sa1; sa = sa1;
} }
mstr_allocated = 1; mstr_allocated = 1;
@ -3999,7 +4034,7 @@ static int macro_subst_tok(TokenString *tok_str,
/* pop nested defined symbol */ /* pop nested defined symbol */
sa1 = *nested_list; sa1 = *nested_list;
*nested_list = sa1->prev; *nested_list = sa1->prev;
tcc_free(sa1); sym_free(sa1);
if (mstr_allocated) if (mstr_allocated)
tok_str_free(mstr); tok_str_free(mstr);
} }
@ -9409,10 +9444,12 @@ int tcc_relocate(TCCState *s1)
tcc_add_runtime(s1); tcc_add_runtime(s1);
build_got_entries(s1);
relocate_common_syms(); relocate_common_syms();
tcc_add_linker_symbols(s1);
build_got_entries(s1);
/* compute relocation address : section are relocated in place. We /* compute relocation address : section are relocated in place. We
also alloc the bss space */ also alloc the bss space */
for(i = 1; i < s1->nb_sections; i++) { for(i = 1; i < s1->nb_sections; i++) {