Changeset 1017 in kBuild
- Timestamp:
- Jun 3, 2007 2:49:52 AM (18 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/kObjCache/kObjCache.c
r1016 r1017 38 38 #include <fcntl.h> 39 39 #include <limits.h> 40 #include <ctype.h> 40 41 #ifndef PATH_MAX 41 42 # define PATH_MAX _MAX_PATH /* windows */ … … 385 386 unsigned char ch = pszMD5[i]; 386 387 int x; 387 if ( ch - '0'<= 9)388 if ((unsigned char)(ch - '0') <= 9) 388 389 x = ch - '0'; 389 else if ( ch - 'a'<= 5)390 else if ((unsigned char)(ch - 'a') <= 5) 390 391 x = ch - 'a' + 10; 391 else if ( ch - 'A'<= 5)392 else if ((unsigned char)(ch - 'A') <= 5) 392 393 x = ch - 'A' + 10; 393 394 else … … 668 669 for (;;) 669 670 { 670 long cbRead = read(fds[0], psz, cbLeft );671 long cbRead = read(fds[0], psz, cbLeft - 1); 671 672 if (!cbRead) 672 673 break; … … 674 675 kObjCacheFatal(pEntry, "%s - read(%d,,%ld) failed: %s\n", pszMsg, fds[0], (long)cbLeft, strerror(errno)); 675 676 psz += cbRead; 677 *psz = '\0'; 676 678 cbLeft -= cbRead; 677 679 678 680 /* expand the buffer? */ 679 if ( !cbLeft)681 if (cbLeft <= 1) 680 682 { 681 683 size_t off = psz - *ppszOutput; … … 826 828 827 829 /** 828 * Worker for kObjCacheCompileIfNeeded that compares the 829 * precompiled output. 830 * Check whether the string is a '#line' statement. 831 * 832 * @returns 1 if it is, 0 if it isn't. 833 * @param psz The line to examin. 834 * @parma piLine Where to store the line number. 835 * @parma ppszFile Where to store the start of the filename. 836 */ 837 static int IsLineStatement(const char *psz, unsigned *piLine, const char **ppszFile) 838 { 839 unsigned iLine; 840 841 /* Expect a hash. */ 842 if (*psz++ != '#') 843 return 0; 844 845 /* Skip blanks between '#' and the line / number */ 846 while (*psz == ' ' || *psz == '\t') 847 psz++; 848 849 /* Skip the 'line' if present. */ 850 if (!strncmp(psz, "line", sizeof("line") - 1)) 851 psz += sizeof("line"); 852 853 /* Expect a line number now. */ 854 if ((unsigned char)(*psz - '0') > 9) 855 return 0; 856 iLine = 0; 857 do 858 { 859 iLine *= 10; 860 iLine += (*psz - '0'); 861 psz++; 862 } 863 while ((unsigned char)(*psz - '0') <= 9); 864 865 /* Expect one or more space now. */ 866 if (*psz != ' ' && *psz != '\t') 867 return 0; 868 do psz++; 869 while (*psz == ' ' || *psz == '\t'); 870 871 /* that's good enough. */ 872 *piLine = iLine; 873 *ppszFile = psz; 874 return 1; 875 } 876 877 878 /** 879 * Scan backwards for the previous #line statement. 880 * 881 * @returns The filename in the previous statement. 882 * @param pszStart Where to start. 883 * @param pszStop Where to stop. Less than pszStart. 884 * @param piLine The line number count to adjust. 885 */ 886 static const char *FindFileStatement(const char *pszStart, const char *pszStop, unsigned *piLine) 887 { 888 unsigned iLine = *piLine; 889 assert(pszStart >= pszStop); 890 while (pszStart >= pszStop) 891 { 892 if (*pszStart == '\n') 893 iLine++; 894 else if (*pszStart == '#') 895 { 896 unsigned iLineTmp; 897 const char *pszFile; 898 const char *psz = pszStart - 1; 899 while (psz >= pszStop && (*psz == ' ' || *psz =='\t')) 900 psz--; 901 if ( (psz < pszStop || *psz == '\n') 902 && IsLineStatement(pszStart, &iLineTmp, &pszFile)) 903 { 904 *piLine = iLine + iLineTmp - 1; 905 return pszFile; 906 } 907 } 908 pszStart--; 909 } 910 return NULL; 911 } 912 913 914 /** 915 * Worker for kObjCacheCompareOldAndNewOutput() that compares the 916 * precompiled output using a fast but not very good method. 830 917 * 831 918 * @returns 1 if matching, 0 if not matching. … … 833 920 * The entry is not updated in any way. 834 921 */ 835 static int kObjCacheCompareOldAndNewOutput(PCKOBJCACHE pEntry) 922 static int kObjCacheCompareFast(PCKOBJCACHE pEntry) 923 { 924 const char * psz1 = pEntry->pszNewCppMapping; 925 const char * const pszEnd1 = psz1 + pEntry->cbNewCpp; 926 const char * psz2 = pEntry->pszOldCppMapping; 927 const char * const pszEnd2 = psz2 + pEntry->cbOldCpp; 928 929 assert(*pszEnd1 == '\0'); 930 assert(*pszEnd2 == '\0'); 931 932 /* 933 * Iterate block by block and backtrack when we find a difference. 934 */ 935 for (;;) 936 { 937 size_t cch = pszEnd1 - psz1; 938 if (cch > (size_t)(pszEnd2 - psz2)) 939 cch = pszEnd2 - psz2; 940 if (cch > 4096) 941 cch = 4096; 942 if ( cch 943 && !memcmp(psz1, psz2, cch)) 944 { 945 /* no differences */ 946 psz1 += cch; 947 psz2 += cch; 948 } 949 else 950 { 951 /* 952 * Pinpoint the difference exactly and the try find the start 953 * of that line. Then skip forward until we find something to 954 * work on that isn't spaces or #line statements. Since we 955 * might be skipping a few new empty headers, it is possible 956 * that we will omit this header from the dependencies when 957 * using VCC. But I think that's a reasonable trade off for 958 * a simple algorithm. 959 */ 960 const char *psz; 961 const char *pszMismatch1; 962 const char *pszFile1 = NULL; 963 unsigned iLine1 = 0; 964 const char *pszMismatch2; 965 const char *pszFile2 = NULL; 966 unsigned iLine2 = 0; 967 968 /* locate the difference. */ 969 while (cch >= 512 && !memcmp(psz1, psz2, 512)) 970 psz1 += 512, psz2 += 512, cch -= 512; 971 while (cch >= 64 && !memcmp(psz1, psz2, 64)) 972 psz1 += 64, psz2 += 64, cch -= 64; 973 while (*psz1 == *psz2 && cch > 0) 974 psz1++, psz2++, cch--; 975 976 /* locate the start of that line. */ 977 psz = psz1; 978 while ( psz > pEntry->pszNewCppMapping 979 && psz[-1] != '\n') 980 psz--; 981 psz2 -= (psz1 - psz); 982 pszMismatch2 = psz2; 983 pszMismatch1 = psz1 = psz; 984 985 /* Parse the 1st file line by line. */ 986 while (psz1 < pszEnd1) 987 { 988 if (*psz1 == '\n') 989 { 990 psz1++; 991 iLine1++; 992 } 993 else 994 { 995 psz = psz1; 996 while (isspace(*psz) && *psz != '\n') 997 psz++; 998 if (*psz == '\n') 999 { 1000 psz1 = psz + 1; 1001 iLine1++; 1002 } 1003 else if (*psz == '#' && IsLineStatement(psz, &iLine1, &pszFile1)) 1004 { 1005 psz1 = memchr(psz, '\n', pszEnd1 - psz); 1006 if (!psz1++) 1007 psz1 = pszEnd1; 1008 } 1009 else if (psz == pszEnd1) 1010 psz1 = psz; 1011 else /* found something that can be compared. */ 1012 break; 1013 } 1014 } 1015 1016 /* Ditto for the 2nd file. */ 1017 while (psz2 < pszEnd2) 1018 { 1019 if (*psz2 == '\n') 1020 { 1021 psz2++; 1022 iLine2++; 1023 } 1024 else 1025 { 1026 psz = psz2; 1027 while (isspace(*psz) && *psz != '\n') 1028 psz++; 1029 if (*psz == '\n') 1030 { 1031 psz2 = psz + 1; 1032 iLine2++; 1033 } 1034 else if (*psz == '#' && IsLineStatement(psz, &iLine2, &pszFile2)) 1035 { 1036 psz2 = memchr(psz, '\n', pszEnd2 - psz); 1037 if (!psz2++) 1038 psz2 = pszEnd2; 1039 } 1040 else if (psz == pszEnd2) 1041 psz2 = psz; 1042 else /* found something that can be compared. */ 1043 break; 1044 } 1045 } 1046 1047 /* Reaching the end of any of them means the return statement can decide. */ 1048 if ( psz1 == pszEnd1 1049 || psz2 == pszEnd2) 1050 break; 1051 1052 /* Match the current line. */ 1053 psz = memchr(psz1, '\n', pszEnd1 - psz1); 1054 if (!psz) 1055 psz = pszEnd1; 1056 cch = psz - psz1; 1057 if (psz2 + cch > pszEnd2) 1058 break; 1059 if (memcmp(psz1, psz2, cch)) 1060 break; 1061 1062 /* Check that we're at the same location now. */ 1063 if (!pszFile1) 1064 pszFile1 = FindFileStatement(pszMismatch1, pEntry->pszNewCppMapping, &iLine1); 1065 if (!pszFile2) 1066 pszFile2 = FindFileStatement(pszMismatch2, pEntry->pszOldCppMapping, &iLine2); 1067 if (pszFile1 && pszFile2) 1068 { 1069 if (iLine1 != iLine2) 1070 break; 1071 while (*pszFile1 == *pszFile2 && *pszFile1 != '\n' && *pszFile1) 1072 pszFile1++, pszFile2++; 1073 if (*pszFile1 != *pszFile2) 1074 break; 1075 } 1076 else if (pszFile1 || pszFile2) 1077 { 1078 assert(0); /* this shouldn't happen. */ 1079 break; 1080 } 1081 1082 /* Try align psz1 on 8 or 4 bytes so at least one of the buffers are aligned. */ 1083 psz1 += cch; 1084 psz2 += cch; 1085 if (cch >= ((uintptr_t)psz1 & 7)) 1086 { 1087 psz2 -= ((uintptr_t)psz1 & 7); 1088 psz1 -= ((uintptr_t)psz1 & 7); 1089 } 1090 else if (cch >= ((uintptr_t)psz1 & 3)) 1091 { 1092 psz2 -= ((uintptr_t)psz1 & 3); 1093 psz1 -= ((uintptr_t)psz1 & 3); 1094 } 1095 } 1096 } 1097 1098 return psz1 == pszEnd1 1099 && psz2 == pszEnd2; 1100 } 1101 1102 1103 /** 1104 * Worker for kObjCacheCompileIfNeeded that compares the 1105 * precompiled output. 1106 * 1107 * @returns 1 if matching, 0 if not matching. 1108 * @param pEntry The entry containing the names of the files to compare. 1109 * This will load the old cpp output (changing pszOldCppName and cbOldCpp). 1110 */ 1111 static int kObjCacheCompareOldAndNewOutput(PKOBJCACHE pEntry) 836 1112 { 837 1113 /** @todo do some quick but fancy comparing that determins whether code … … 839 1115 * has just been moved up/down a bit. The typical case is adding a new error 840 1116 * #define that doesn't influence the current compile job. */ 841 return 0; 1117 1118 /* 1119 * Load the old output. 1120 */ 1121 pEntry->pszOldCppMapping = ReadFileInDir(pEntry->pszOldCppName, pEntry->pszDir, &pEntry->cbOldCpp); 1122 if (!pEntry->pszOldCppMapping) 1123 { 1124 kObjCacheVerbose(pEntry, "failed to read old cpp file ('%s' in '%s'): %s\n", 1125 pEntry->pszOldCppName, pEntry->pszDir, strerror(errno)); 1126 return 0; 1127 } 1128 1129 /* 1130 * I may implement a more sophisticated alternative method later... maybe. 1131 */ 1132 //if () 1133 // return kObjCacheCompareBest(pEntry); 1134 return kObjCacheCompareFast(pEntry); 842 1135 } 843 1136 … … 983 1276 984 1277 /* 985 * Discard the old precompiled output it's no longer needed.s 986 */ 987 if (pEntry->pszOldCppName) 1278 * Discard the old precompiled output if it's no longer needed. 1279 */ 1280 if ( pEntry->pszOldCppName 1281 && ( !pEntry->fPiped 1282 || pEntry->fNeedCompiling)) 988 1283 { 989 1284 UnlinkFileInDir(pEntry->pszOldCppName, pEntry->pszDir); … … 1442 1737 */ 1443 1738 kObjCacheWrite(pEntry); 1444 //kObjCacheCleanup(pEntry);1445 1739 /* kObjCacheDestroy(pEntry); - don't bother */ 1446 1740 return 0; 1447 1741 } 1448 1742 1743 1744 /** @page kObjCache Benchmarks. 1745 * 1746 * 2007-06-02 - 21-23:00: 1747 * Mac OS X debug -j 3 clobber build (rm -Rf out/darwin.x86/debug ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3): 1748 * real 10m26.077s 1749 * user 13m13.291s 1750 * sys 2m58.193s 1751 * 1752 * Mac OS X debug -j 3 depend build (touch include/iprt/err.h ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3): 1753 * real 3m55.275s 1754 * user 4m11.852s 1755 * sys 0m54.931s 1756 * 1757 * Mac OS X debug -j 3 cached clobber build (rm -Rf out/darwin.x86/debug ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 USE_KOBJCACHE=1): 1758 * real 11m42.513s 1759 * user 14m27.736s 1760 * sys 3m39.512s 1761 * 1762 * Mac OS X debug -j 3 cached clobber build (touch include/iprt/err.h ; sync ; svn diff ; sync ; sleep 1 ; time kmk -j 3 USE_KOBJCACHE=1): 1763 * real 2m24.712s real 2m10.909s 1764 * user 2m15.339s user 2m15.146s 1765 * sys 0m56.278s sys 0m55.591s 1766 * !Stuff is built three times here because of + instead of +| in footer.kmk! 1767 * 1768 */
Note:
See TracChangeset
for help on using the changeset viewer.