Changeset 108863 in vbox for trunk/src/VBox/VMM
- Timestamp:
- Apr 6, 2025 2:25:04 AM (5 weeks ago)
- svn:sync-xref-src-repo-rev:
- 168313
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/VBox/VMM/VMMAll/target-armv8/bsd-spec-analyze.py
r108862 r108863 38 38 import collections; 39 39 import datetime; 40 import io; 40 41 import json; 41 42 import operator; … … 45 46 import tarfile; 46 47 import traceback; 48 # profiling: 47 49 import cProfile; 50 import pstats 48 51 49 52 … … 777 780 # 778 781 779 class MaskIterator1(object): 780 """ Helper class for DecoderNode.constructNextLevel(). """ 781 782 ## Maximum number of mask sub-parts. 783 # Lower number means fewer instructions required to convert it into an index. 784 kcMaxMaskParts = 3 785 786 def __init__(self, fMask, cMaxTableSizeInBits, dDictDoneAlready): 787 self.fMask = fMask; 788 self.afVariations = self.variationsForMask(fMask, cMaxTableSizeInBits, dDictDoneAlready); 789 790 def __iter__(self): 791 ## @todo make this more dynamic... 792 return iter(self.afVariations); 793 794 @staticmethod 795 def variationsForMask(fMask, cMaxTableSizeInBits, dDictDoneAlready): 796 dBits = collections.OrderedDict(); 797 for iBit in range(32): 798 if fMask & (1 << iBit): 799 dBits[iBit] = 1; 800 801 if len(dBits) > cMaxTableSizeInBits or fMask in dDictDoneAlready: 802 aiRet = []; 803 elif len(dBits) > 0: 804 aaiMaskAlgo = DecoderNode.compactMaskAsList(list(dBits)); 805 if len(aaiMaskAlgo) <= MaskIterator1.kcMaxMaskParts: 806 dDictDoneAlready[fMask] = 1; 807 aiRet = [(fMask, list(dBits), aaiMaskAlgo)]; 808 else: 809 aiRet = []; 810 else: 811 return []; 812 813 def recursive(fMask, dBits): 814 if len(dBits) > 0 and fMask not in dDictDoneAlready: 815 if len(dBits) <= cMaxTableSizeInBits: 816 aaiMaskAlgo = DecoderNode.compactMaskAsList(list(dBits)); 817 if len(aaiMaskAlgo) <= MaskIterator1.kcMaxMaskParts: 818 dDictDoneAlready[fMask] = 1; 819 aiRet.append((fMask, list(dBits), aaiMaskAlgo)); 820 if len(dBits) > 1: 821 dChildBits = collections.OrderedDict(dBits); 822 for iBit in dBits.keys(): 823 del dChildBits[iBit]; 824 recursive(fMask & ~(1 << iBit), dChildBits) 825 826 if len(dBits) > 1: 827 dChildBits = collections.OrderedDict(dBits); 828 for iBit in dBits.keys(): 829 del dChildBits[iBit]; 830 recursive(fMask & ~(1 << iBit), dChildBits) 831 832 print("debug: fMask=%#x len(aiRet)=%d dDictDoneAlready=%d" % (fMask, len(aiRet), len(dDictDoneAlready))); 833 return aiRet; 834 835 class MaskIterator2(object): 836 """ Helper class for DecoderNode.constructNextLevel(). """ 837 838 ## Maximum number of mask sub-parts. 839 # Lower number means fewer instructions required to convert it into an index. 840 kcMaxMaskParts = 3 841 842 class StackEntry(object): 843 def __init__(self, fMask, aiBits): 844 self.fMask = fMask; 845 self.aiBits = aiBits; 846 self.iCur = -1; 847 #fTmp = 0; 848 #for iBit in aiBits: 849 # fTmp |= 1 << iBit; 850 #assert fTmp == fMask, 'fTmp=%#x fMask=%#x aiBits=%s' % (fTmp, fMask, aiBits); 851 852 def __init__(self, fMask, cMaxTableSizeInBits, dDictDoneAlready): 853 self.fMask = fMask; 854 self.cMaxTableSizeInBits = cMaxTableSizeInBits; 855 self.dDictDoneAlready = dDictDoneAlready; 856 self.cReturned = 0; 857 self.cLoops = 0; 858 859 dBits = collections.OrderedDict(); 860 for iBit in range(32): 861 if fMask & (1 << iBit): 862 dBits[iBit] = 1; 863 self.oTop = self.StackEntry(fMask, list(dBits)); 864 self.aoStack = []; 865 866 def __iter__(self): 867 return self; 868 869 def __next__(self): 870 oTop = self.oTop; 871 while oTop: 872 self.cLoops += 1 873 iCur = oTop.iCur; 874 cCurBits = len(oTop.aiBits); 875 if iCur < 0: 876 # Return self if appropriate 877 if ( 0 < cCurBits < self.cMaxTableSizeInBits 878 and oTop.fMask not in self.dDictDoneAlready): 879 aaiMaskAlgo = []#DecoderNode.compactMaskAsList(oTop.aiBits); 880 if len(aaiMaskAlgo) <= MaskIterator2.kcMaxMaskParts: 881 oTop.iCur = 0; 882 self.dDictDoneAlready[oTop.fMask] = 1; 883 self.cReturned += 1; 884 #return (oTop.fMask, oTop.aiBits, aaiMaskAlgo); 885 iCur = 0; 886 887 if iCur < cCurBits and cCurBits > 1: 888 # push 889 oTop.iCur = iCur + 1; 890 self.aoStack.append(oTop); 891 oTop = self.StackEntry(oTop.fMask & ~(1 << oTop.aiBits[iCur]), oTop.aiBits[:iCur] + oTop.aiBits[iCur + 1:]); 892 self.oTop = oTop; 893 else: 894 # pop. 895 oTop.iCur = 0xff; 896 oTop = self.aoStack.pop() if self.aoStack else None; 897 self.oTop = oTop; 898 # Done; 899 print('MaskIterator2: fMask=%#x -> %u items returned; %u loops' % (self.fMask, self.cReturned, self.cLoops)); 900 raise StopIteration; 901 902 class MaskIterator(object): 903 """ Helper class for DecoderNode.constructNextLevel(). """ 904 905 ## Maximum number of mask sub-parts. 906 # Lower number means fewer instructions required to convert it into an index. 907 # This is implied by the code in compileMaskCompactorLimited. 908 kcMaxMaskParts = 3 909 910 def __init__(self, fMask, cMaxTableSizeInBits, dDictDoneAlready): 911 self.fMask = fMask; 912 self.aaiAlgo = MaskIterator.compileMaskCompactor(fMask); 913 self.fCompactMask = DecoderNode.toIndexByMask(fMask, self.aaiAlgo); 914 #print('debug: fMask=%#x -> fCompactMask=%#x aaiAlgo=%s' % (fMask, self.fCompactMask, self.aaiAlgo)); 915 self.fnExpandMask = DecoderNode.compactDictAlgoToLambdaRev(self.aaiAlgo); 916 self.cMaxTableSizeInBits = cMaxTableSizeInBits; 917 self.dDictDoneAlready = dDictDoneAlready; 918 self.cReturned = 0; 919 920 @staticmethod 921 def compileMaskCompactor(fMask): 782 class MaskZipper(object): 783 """ 784 This is mainly a class for putting static methods relating to mask 785 packing and unpack. 786 """ 787 788 def __init__(self): 789 pass; 790 791 @staticmethod 792 def compileAlgo(fMask): 922 793 """ 923 794 Returns an with instructions for extracting the bits from the mask into … … 949 820 950 821 @staticmethod 951 def compile MaskCompactorLimited(fMask):952 """ 953 Version of compile MaskCompactorthat returns an empty list if there are822 def compileAlgoLimited(fMask): 823 """ 824 Version of compileAlgo that returns an empty list if there are 954 825 more than three sections. 955 826 """ … … 1003 874 1004 875 @staticmethod 1005 def maskCompactorAlgoToBitList(aaiAlgo): 876 def compileAlgoFromList(aiOrderedBits): 877 """ 878 Returns an with instructions for extracting the bits from the mask into 879 a compacted form. Each array entry is an array/tuple of source bit [0], 880 destination bit [1], and mask (shifted to pos 0) [2]. 881 """ 882 aaiAlgo = []; 883 iDstBit = 0; 884 i = 0; 885 while i < len(aiOrderedBits): 886 iSrcBit = aiOrderedBits[i]; 887 cCount = 1; 888 i += 1; 889 while i < len(aiOrderedBits) and aiOrderedBits[i] == iSrcBit + cCount: 890 cCount += 1; 891 i += 1; 892 aaiAlgo.append([iSrcBit, iDstBit, (1 << cCount) - 1]) 893 iDstBit += cCount; 894 return aaiAlgo; 895 896 @staticmethod 897 def algoToBitList(aaiAlgo): 1006 898 aiRet = []; 1007 899 for iSrcBit, _, fMask in aaiAlgo: … … 1010 902 return aiRet; 1011 903 904 @staticmethod 905 def zipMask(uValue, aaiAlgo): 906 idxRet = 0; 907 for iSrcBit, iDstBit, fMask in aaiAlgo: 908 idxRet |= ((uValue >> iSrcBit) & fMask) << iDstBit; 909 return idxRet; 910 911 @staticmethod 912 def __zipMask1(uValue, aaiAlgo): 913 iSrcBit, _, fMask = aaiAlgo[0]; 914 return (uValue >> iSrcBit) & fMask; 915 916 @staticmethod 917 def __zipMask2(uValue, aaiAlgo): 918 iSrcBit0, _, fMask0 = aaiAlgo[0]; 919 iSrcBit1, iDstBit1, fMask1 = aaiAlgo[1]; 920 return ((uValue >> iSrcBit0) & fMask0) | (((uValue >> iSrcBit1) & fMask1) << iDstBit1); 921 922 @staticmethod 923 def __zipMask3(uValue, aaiAlgo): 924 iSrcBit0, _, fMask0 = aaiAlgo[0]; 925 iSrcBit1, iDstBit1, fMask1 = aaiAlgo[1]; 926 iSrcBit2, iDstBit2, fMask2 = aaiAlgo[2]; 927 return ((uValue >> iSrcBit0) & fMask0) \ 928 | (((uValue >> iSrcBit1) & fMask1) << iDstBit1) \ 929 | (((uValue >> iSrcBit2) & fMask2) << iDstBit2); 930 931 @staticmethod 932 def algoToZipLambda(aaiAlgo, fAlgoMask, fCompileIt = True): 933 assert aaiAlgo; 934 if not fCompileIt: 935 if len(aaiAlgo) == 1: return MaskZipper.__zipMask1; 936 if len(aaiAlgo) == 2: return MaskZipper.__zipMask2; 937 if len(aaiAlgo) == 3: return MaskZipper.__zipMask3; 938 return MaskZipper.zipMask; 939 # Compile it: 940 sBody = ''; 941 for iSrcBit, iDstBit, fMask in aaiAlgo: 942 if sBody: 943 sBody += ' | '; 944 assert iSrcBit >= iDstBit; 945 if iDstBit == 0: 946 if iSrcBit == 0: 947 sBody += '(uValue & %#x)' % (fMask,); 948 else: 949 sBody += '((uValue >> %u) & %#x)' % (iSrcBit, fMask); 950 else: 951 sBody += '((uValue >> %u) & %#x)' % (iSrcBit - iDstBit, fMask << iDstBit); 952 _ = fAlgoMask 953 #sFn = 'zipMaskCompiled_%#010x' % (fAlgoMask,); 954 #sFn = 'zipMaskCompiled'; 955 #dTmp = {}; 956 #exec('def %s(uValue,_): return %s' % (sFn, sBody), globals(), dTmp); 957 #return dTmp[sFn]; 958 return eval('lambda uValue,_: ' + sBody); 959 960 @staticmethod 961 def unzipMask(uValue, aaiAlgo): 962 fRet = 0; 963 for iSrcBit, iDstBit, fMask in aaiAlgo: 964 fRet |= ((uValue >> iDstBit) & fMask) << iSrcBit; 965 return fRet; 966 967 @staticmethod 968 def __unzipMask1(uValue, aaiAlgo): 969 return uValue << aaiAlgo[0][0]; 970 971 @staticmethod 972 def __unzipMask2(uValue, aaiAlgo): 973 iSrcBit0, _, fMask0 = aaiAlgo[0]; 974 iSrcBit1, iDstBit1, fMask1 = aaiAlgo[1]; 975 return ((uValue & fMask0) << iSrcBit0) | (((uValue >> iDstBit1) & fMask1) << iSrcBit1); 976 977 @staticmethod 978 def __unzipMask3(uValue, aaiAlgo): 979 iSrcBit0, _, fMask0 = aaiAlgo[0]; 980 iSrcBit1, iDstBit1, fMask1 = aaiAlgo[1]; 981 iSrcBit2, iDstBit2, fMask2 = aaiAlgo[2]; 982 return ((uValue & fMask0) << iSrcBit0) \ 983 | (((uValue >> iDstBit1) & fMask1) << iSrcBit1) \ 984 | (((uValue >> iDstBit2) & fMask2) << iSrcBit2); 985 986 @staticmethod 987 def algoToUnzipLambda(aaiAlgo, fAlgoMask, fCompileIt = True): 988 assert aaiAlgo; 989 if not fCompileIt: 990 if len(aaiAlgo) == 1: return MaskZipper.__unzipMask1; 991 if len(aaiAlgo) == 2: return MaskZipper.__unzipMask2; 992 if len(aaiAlgo) == 3: return MaskZipper.__unzipMask3; 993 return MaskZipper.unzipMask; 994 # Compile it: 995 sBody = ''; 996 for iSrcBit, iDstBit, fMask in aaiAlgo: 997 if sBody: 998 sBody += ' | '; 999 if iDstBit == 0: 1000 if iSrcBit == 0: 1001 sBody += '(uIdx & %#x)' % (fMask,); 1002 else: 1003 sBody += '((uIdx & %#x) << %u)' % (fMask, iSrcBit); 1004 else: 1005 sBody += '((uIdx << %u) & %#x)' % (iSrcBit - iDstBit, fMask << iSrcBit); 1006 1007 _ = fAlgoMask 1008 #dTmp = {}; 1009 #sFn = 'unzipMaskCompiled'; 1010 #sFn = 'unzipMaskCompiled_%#010x' % (fAlgoMask,); 1011 #exec('def %s(uIdx,_): return %s' % (sFn, sBody), globals(), dTmp); 1012 #return dTmp[sFn]; 1013 return eval('lambda uIdx,_: ' + sBody); 1014 1015 1016 class MaskIterator(object): 1017 """ Helper class for DecoderNode.constructNextLevel(). """ 1018 1019 ## Maximum number of mask sub-parts. 1020 # Lower number means fewer instructions required to convert it into an index. 1021 # This is implied by the code in MaskZipper.compileAlgoLimited. 1022 kcMaxMaskParts = 3 1023 1024 def __init__(self, fMask, cMaxTableSizeInBits, dDictDoneAlready, fCompileIt = False): 1025 self.fMask = fMask; 1026 self.aaiAlgo = MaskZipper.compileAlgo(fMask); 1027 self.fCompactMask = MaskZipper.zipMask(fMask, self.aaiAlgo); 1028 #print('debug: fMask=%#x -> fCompactMask=%#x aaiAlgo=%s' % (fMask, self.fCompactMask, self.aaiAlgo)); 1029 self.fnExpandMask = MaskZipper.algoToUnzipLambda(self.aaiAlgo, fMask, fCompileIt); 1030 self.cMaxTableSizeInBits = cMaxTableSizeInBits; 1031 self.dDictDoneAlready = dDictDoneAlready; 1032 self.cReturned = 0; 1033 1012 1034 def __iter__(self): 1013 1035 return self; … … 1018 1040 cCurBits = fCompactMask.bit_count(); 1019 1041 if cCurBits <= self.cMaxTableSizeInBits: 1020 fMask = self.fnExpandMask(fCompactMask );1042 fMask = self.fnExpandMask(fCompactMask, self.aaiAlgo); 1021 1043 if fMask not in self.dDictDoneAlready: 1022 aaiMaskAlgo = Mask Iterator.compileMaskCompactorLimited(fMask);1044 aaiMaskAlgo = MaskZipper.compileAlgoLimited(fMask); 1023 1045 if aaiMaskAlgo: 1024 #assert aaiMaskAlgo == Mask Iterator.compileMaskCompactor(fMask), \1025 # '%s vs %s' % (aaiMaskAlgo, Mask Iterator.compileMaskCompactor(fMask));1046 #assert aaiMaskAlgo == MaskZipper.compileAlgo(fMask), \ 1047 # '%s vs %s' % (aaiMaskAlgo, MaskZipper.compileAlgo(fMask)); 1026 1048 self.dDictDoneAlready[fMask] = 1; 1027 1049 self.fCompactMask = fCompactMask - 1; 1028 1050 self.cReturned += 1; 1029 return (fMask, Mask Iterator.maskCompactorAlgoToBitList(aaiMaskAlgo), aaiMaskAlgo);1051 return (fMask, MaskZipper.algoToBitList(aaiMaskAlgo), aaiMaskAlgo); 1030 1052 fCompactMask -= 1; 1031 1053 self.fCompactMask = 0; … … 1077 1099 1078 1100 @staticmethod 1079 def compactMask(fMask):1080 """1081 Returns an with instructions for extracting the bits from the mask into1082 a compacted form. Each array entry is an array/tuple of source bit [0],1083 destination bit [1], and bit counts [2].1084 """1085 aaiAlgo = [];1086 iSrcBit = 0;1087 iDstBit = 0;1088 while fMask > 0:1089 # Skip leading zeros.1090 cSkip = (fMask & -fMask).bit_length() - 1;1091 assert (fMask & ((1 << cSkip) - 1)) == 0 and ((fMask >> cSkip) & 1), 'fMask=%#x cSkip=%d' % (fMask, cSkip)1092 iSrcBit += cSkip;1093 fMask >>= cSkip;1094 1095 # Calculate leading ones the same way.1096 cCount1 = (~fMask & -~fMask).bit_length() - 1;1097 cCount = 11098 fMask >>= 1;1099 while fMask & 1:1100 fMask >>= 1;1101 cCount += 11102 assert cCount1 == cCount;1103 aaiAlgo.append([iSrcBit, iDstBit, (1 << cCount) - 1])1104 iSrcBit += cCount;1105 iDstBit += cCount;1106 return aaiAlgo;1107 1108 @staticmethod1109 def compactMaskAsList(aiOrderedBits):1110 """1111 Returns an with instructions for extracting the bits from the mask into1112 a compacted form. Each array entry is an array/tuple of source bit [0],1113 destination bit [1], and mask (shifted to pos 0) [2].1114 """1115 aaiAlgo = [];1116 iDstBit = 0;1117 i = 0;1118 while i < len(aiOrderedBits):1119 iSrcBit = aiOrderedBits[i];1120 cCount = 1;1121 i += 1;1122 while i < len(aiOrderedBits) and aiOrderedBits[i] == iSrcBit + cCount:1123 cCount += 1;1124 i += 1;1125 aaiAlgo.append([iSrcBit, iDstBit, (1 << cCount) - 1])1126 iDstBit += cCount;1127 return aaiAlgo;1128 1129 @staticmethod1130 def compactDictAlgoToLambda(aaiAlgo):1131 assert aaiAlgo;1132 sBody = '';1133 for iSrcBit, iDstBit, fMask in aaiAlgo:1134 if sBody:1135 sBody += ' | ';1136 assert iSrcBit >= iDstBit;1137 if iDstBit == 0:1138 if iSrcBit == 0:1139 sBody += '(uValue & %#x)' % (fMask,);1140 else:1141 sBody += '((uValue >> %u) & %#x)' % (iSrcBit, fMask);1142 else:1143 sBody += '((uValue >> %u) & %#x)' % (iSrcBit - iDstBit, fMask << iDstBit);1144 return eval('lambda uValue: ' + sBody);1145 1146 @staticmethod1147 def compactDictAlgoToLambdaRev(aaiAlgo):1148 assert aaiAlgo;1149 sBody = '';1150 for iSrcBit, iDstBit, fMask in aaiAlgo:1151 if sBody:1152 sBody += ' | ';1153 if iDstBit == 0:1154 if iSrcBit == 0:1155 sBody += '(uIdx & %#x)' % (fMask,);1156 else:1157 sBody += '((uIdx & %#x) << %u)' % (fMask, iSrcBit);1158 else:1159 sBody += '((uIdx << %u) & %#x)' % (iSrcBit - iDstBit, fMask << iSrcBit);1160 return eval('lambda uIdx: ' + sBody);1161 1162 @staticmethod1163 def toIndexByMask(uValue, aaiAlgo):1164 idxRet = 0;1165 for iSrcBit, iDstBit, fMask in aaiAlgo:1166 idxRet |= ((uValue >> iSrcBit) & fMask) << iDstBit;1167 return idxRet;1168 1169 @staticmethod1170 1101 def popCount(uValue): 1171 1102 cBits = 0; … … 1194 1125 dMaskCounts[oInstr.fFixedMask & ~self.fCheckedMask] += 1; 1195 1126 assert 0 not in dMaskCounts or dMaskCounts[0] <= 1, \ 1196 'dMaskCounts=%s len(self.aoInstructions)=%s\n%s' % (dMaskCounts, len(self.aoInstructions), self.aoInstructions);1127 'dMaskCounts=%s len(self.aoInstructions)=%s\n%s' % (dMaskCounts, len(self.aoInstructions), self.aoInstructions); 1197 1128 1198 1129 ## Determine the max table size for the number of instructions we have. … … 1201 1132 # cInstructionsAsShift += 1; 1202 1133 #cMaxTableSizeInBits = self.kacMaxTableSizesInBits[cInstructionsAsShift]; 1134 1135 # 1136 # Whether to bother compiling the mask zip/unzip functions. 1137 # 1138 # The goal here is to keep the {built-in method builtins.eval} line far 1139 # away from top of the profiler stats, while at the same time keeping the 1140 # __zipMaskN and __unzipMaskN methods from taking up too much time. 1141 # 1142 fCompileMaskZipUnzip = len(self.aoInstructions) >= 12; 1203 1143 1204 1144 # … … 1225 1165 # (The MaskIterator skips masks that are too wide and too fragmented.) 1226 1166 # 1227 for fMask, dOrderedDictMask, aaiMaskToIdxAlgo in MaskIterator(fOrgMask, cMaxTableSizeInBits, dDictDoneAlready): 1167 for fMask, dOrderedDictMask, aaiMaskToIdxAlgo in MaskIterator(fOrgMask, cMaxTableSizeInBits, 1168 dDictDoneAlready, fCompileMaskZipUnzip): 1228 1169 #print('%s>>> fMask=%#010x dOrderedDictMask=%s aaiMaskToIdxAlgo=%s)...' 1229 1170 # % (sDbgPrefix, fMask, dOrderedDictMask, aaiMaskToIdxAlgo)); … … 1231 1172 1232 1173 # Compile the indexing/unindexing functions. 1233 fnToIndex = self.compactDictAlgoToLambda(aaiMaskToIdxAlgo);1234 fnFromIndex = self.compactDictAlgoToLambdaRev(aaiMaskToIdxAlgo);1174 fnToIndex = MaskZipper.algoToZipLambda(aaiMaskToIdxAlgo, fMask, fCompileMaskZipUnzip); 1175 fnFromIndex = MaskZipper.algoToUnzipLambda(aaiMaskToIdxAlgo, fMask, fCompileMaskZipUnzip); 1235 1176 1236 1177 # Create an temporary table empty with empty lists as entries. … … 1242 1183 # Insert the instructions into the temporary table. 1243 1184 for oInstr in self.aoInstructions: 1244 idx = fnToIndex(oInstr.fFixedValue); 1245 #assert idx == self.toIndexByMask(oInstr.fFixedValue & fMask, aaiMaskToIdxAlgo); 1246 #assert idx == fnToIndex(fnFromIndex(idx)); 1185 idx = fnToIndex(oInstr.fFixedValue, aaiMaskToIdxAlgo); 1186 #assert idx == MaskZipper.zipMask(oInstr.fFixedValue & fMask, aaiMaskToIdxAlgo); 1187 #assert idx == fnToIndex(fnFromIndex(idx, aaiMaskToIdxAlgo), aaiMaskToIdxAlgo); 1188 #assert idx == MaskZipper.zipMask(MaskZipper.unzipMask(idx, aaiMaskToIdxAlgo), aaiMaskToIdxAlgo); 1189 1247 1190 #print('%s%#010x -> %#05x %s' % (sDbgPrefix, oInstr.fFixedValue, idx, oInstr.sName)); 1248 1191 aoList = aaoTmp[idx]; … … 1255 1198 oChild = DecoderNode(aoInstrs, 1256 1199 self.fCheckedMask | fMask, 1257 self.fCheckedValue | fnFromIndex(idx ),1200 self.fCheckedValue | fnFromIndex(idx, aaiMaskToIdxAlgo), 1258 1201 self.uDepth + 1); 1259 1202 aoChildrenTmp.append(oChild); … … 1575 1518 rcExit = 2; 1576 1519 if oProfiler: 1577 oProfiler.print_stats(sort='tottime'); 1520 if not oProfiler: 1521 oProfiler.print_stats(sort='tottime'); 1522 else: 1523 oStringStream = io.StringIO(); 1524 pstats.Stats(oProfiler, stream = oStringStream).strip_dirs().sort_stats('tottime').print_stats(64); 1525 for iStatLine, sStatLine in enumerate(oStringStream.getvalue().split('\n')): 1526 if iStatLine > 20: 1527 asStatWords = sStatLine.split(); 1528 if asStatWords[1] in { '0.000', '0.001', '0.002', '0.003', '0.004', '0.005' }: 1529 break; 1530 print(sStatLine); 1578 1531 sys.exit(rcExit); 1579 1532
Note:
See TracChangeset
for help on using the changeset viewer.