Ben Gamari pushed to branch wip/T26009 at Glasgow Haskell Compiler / GHC

Commits:

3 changed files:

Changes:

  • rts/Hash.c
    ... ... @@ -94,13 +94,13 @@ hashWord(const HashTable *table, StgWord key)
    94 94
     }
    
    95 95
     
    
    96 96
     int
    
    97
    -hashStr(const HashTable *table, StgWord w)
    
    97
    +hashBuffer(const HashTable *table, const void *buf, size_t len)
    
    98 98
     {
    
    99
    -    const char *key = (char*) w;
    
    99
    +    const char *key = (char*) buf;
    
    100 100
     #if WORD_SIZE_IN_BITS == 64
    
    101
    -    StgWord h = XXH3_64bits_withSeed (key, strlen(key), 1048583);
    
    101
    +    StgWord h = XXH3_64bits_withSeed (key, len, 1048583);
    
    102 102
     #else
    
    103
    -    StgWord h = XXH32 (key, strlen(key), 1048583);
    
    103
    +    StgWord h = XXH32 (key, len, 1048583);
    
    104 104
     #endif
    
    105 105
     
    
    106 106
         /* Mod the size of the hash table (a power of 2) */
    
    ... ... @@ -114,6 +114,13 @@ hashStr(const HashTable *table, StgWord w)
    114 114
         return bucket;
    
    115 115
     }
    
    116 116
     
    
    117
    +int
    
    118
    +hashStr(const HashTable *table, StgWord w)
    
    119
    +{
    
    120
    +    const char *key = (char*) w;
    
    121
    +    return hashBuffer(table, key, strlen(key));
    
    122
    +}
    
    123
    +
    
    117 124
     STATIC_INLINE int
    
    118 125
     compareWord(StgWord key1, StgWord key2)
    
    119 126
     {
    

  • rts/Hash.h
    ... ... @@ -69,6 +69,10 @@ void * removeStrHashTable ( StrHashTable *table, const char * key,
    69 69
      */
    
    70 70
     typedef int HashFunction(const HashTable *table, StgWord key);
    
    71 71
     typedef int CompareFunction(StgWord key1, StgWord key2);
    
    72
    +
    
    73
    +// Helper for implementing hash functions
    
    74
    +int hashBuffer(const HashTable *table, const void *buf, size_t len);
    
    75
    +
    
    72 76
     int hashWord(const HashTable *table, StgWord key);
    
    73 77
     int hashStr(const HashTable *table, StgWord w);
    
    74 78
     void        insertHashTable_ ( HashTable *table, StgWord key,
    
    ... ... @@ -79,6 +83,7 @@ void * removeHashTable_ ( HashTable *table, StgWord key,
    79 83
                                    const void *data, HashFunction f,
    
    80 84
                                    CompareFunction cmp );
    
    81 85
     
    
    86
    +
    
    82 87
     /* Freeing hash tables
    
    83 88
      */
    
    84 89
     void freeHashTable ( HashTable *table, void (*freeDataFun)(void *) );
    

  • rts/linker/PEi386.c
    ... ... @@ -427,8 +427,53 @@ const int default_alignment = 8;
    427 427
        the pointer as a redirect.  Essentially it's a DATA DLL reference.  */
    
    428 428
     const void* __rts_iob_func = (void*)&__acrt_iob_func;
    
    429 429
     
    
    430
    +/*
    
    431
    + * Note [Avoiding repeated DLL loading]
    
    432
    + * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    
    433
    + * As LoadLibraryEx tends to be expensive and addDLL_PEi386 is called on every
    
    434
    + * DLL-imported symbol, we use a hash-set to keep track of which DLLs have
    
    435
    + * already been loaded. This hash-set is keyed on the dll_name passed to
    
    436
    + * addDLL_PEi386 and serves as a quick check to avoid repeated calls to
    
    437
    + * LoadLibraryEx for the identical DLL. See #26009.
    
    438
    + */
    
    439
    +
    
    440
    +typedef struct {
    
    441
    +    HashTable *hash;
    
    442
    +} LoadedDllSet;
    
    443
    +
    
    444
    +LoadedDllSet loaded_dll_set;
    
    445
    +
    
    446
    +void initLoadedDllSet(LoadedDllSet *set) {
    
    447
    +    set->hash = allocHashTable();
    
    448
    +}
    
    449
    +
    
    450
    +int hash_path(const HashTable *table, StgWord w)
    
    451
    +{
    
    452
    +    const pathchar *key = (pathchar*) w;
    
    453
    +    return hashBuffer(table, key, sizeof(pathchar) * wcslen(key));
    
    454
    +}
    
    455
    +
    
    456
    +int compare_path(StgWord key1, StgWord key2)
    
    457
    +{
    
    458
    +    return wscmp((pathchar*) key1, (pathchar*) key2);
    
    459
    +}
    
    460
    +
    
    461
    +void addLoadedDll(LoadedDllSet *set, pathchar *dll_name)
    
    462
    +{
    
    463
    +    insertHashTable_(set->hash, (StgWord) dll_name, (void*) 1, hash_path);
    
    464
    +}
    
    465
    +
    
    466
    +bool isDllLoaded(LoadedDllSet *set, pathchar *dll_name)
    
    467
    +{
    
    468
    +    void * result = lookupHashTable_(set->hash, (StgWord) dll_name, hash_path, compare_path);
    
    469
    +    return result != NULL;
    
    470
    +}
    
    471
    +
    
    472
    +
    
    430 473
     void initLinker_PEi386(void)
    
    431 474
     {
    
    475
    +    initLoadedDllSet(&loaded_dll_set);
    
    476
    +
    
    432 477
         if (!ghciInsertSymbolTable(WSTR("(GHCi/Ld special symbols)"),
    
    433 478
                                    symhash, "__image_base__",
    
    434 479
                                    GetModuleHandleW (NULL), HS_BOOL_TRUE,
    
    ... ... @@ -802,6 +847,10 @@ addDLL_PEi386( pathchar *dll_name, HINSTANCE *loaded )
    802 847
         /* ------------------- Win32 DLL loader ------------------- */
    
    803 848
         IF_DEBUG(linker, debugBelch("addDLL; dll_name = `%" PATH_FMT "'\n", dll_name));
    
    804 849
     
    
    850
    +    if (isDllLoaded(&loaded_dll_set, dll_name)) {
    
    851
    +        return NULL;
    
    852
    +    }
    
    853
    +
    
    805 854
         /* The file name has no suffix (yet) so that we can try
    
    806 855
            both foo.dll and foo.drv
    
    807 856
     
    
    ... ... @@ -840,6 +889,7 @@ addDLL_PEi386( pathchar *dll_name, HINSTANCE *loaded )
    840 889
             goto error;
    
    841 890
         }
    
    842 891
     
    
    892
    +    addLoadedDll(&loaded_dll_set, dll_name);
    
    843 893
         addDLLHandle(buf, instance);
    
    844 894
         if (loaded) {
    
    845 895
             *loaded = instance;