Mon Nov 23 18:24:05 2020 UTC ()
make(1): migrate CachedDir.files from HashTable to HashSet


(rillig)
diff -r1.210 -r1.211 src/usr.bin/make/dir.c
diff -r1.34 -r1.35 src/usr.bin/make/dir.h
diff -r1.35 -r1.36 src/usr.bin/make/hash.h

cvs diff -r1.210 -r1.211 src/usr.bin/make/dir.c (expand / switch to unified diff)

--- src/usr.bin/make/dir.c 2020/11/14 21:29:44 1.210
+++ src/usr.bin/make/dir.c 2020/11/23 18:24:05 1.211
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: dir.c,v 1.210 2020/11/14 21:29:44 rillig Exp $ */ 1/* $NetBSD: dir.c,v 1.211 2020/11/23 18:24:05 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * All rights reserved. 5 * All rights reserved.
6 * 6 *
7 * This code is derived from software contributed to Berkeley by 7 * This code is derived from software contributed to Berkeley by
8 * Adam de Boor. 8 * Adam de Boor.
9 * 9 *
10 * Redistribution and use in source and binary forms, with or without 10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions 11 * modification, are permitted provided that the following conditions
12 * are met: 12 * are met:
13 * 1. Redistributions of source code must retain the above copyright 13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer. 14 * notice, this list of conditions and the following disclaimer.
@@ -124,27 +124,27 @@ @@ -124,27 +124,27 @@
124 */ 124 */
125 125
126#include <sys/types.h> 126#include <sys/types.h>
127#include <sys/stat.h> 127#include <sys/stat.h>
128 128
129#include <dirent.h> 129#include <dirent.h>
130#include <errno.h> 130#include <errno.h>
131 131
132#include "make.h" 132#include "make.h"
133#include "dir.h" 133#include "dir.h"
134#include "job.h" 134#include "job.h"
135 135
136/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */ 136/* "@(#)dir.c 8.2 (Berkeley) 1/2/94" */
137MAKE_RCSID("$NetBSD: dir.c,v 1.210 2020/11/14 21:29:44 rillig Exp $"); 137MAKE_RCSID("$NetBSD: dir.c,v 1.211 2020/11/23 18:24:05 rillig Exp $");
138 138
139#define DIR_DEBUG0(text) DEBUG0(DIR, text) 139#define DIR_DEBUG0(text) DEBUG0(DIR, text)
140#define DIR_DEBUG1(fmt, arg1) DEBUG1(DIR, fmt, arg1) 140#define DIR_DEBUG1(fmt, arg1) DEBUG1(DIR, fmt, arg1)
141#define DIR_DEBUG2(fmt, arg1, arg2) DEBUG2(DIR, fmt, arg1, arg2) 141#define DIR_DEBUG2(fmt, arg1, arg2) DEBUG2(DIR, fmt, arg1, arg2)
142 142
143/* A search path is a list of CachedDir structures. A CachedDir has in it the 143/* A search path is a list of CachedDir structures. A CachedDir has in it the
144 * name of the directory and the names of all the files in the directory. 144 * name of the directory and the names of all the files in the directory.
145 * This is used to cut down on the number of system calls necessary to find 145 * This is used to cut down on the number of system calls necessary to find
146 * implicit dependents and their like. Since these searches are made before 146 * implicit dependents and their like. Since these searches are made before
147 * any actions are taken, we need not worry about the directory changing due 147 * any actions are taken, we need not worry about the directory changing due
148 * to creation commands. If this hampers the style of some makefiles, they 148 * to creation commands. If this hampers the style of some makefiles, they
149 * must be changed. 149 * must be changed.
150 * 150 *
@@ -369,27 +369,27 @@ Dir_Init(void) @@ -369,27 +369,27 @@ Dir_Init(void)
369 HashTable_Init(&mtimes); 369 HashTable_Init(&mtimes);
370 HashTable_Init(&lmtimes); 370 HashTable_Init(&lmtimes);
371} 371}
372 372
373void 373void
374Dir_InitDir(const char *cdname) 374Dir_InitDir(const char *cdname)
375{ 375{
376 Dir_InitCur(cdname); 376 Dir_InitCur(cdname);
377 377
378 dotLast = bmake_malloc(sizeof *dotLast); 378 dotLast = bmake_malloc(sizeof *dotLast);
379 dotLast->refCount = 1; 379 dotLast->refCount = 1;
380 dotLast->hits = 0; 380 dotLast->hits = 0;
381 dotLast->name = bmake_strdup(".DOTLAST"); 381 dotLast->name = bmake_strdup(".DOTLAST");
382 HashTable_Init(&dotLast->files); 382 HashSet_Init(&dotLast->files);
383} 383}
384 384
385/* 385/*
386 * Called by Dir_InitDir and whenever .CURDIR is assigned to. 386 * Called by Dir_InitDir and whenever .CURDIR is assigned to.
387 */ 387 */
388void 388void
389Dir_InitCur(const char *cdname) 389Dir_InitCur(const char *cdname)
390{ 390{
391 CachedDir *dir; 391 CachedDir *dir;
392 392
393 if (cdname == NULL) 393 if (cdname == NULL)
394 return; 394 return;
395 395
@@ -563,27 +563,27 @@ Dir_HasWildcards(const char *name) @@ -563,27 +563,27 @@ Dir_HasWildcards(const char *name)
563 * dir Directory to search 563 * dir Directory to search
564 * expansion Place to store the results 564 * expansion Place to store the results
565 */ 565 */
566static void 566static void
567DirMatchFiles(const char *pattern, CachedDir *dir, StringList *expansions) 567DirMatchFiles(const char *pattern, CachedDir *dir, StringList *expansions)
568{ 568{
569 const char *dirName = dir->name; 569 const char *dirName = dir->name;
570 Boolean isDot = dirName[0] == '.' && dirName[1] == '\0'; 570 Boolean isDot = dirName[0] == '.' && dirName[1] == '\0';
571 HashIter hi; 571 HashIter hi;
572 572
573 /* XXX: Iterating over all hash entries is inefficient. If the pattern 573 /* XXX: Iterating over all hash entries is inefficient. If the pattern
574 * is a plain string without any wildcards, a direct lookup is faster. */ 574 * is a plain string without any wildcards, a direct lookup is faster. */
575 575
576 HashIter_Init(&hi, &dir->files); 576 HashIter_InitSet(&hi, &dir->files);
577 while (HashIter_Next(&hi) != NULL) { 577 while (HashIter_Next(&hi) != NULL) {
578 const char *base = hi.entry->key; 578 const char *base = hi.entry->key;
579 579
580 if (!Str_Match(base, pattern)) 580 if (!Str_Match(base, pattern))
581 continue; 581 continue;
582 582
583 /* 583 /*
584 * Follow the UNIX convention that dot files are only found if the 584 * Follow the UNIX convention that dot files are only found if the
585 * pattern begins with a dot. The pattern '.*' does not match '.' or 585 * pattern begins with a dot. The pattern '.*' does not match '.' or
586 * '..' since these are not included in the directory cache. 586 * '..' since these are not included in the directory cache.
587 * 587 *
588 * This means that the pattern '[a-z.]*' does not find '.file', which 588 * This means that the pattern '[a-z.]*' does not find '.file', which
589 * is consistent with bash, NetBSD sh and csh. 589 * is consistent with bash, NetBSD sh and csh.
@@ -838,27 +838,27 @@ Dir_Expand(const char *word, SearchPath  @@ -838,27 +838,27 @@ Dir_Expand(const char *word, SearchPath
838 if (DEBUG(DIR)) 838 if (DEBUG(DIR))
839 PrintExpansions(expansions); 839 PrintExpansions(expansions);
840} 840}
841 841
842/* Find if the file with the given name exists in the given path. 842/* Find if the file with the given name exists in the given path.
843 * Return the freshly allocated path to the file, or NULL. */ 843 * Return the freshly allocated path to the file, or NULL. */
844static char * 844static char *
845DirLookup(CachedDir *dir, const char *base) 845DirLookup(CachedDir *dir, const char *base)
846{ 846{
847 char *file; /* the current filename to check */ 847 char *file; /* the current filename to check */
848 848
849 DIR_DEBUG1(" %s ...\n", dir->name); 849 DIR_DEBUG1(" %s ...\n", dir->name);
850 850
851 if (HashTable_FindEntry(&dir->files, base) == NULL) 851 if (!HashSet_Contains(&dir->files, base))
852 return NULL; 852 return NULL;
853 853
854 file = str_concat3(dir->name, "/", base); 854 file = str_concat3(dir->name, "/", base);
855 DIR_DEBUG1(" returning %s\n", file); 855 DIR_DEBUG1(" returning %s\n", file);
856 dir->hits++; 856 dir->hits++;
857 hits++; 857 hits++;
858 return file; 858 return file;
859} 859}
860 860
861 861
862/* Find if the file with the given name exists in the given directory. 862/* Find if the file with the given name exists in the given directory.
863 * Return the freshly allocated path to the file, or NULL. */ 863 * Return the freshly allocated path to the file, or NULL. */
864static char * 864static char *
@@ -891,51 +891,51 @@ DirLookupAbs(CachedDir *dir, const char  @@ -891,51 +891,51 @@ DirLookupAbs(CachedDir *dir, const char
891 DIR_DEBUG1(" %s ...\n", dir->name); 891 DIR_DEBUG1(" %s ...\n", dir->name);
892 892
893 /* 893 /*
894 * If the file has a leading path component and that component 894 * If the file has a leading path component and that component
895 * exactly matches the entire name of the current search 895 * exactly matches the entire name of the current search
896 * directory, we can attempt another cache lookup. And if we don't 896 * directory, we can attempt another cache lookup. And if we don't
897 * have a hit, we can safely assume the file does not exist at all. 897 * have a hit, we can safely assume the file does not exist at all.
898 */ 898 */
899 for (dnp = dir->name, np = name; *dnp != '\0' && *dnp == *np; dnp++, np++) 899 for (dnp = dir->name, np = name; *dnp != '\0' && *dnp == *np; dnp++, np++)
900 continue; 900 continue;
901 if (*dnp != '\0' || np != cp - 1) 901 if (*dnp != '\0' || np != cp - 1)
902 return NULL; 902 return NULL;
903 903
904 if (HashTable_FindEntry(&dir->files, cp) == NULL) { 904 if (!HashSet_Contains(&dir->files, cp)) {
905 DIR_DEBUG0(" must be here but isn't -- returning\n"); 905 DIR_DEBUG0(" must be here but isn't -- returning\n");
906 return bmake_strdup(""); /* to terminate the search */ 906 return bmake_strdup(""); /* to terminate the search */
907 } 907 }
908 908
909 dir->hits++; 909 dir->hits++;
910 hits++; 910 hits++;
911 DIR_DEBUG1(" returning %s\n", name); 911 DIR_DEBUG1(" returning %s\n", name);
912 return bmake_strdup(name); 912 return bmake_strdup(name);
913} 913}
914 914
915/* Find the file given on "." or curdir. 915/* Find the file given on "." or curdir.
916 * Return the freshly allocated path to the file, or NULL. */ 916 * Return the freshly allocated path to the file, or NULL. */
917static char * 917static char *
918DirFindDot(const char *name, const char *base) 918DirFindDot(const char *name, const char *base)
919{ 919{
920 920
921 if (HashTable_FindEntry(&dot->files, base) != NULL) { 921 if (HashSet_Contains(&dot->files, base)) {
922 DIR_DEBUG0(" in '.'\n"); 922 DIR_DEBUG0(" in '.'\n");
923 hits++; 923 hits++;
924 dot->hits++; 924 dot->hits++;
925 return bmake_strdup(name); 925 return bmake_strdup(name);
926 } 926 }
927 927
928 if (cur != NULL && HashTable_FindEntry(&cur->files, base) != NULL) { 928 if (cur != NULL && HashSet_Contains(&cur->files, base)) {
929 DIR_DEBUG1(" in ${.CURDIR} = %s\n", cur->name); 929 DIR_DEBUG1(" in ${.CURDIR} = %s\n", cur->name);
930 hits++; 930 hits++;
931 cur->hits++; 931 cur->hits++;
932 return str_concat3(cur->name, "/", base); 932 return str_concat3(cur->name, "/", base);
933 } 933 }
934 934
935 return NULL; 935 return NULL;
936} 936}
937 937
938/* Find the file with the given name along the given search path. 938/* Find the file with the given name along the given search path.
939 * 939 *
940 * If the file is found in a directory that is not on the path 940 * If the file is found in a directory that is not on the path
941 * already (either 'name' is absolute or it is a relative path 941 * already (either 'name' is absolute or it is a relative path
@@ -1380,40 +1380,40 @@ Dir_AddDir(SearchPath *path, const char  @@ -1380,40 +1380,40 @@ Dir_AddDir(SearchPath *path, const char
1380 dir->refCount++; 1380 dir->refCount++;
1381 Lst_Append(path, dir); 1381 Lst_Append(path, dir);
1382 } 1382 }
1383 return dir; 1383 return dir;
1384 } 1384 }
1385 1385
1386 DIR_DEBUG1("Caching %s ...", name); 1386 DIR_DEBUG1("Caching %s ...", name);
1387 1387
1388 if ((d = opendir(name)) != NULL) { 1388 if ((d = opendir(name)) != NULL) {
1389 dir = bmake_malloc(sizeof *dir); 1389 dir = bmake_malloc(sizeof *dir);
1390 dir->name = bmake_strdup(name); 1390 dir->name = bmake_strdup(name);
1391 dir->hits = 0; 1391 dir->hits = 0;
1392 dir->refCount = 1; 1392 dir->refCount = 1;
1393 HashTable_Init(&dir->files); 1393 HashSet_Init(&dir->files);
1394 1394
1395 while ((dp = readdir(d)) != NULL) { 1395 while ((dp = readdir(d)) != NULL) {
1396#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */ 1396#if defined(sun) && defined(d_ino) /* d_ino is a sunos4 #define for d_fileno */
1397 /* 1397 /*
1398 * The sun directory library doesn't check for a 0 inode 1398 * The sun directory library doesn't check for a 0 inode
1399 * (0-inode slots just take up space), so we have to do 1399 * (0-inode slots just take up space), so we have to do
1400 * it ourselves. 1400 * it ourselves.
1401 */ 1401 */
1402 if (dp->d_fileno == 0) { 1402 if (dp->d_fileno == 0) {
1403 continue; 1403 continue;
1404 } 1404 }
1405#endif /* sun && d_ino */ 1405#endif /* sun && d_ino */
1406 (void)HashTable_CreateEntry(&dir->files, dp->d_name, NULL); 1406 (void)HashSet_Add(&dir->files, dp->d_name);
1407 } 1407 }
1408 (void)closedir(d); 1408 (void)closedir(d);
1409 OpenDirs_Add(&openDirs, dir); 1409 OpenDirs_Add(&openDirs, dir);
1410 if (path != NULL) 1410 if (path != NULL)
1411 Lst_Append(path, dir); 1411 Lst_Append(path, dir);
1412 } 1412 }
1413 DIR_DEBUG0("done\n"); 1413 DIR_DEBUG0("done\n");
1414 return dir; 1414 return dir;
1415} 1415}
1416 1416
1417/* Return a copy of dirSearchPath, incrementing the reference counts for 1417/* Return a copy of dirSearchPath, incrementing the reference counts for
1418 * the contained directories. */ 1418 * the contained directories. */
1419SearchPath * 1419SearchPath *
@@ -1475,27 +1475,27 @@ Dir_MakeFlags(const char *flag, SearchPa @@ -1475,27 +1475,27 @@ Dir_MakeFlags(const char *flag, SearchPa
1475 * 1475 *
1476 * Input: 1476 * Input:
1477 * dirp The directory descriptor to nuke 1477 * dirp The directory descriptor to nuke
1478 */ 1478 */
1479void 1479void
1480Dir_Destroy(void *dirp) 1480Dir_Destroy(void *dirp)
1481{ 1481{
1482 CachedDir *dir = dirp; 1482 CachedDir *dir = dirp;
1483 dir->refCount--; 1483 dir->refCount--;
1484 1484
1485 if (dir->refCount == 0) { 1485 if (dir->refCount == 0) {
1486 OpenDirs_Remove(&openDirs, dir->name); 1486 OpenDirs_Remove(&openDirs, dir->name);
1487 1487
1488 HashTable_Done(&dir->files); 1488 HashSet_Done(&dir->files);
1489 free(dir->name); 1489 free(dir->name);
1490 free(dir); 1490 free(dir);
1491 } 1491 }
1492} 1492}
1493 1493
1494/* Clear out all elements from the given search path. 1494/* Clear out all elements from the given search path.
1495 * The path is set to the empty list but is not destroyed. */ 1495 * The path is set to the empty list but is not destroyed. */
1496void 1496void
1497Dir_ClearPath(SearchPath *path) 1497Dir_ClearPath(SearchPath *path)
1498{ 1498{
1499 while (!Lst_IsEmpty(path)) { 1499 while (!Lst_IsEmpty(path)) {
1500 CachedDir *dir = Lst_Dequeue(path); 1500 CachedDir *dir = Lst_Dequeue(path);
1501 Dir_Destroy(dir); 1501 Dir_Destroy(dir);

cvs diff -r1.34 -r1.35 src/usr.bin/make/dir.h (expand / switch to unified diff)

--- src/usr.bin/make/dir.h 2020/11/14 19:24:24 1.34
+++ src/usr.bin/make/dir.h 2020/11/23 18:24:05 1.35
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: dir.h,v 1.34 2020/11/14 19:24:24 rillig Exp $ */ 1/* $NetBSD: dir.h,v 1.35 2020/11/23 18:24:05 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * 5 *
6 * This code is derived from software contributed to Berkeley by 6 * This code is derived from software contributed to Berkeley by
7 * Adam de Boor. 7 * Adam de Boor.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -77,28 +77,27 @@ @@ -77,28 +77,27 @@
77 77
78/* A cache for the filenames in a directory. */ 78/* A cache for the filenames in a directory. */
79typedef struct CachedDir { 79typedef struct CachedDir {
80 char *name; /* Name of directory, either absolute or 80 char *name; /* Name of directory, either absolute or
81 * relative to the current directory. 81 * relative to the current directory.
82 * The name is not normalized in any way, 82 * The name is not normalized in any way,
83 * that is, "." and "./." are different. 83 * that is, "." and "./." are different.
84 * 84 *
85 * Not sure what happens when .CURDIR is 85 * Not sure what happens when .CURDIR is
86 * assigned a new value; see Parse_DoVar. */ 86 * assigned a new value; see Parse_DoVar. */
87 int refCount; /* Number of SearchPaths with this directory */ 87 int refCount; /* Number of SearchPaths with this directory */
88 int hits; /* The number of times a file in this 88 int hits; /* The number of times a file in this
89 * directory has been found */ 89 * directory has been found */
90 HashTable files; /* Hash set of files in directory; 90 HashSet files; /* The files in the directory. */
91 * all values are NULL. */ 
92} CachedDir; 91} CachedDir;
93 92
94void Dir_Init(void); 93void Dir_Init(void);
95void Dir_InitDir(const char *); 94void Dir_InitDir(const char *);
96void Dir_InitCur(const char *); 95void Dir_InitCur(const char *);
97void Dir_InitDot(void); 96void Dir_InitDot(void);
98void Dir_End(void); 97void Dir_End(void);
99void Dir_SetPATH(void); 98void Dir_SetPATH(void);
100Boolean Dir_HasWildcards(const char *); 99Boolean Dir_HasWildcards(const char *);
101void Dir_Expand(const char *, SearchPath *, StringList *); 100void Dir_Expand(const char *, SearchPath *, StringList *);
102char *Dir_FindFile(const char *, SearchPath *); 101char *Dir_FindFile(const char *, SearchPath *);
103char *Dir_FindHereOrAbove(const char *, const char *); 102char *Dir_FindHereOrAbove(const char *, const char *);
104void Dir_UpdateMTime(GNode *, Boolean); 103void Dir_UpdateMTime(GNode *, Boolean);

cvs diff -r1.35 -r1.36 src/usr.bin/make/hash.h (expand / switch to unified diff)

--- src/usr.bin/make/hash.h 2020/11/23 18:07:10 1.35
+++ src/usr.bin/make/hash.h 2020/11/23 18:24:05 1.36
@@ -1,14 +1,14 @@ @@ -1,14 +1,14 @@
1/* $NetBSD: hash.h,v 1.35 2020/11/23 18:07:10 rillig Exp $ */ 1/* $NetBSD: hash.h,v 1.36 2020/11/23 18:24:05 rillig Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California. 4 * Copyright (c) 1988, 1989, 1990 The Regents of the University of California.
5 * 5 *
6 * This code is derived from software contributed to Berkeley by 6 * This code is derived from software contributed to Berkeley by
7 * Adam de Boor. 7 * Adam de Boor.
8 * 8 *
9 * Redistribution and use in source and binary forms, with or without 9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions 10 * modification, are permitted provided that the following conditions
11 * are met: 11 * are met:
12 * 1. Redistributions of source code must retain the above copyright 12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer. 13 * notice, this list of conditions and the following disclaimer.
14 * 2. Redistributions in binary form must reproduce the above copyright 14 * 2. Redistributions in binary form must reproduce the above copyright
@@ -151,14 +151,20 @@ HashSet_Add(HashSet *set, const char *ke @@ -151,14 +151,20 @@ HashSet_Add(HashSet *set, const char *ke
151{ 151{
152 Boolean isNew; 152 Boolean isNew;
153 153
154 (void)HashTable_CreateEntry(&set->tbl, key, &isNew); 154 (void)HashTable_CreateEntry(&set->tbl, key, &isNew);
155 return isNew; 155 return isNew;
156} 156}
157 157
158MAKE_INLINE Boolean 158MAKE_INLINE Boolean
159HashSet_Contains(HashSet *set, const char *key) 159HashSet_Contains(HashSet *set, const char *key)
160{ 160{
161 return HashTable_FindEntry(&set->tbl, key) != NULL; 161 return HashTable_FindEntry(&set->tbl, key) != NULL;
162} 162}
163 163
 164MAKE_INLINE void
 165HashIter_InitSet(HashIter *hi, HashSet *set)
 166{
 167 HashIter_Init(hi, &set->tbl);
 168}
 169
164#endif /* MAKE_HASH_H */ 170#endif /* MAKE_HASH_H */