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

Commits:

4 changed files:

Changes:

  • rts/PathUtils.c
    ... ... @@ -13,7 +13,7 @@
    13 13
     #include <wchar.h>
    
    14 14
     #endif
    
    15 15
     
    
    16
    -pathchar* pathdup(pathchar *path)
    
    16
    +pathchar* pathdup(const pathchar *path)
    
    17 17
     {
    
    18 18
         pathchar *ret;
    
    19 19
     #if defined(mingw32_HOST_OS)
    
    ... ... @@ -26,7 +26,7 @@ pathchar* pathdup(pathchar *path)
    26 26
         return ret;
    
    27 27
     }
    
    28 28
     
    
    29
    -pathchar* pathdir(pathchar *path)
    
    29
    +pathchar* pathdir(const pathchar *path)
    
    30 30
     {
    
    31 31
         pathchar *ret;
    
    32 32
     #if defined(mingw32_HOST_OS)
    
    ... ... @@ -40,7 +40,8 @@ pathchar* pathdir(pathchar *path)
    40 40
         stgFree(drive);
    
    41 41
         stgFree(dirName);
    
    42 42
     #else
    
    43
    -    pathchar* dirName = dirname(path);
    
    43
    +    // N.B. cast is safe as we do not modify dirName
    
    44
    +    const pathchar* dirName = dirname((pathchar *) path);
    
    44 45
         size_t memberLen  = pathlen(dirName);
    
    45 46
         ret = stgMallocBytes(pathsize * (memberLen + 2), "pathdir(path)");
    
    46 47
         strcpy(ret, dirName);
    
    ... ... @@ -50,7 +51,7 @@ pathchar* pathdir(pathchar *path)
    50 51
         return ret;
    
    51 52
     }
    
    52 53
     
    
    53
    -pathchar* mkPath(char* path)
    
    54
    +pathchar* mkPath(const char* path)
    
    54 55
     {
    
    55 56
     #if defined(mingw32_HOST_OS)
    
    56 57
         size_t required = mbstowcs(NULL, path, 0);
    
    ... ... @@ -66,7 +67,7 @@ pathchar* mkPath(char* path)
    66 67
     #endif
    
    67 68
     }
    
    68 69
     
    
    69
    -HsBool endsWithPath(pathchar* base, pathchar* str) {
    
    70
    +HsBool endsWithPath(const pathchar* base, const pathchar* str) {
    
    70 71
         int blen = pathlen(base);
    
    71 72
         int slen = pathlen(str);
    
    72 73
         return (blen >= slen) && (0 == pathcmp(base + blen - slen, str));
    

  • rts/PathUtils.h
    ... ... @@ -37,9 +37,9 @@
    37 37
     
    
    38 38
     #include "BeginPrivate.h"
    
    39 39
     
    
    40
    -pathchar* pathdup(pathchar *path);
    
    41
    -pathchar* pathdir(pathchar *path);
    
    42
    -pathchar* mkPath(char* path);
    
    43
    -HsBool endsWithPath(pathchar* base, pathchar* str);
    
    40
    +pathchar* pathdup(const pathchar *path);
    
    41
    +pathchar* pathdir(const pathchar *path);
    
    42
    +pathchar* mkPath(const char* path);
    
    43
    +HsBool endsWithPath(const pathchar* base, const pathchar* str);
    
    44 44
     
    
    45 45
     #include "EndPrivate.h"

  • rts/linker/PEi386.c
    ... ... @@ -378,7 +378,7 @@ static size_t makeSymbolExtra_PEi386(
    378 378
     #endif
    
    379 379
     
    
    380 380
     static void addDLLHandle(
    
    381
    -    pathchar* dll_name,
    
    381
    +    const pathchar* dll_name,
    
    382 382
         HINSTANCE instance);
    
    383 383
     
    
    384 384
     static bool verifyCOFFHeader(
    
    ... ... @@ -427,8 +427,52 @@ 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-map to keep track of which DLLs have
    
    435
    + * already been loaded. This hash-map is keyed on the dll_name passed to
    
    436
    + * addDLL_PEi386 and is mapped to its HINSTANCE. This serves as a quick check
    
    437
    + * to avoid repeated calls to LoadLibraryEx for the identical DLL. See #26009.
    
    438
    + */
    
    439
    +
    
    440
    +typedef struct {
    
    441
    +    HashTable *hash;
    
    442
    +} LoadedDllCache;
    
    443
    +
    
    444
    +LoadedDllCache loaded_dll_cache;
    
    445
    +
    
    446
    +static void initLoadedDllCache(LoadedDllCache *cache) {
    
    447
    +    cache->hash = allocHashTable();
    
    448
    +}
    
    449
    +
    
    450
    +static 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
    +static int compare_path(StgWord key1, StgWord key2)
    
    457
    +{
    
    458
    +    return wcscmp((pathchar*) key1, (pathchar*) key2) == 0;
    
    459
    +}
    
    460
    +
    
    461
    +static void addLoadedDll(LoadedDllCache *cache, const pathchar *dll_name, HINSTANCE instance)
    
    462
    +{
    
    463
    +    insertHashTable_(cache->hash, (StgWord) dll_name, instance, hash_path);
    
    464
    +}
    
    465
    +
    
    466
    +static HINSTANCE isDllLoaded(const LoadedDllCache *cache, const pathchar *dll_name)
    
    467
    +{
    
    468
    +    void *result = lookupHashTable_(cache->hash, (StgWord) dll_name, hash_path, compare_path);
    
    469
    +    return (HINSTANCE) result;
    
    470
    +}
    
    471
    +
    
    430 472
     void initLinker_PEi386(void)
    
    431 473
     {
    
    474
    +    initLoadedDllCache(&loaded_dll_cache);
    
    475
    +
    
    432 476
         if (!ghciInsertSymbolTable(WSTR("(GHCi/Ld special symbols)"),
    
    433 477
                                    symhash, "__image_base__",
    
    434 478
                                    GetModuleHandleW (NULL), HS_BOOL_TRUE,
    
    ... ... @@ -455,7 +499,7 @@ void exitLinker_PEi386(void)
    455 499
     static OpenedDLL* opened_dlls = NULL;
    
    456 500
     
    
    457 501
     /* Adds a DLL instance to the list of DLLs in which to search for symbols. */
    
    458
    -static void addDLLHandle(pathchar* dll_name, HINSTANCE instance) {
    
    502
    +static void addDLLHandle(const pathchar* dll_name, HINSTANCE instance) {
    
    459 503
     
    
    460 504
         IF_DEBUG(linker, debugBelch("addDLLHandle(%" PATH_FMT ")...\n", dll_name));
    
    461 505
         /* At this point, we actually know what was loaded.
    
    ... ... @@ -797,11 +841,20 @@ uint8_t* getSymShortName ( COFF_HEADER_INFO *info, COFF_symbol* sym )
    797 841
     }
    
    798 842
     
    
    799 843
     const char *
    
    800
    -addDLL_PEi386( pathchar *dll_name, HINSTANCE *loaded )
    
    844
    +addDLL_PEi386( const pathchar *dll_name, HINSTANCE *loaded )
    
    801 845
     {
    
    802 846
         /* ------------------- Win32 DLL loader ------------------- */
    
    803 847
         IF_DEBUG(linker, debugBelch("addDLL; dll_name = `%" PATH_FMT "'\n", dll_name));
    
    804 848
     
    
    849
    +    // See Note [Avoiding repeated DLL loading]
    
    850
    +    HINSTANCE instance = isDllLoaded(&loaded_dll_cache, dll_name);
    
    851
    +    if (instance) {
    
    852
    +        if (loaded) {
    
    853
    +            *loaded = instance;
    
    854
    +        }
    
    855
    +        return NULL;
    
    856
    +    }
    
    857
    +
    
    805 858
         /* The file name has no suffix (yet) so that we can try
    
    806 859
            both foo.dll and foo.drv
    
    807 860
     
    
    ... ... @@ -820,7 +873,6 @@ addDLL_PEi386( pathchar *dll_name, HINSTANCE *loaded )
    820 873
         const DWORD flags[] = { LOAD_LIBRARY_SEARCH_USER_DIRS | LOAD_LIBRARY_SEARCH_DEFAULT_DIRS, 0 };
    
    821 874
     
    
    822 875
         /* Iterate through the possible flags and formats.  */
    
    823
    -    HINSTANCE instance;
    
    824 876
         for (int cFlag = 0; cFlag < 2; cFlag++) {
    
    825 877
             for (int cFormat = 0; cFormat < 4; cFormat++) {
    
    826 878
                 snwprintf(buf, bufsize, formats[cFormat], dll_name);
    
    ... ... @@ -839,6 +891,7 @@ addDLL_PEi386( pathchar *dll_name, HINSTANCE *loaded )
    839 891
         goto error;
    
    840 892
     
    
    841 893
     loaded:
    
    894
    +    addLoadedDll(&loaded_dll_cache, dll_name, instance);
    
    842 895
         addDLLHandle(buf, instance);
    
    843 896
         if (loaded) {
    
    844 897
             *loaded = instance;
    

  • rts/linker/PEi386.h
    ... ... @@ -45,7 +45,7 @@ typedef struct _COFF_HEADER_INFO {
    45 45
     
    
    46 46
     void initLinker_PEi386( void );
    
    47 47
     void exitLinker_PEi386( void );
    
    48
    -const char * addDLL_PEi386( pathchar *dll_name, HINSTANCE *instance  );
    
    48
    +const char * addDLL_PEi386( const pathchar *dll_name, HINSTANCE *instance  );
    
    49 49
     void freePreloadObjectFile_PEi386( ObjectCode *oc );
    
    50 50
     
    
    51 51
     bool checkAndLoadImportLibrary( pathchar* arch_name, char* member_name, FILE* f);