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

Reply via email to