On 7/7/23 08:59, grischka wrote:
On 07.07.2023 07:45, draco wrote:
Hermann,
I tested your patch a bit, seems to work as expected and brings tcc
win32 back to it's normal speed.
It might be too slow on linux too ...
Basically the "#ifndef cache" is meant to make it faster,
while the #pragma once also needs to detect path aliases.
That is two different goals in the first place.
Another goal in tinycc is simple code. For example to have
a common solution for platforms.
I did a benchmark on linux and it is about 2% slower on my machine.
I created a new patch where I removed the stat call.
I now calculate the full path name on linux and windows.
This means that soft/hard links do not work any more.
There is still a small slowdown because we create/compare the full path
name now.
But it is about 0.1% on my 64 bits x86_64 machine. Hard to measure correct.
Herman
diff --git a/tcc.h b/tcc.h
index 78b0174..00d8087 100644
--- a/tcc.h
+++ b/tcc.h
@@ -38,7 +38,6 @@
#include <fcntl.h>
#include <setjmp.h>
#include <time.h>
-#include <sys/stat.h>
#ifndef _WIN32
# include <unistd.h>
@@ -717,10 +716,6 @@ typedef struct InlineFunc {
/* include file cache, used to find files faster and also to eliminate
inclusion if the include file is protected by #ifndef ... #endif */
typedef struct CachedInclude {
- struct stat st;
-#ifdef _WIN32
- unsigned long long hash;
-#endif
int ifndef_macro;
int once;
int hash_next; /* -1 if none */
diff --git a/tccpp.c b/tccpp.c
index b95c63d..a483648 100644
--- a/tccpp.c
+++ b/tccpp.c
@@ -51,6 +51,7 @@ static int pp_debug_tok, pp_debug_symv;
static int pp_once;
static int pp_expr;
static int pp_counter;
+static char pp_wd[1024];
static void tok_print(const char *msg, const int *str);
static struct TinyAlloc *toksym_alloc;
@@ -1607,98 +1608,89 @@ bad_twosharp:
define_push(v, t, tok_str_dup(&tokstr_buf), first);
}
-#ifdef _WIN32
-static unsigned long long calc_file_hash(const char *filename)
-{
- unsigned long long hash = 14695981039346656037ull; // FNV_offset_basis;
- int fd = open (filename, O_RDONLY | O_BINARY);
-
- if (fd < 0)
- return 0;
- for (;;) {
- unsigned char temp[IO_BUF_SIZE];
- int i, n = read(fd, temp, sizeof(temp));
-
- if (n <= 0)
- break;
- for (i = 0; i < n; i++)
- hash = hash * 1099511628211ull ^ temp[i]; // FNV_prime
- }
- close(fd);
- return hash ? hash : 1ull;
-}
-#endif
-
static CachedInclude *search_cached_include(TCCState *s1, const char
*filename, int add)
{
+ unsigned char *s, *t, *f;
unsigned int h = 0;
CachedInclude *e;
int i;
- struct stat st;
-#ifdef _WIN32
- unsigned long long hash = 0;
-#endif
+ char fullname[sizeof(pp_wd)];
/* This is needed for #pragmae once
- * We cannot use stat on windows because st_ino is not set correctly
- * so we calculate a hash of file contents.
- * This also works for hard/soft links as in gcc/clang.
- */
- memset (&st, 0, sizeof(st));
- if (stat (filename, &st))
- goto skip;
- h = st.st_size & (CACHED_INCLUDES_HASH_SIZE - 1);
+ * We calculate the full pathname to find simular names.
+ * This does not work for hard/soft links like in gcc/clang.
+ */
+
+ if (IS_ABSPATH (filename))
+ pstrcpy (fullname, sizeof(fullname), filename);
+ else {
+ pstrcpy (fullname, sizeof(fullname), pp_wd);
+ pstrcat (fullname, sizeof(fullname), "/");
+ pstrcat (fullname, sizeof(fullname), filename);
+ }
#ifdef _WIN32
- /* Only calculate file hash if file size same. */
- i = s1->cached_includes_hash[h];
- for(;;) {
- if (i == 0)
- break;
- e = s1->cached_includes[i - 1];
- if (e->st.st_size == st.st_size) {
- if (0 == PATHCMP(e->filename, filename)) {
- hash = e->hash;
- break;
- }
- if (e->hash == 0)
- e->hash = calc_file_hash(e->filename);
- if (hash == 0)
- hash = calc_file_hash(filename);
+ normalize_slashes(fullname);
+#endif
+ /* Skip possible drive letter */
+ f = (unsigned char *) fullname;
+ while (*f != '/')
+ f++;
+ s = f;
+ t = f;
+ while (*s) {
+ if (*s == '/') {
+ *t++ = *s++;
+ while (*s == '/')
+ s++;
}
- i = e->hash_next;
+ if (s[0] == '.' && s[1] == '/')
+ s += 2;
+ else if (s[0] == '.' && s[1] == '.' && s[2] == '/') {
+ s += 3;
+ if (t > (f + 1) && t[-1] == '/')
+ t--;
+ while (t > (f + 1) && t[-1] != '/')
+ t--;
+ }
+ else
+ while (*s && *s != '/')
+ *t++ = *s++;
}
+ *t = '\0';
+
+ h = TOK_HASH_INIT;
+ s = (unsigned char *) fullname;
+ while (*s) {
+#ifdef _WIN32
+ h = TOK_HASH_FUNC(h, toup(*s));
+#else
+ h = TOK_HASH_FUNC(h, *s);
#endif
+ s++;
+ }
+ h &= (CACHED_INCLUDES_HASH_SIZE - 1);
i = s1->cached_includes_hash[h];
for(;;) {
if (i == 0)
break;
e = s1->cached_includes[i - 1];
-#ifdef _WIN32
- if (e->st.st_size == st.st_size && e->hash == hash)
-#else
- if (st.st_dev == e->st.st_dev && st.st_ino == e->st.st_ino)
-#endif
+ if (0 == PATHCMP(e->filename, fullname))
return e;
i = e->hash_next;
}
-skip:
if (!add)
return NULL;
- e = tcc_malloc(sizeof(CachedInclude) + strlen(filename));
- e->st = st;
-#ifdef _WIN32
- e->hash = hash;
-#endif
- strcpy(e->filename, filename);
+ e = tcc_malloc(sizeof(CachedInclude) + strlen(fullname));
+ strcpy(e->filename, fullname);
e->ifndef_macro = e->once = 0;
dynarray_add(&s1->cached_includes, &s1->nb_cached_includes, e);
/* add in hash table */
e->hash_next = s1->cached_includes_hash[h];
s1->cached_includes_hash[h] = s1->nb_cached_includes;
#ifdef INC_DEBUG
- printf("adding cached '%s'\n", filename);
+ printf("adding cached '%s'\n", fullname);
#endif
return e;
}
@@ -3709,6 +3701,7 @@ ST_FUNC void preprocess_start(TCCState *s1, int filetype)
parse_flags = is_asm ? PARSE_FLAG_ASM_FILE : 0;
tok_flags = TOK_FLAG_BOL | TOK_FLAG_BOF;
+ getcwd(pp_wd, sizeof(pp_wd));
}
/* cleanup from error/setjmp */
_______________________________________________
Tinycc-devel mailing list
Tinycc-devel@nongnu.org
https://lists.nongnu.org/mailman/listinfo/tinycc-devel