[Tizen] Fix calculation of method count for modules
authorGleb Balykov <g.balykov@samsung.com>
Wed, 22 Jun 2022 19:33:48 +0000 (22:33 +0300)
committerGleb Balykov <g.balykov@samsung.com>
Tue, 27 Sep 2022 12:50:22 +0000 (15:50 +0300)
This was a bit out of sync with the way runtime increments methodCount in MulticoreJitRecorder::EncodeModule.
Value of methodCount for module is not used in runtime, but anyway this is a bug and merge of module with itself
without this patch produces different sha256 because counters did not match. After this patch sha256 match.

src/coreclr/tools/mcj-edit/mcj-edit.py

index 99db99d..e0b3ade 100644 (file)
@@ -1399,9 +1399,9 @@ class IType(ABC):
     def updateModuleIndex(self, moduleIndexMap):
         pass
 
-    # Get all module indexes used in related types
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times
     @abstractmethod
-    def getAllModuleIndexes(self):
+    def getAllNonUniqueRefModuleIndexes(self):
         pass
 
     # Copy type
@@ -1445,8 +1445,8 @@ class TypeSimple(IType):
     def getElementKind(self):
         return self._elementKind
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times
+    def getAllNonUniqueRefModuleIndexes(self):
         return []
 
     # Update all module indexes according to map old_index->new_index
@@ -1537,8 +1537,8 @@ class TypeToken(IType):
     def getTypeToken(self):
         return self._typeToken
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times
+    def getAllNonUniqueRefModuleIndexes(self):
         return [self._moduleIndex]
 
     # Update all module indexes according to map old_index->new_index
@@ -1628,9 +1628,9 @@ class TypeParamType(IType):
     def getParamType(self):
         return self._paramType
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
-        return self._paramType.getAllModuleIndexes()
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times
+    def getAllNonUniqueRefModuleIndexes(self):
+        return self._paramType.getAllNonUniqueRefModuleIndexes()
 
     # Update all module indexes according to map old_index->new_index
     def updateModuleIndex(self, moduleIndexMap):
@@ -1718,9 +1718,9 @@ class TypeArray(IType):
     def getRank(self):
         return self._rank
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
-        return self._arrayElementType.getAllModuleIndexes()
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times
+    def getAllNonUniqueRefModuleIndexes(self):
+        return self._arrayElementType.getAllNonUniqueRefModuleIndexes()
 
     # Update all module indexes according to map old_index->new_index
     def updateModuleIndex(self, moduleIndexMap):
@@ -1807,9 +1807,9 @@ class TypeSZArray(IType):
     def getArrayElementType(self):
         return self._arrayElementType
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
-        return self._arrayElementType.getAllModuleIndexes()
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times
+    def getAllNonUniqueRefModuleIndexes(self):
+        return self._arrayElementType.getAllNonUniqueRefModuleIndexes()
 
     # Update all module indexes according to map old_index->new_index
     def updateModuleIndex(self, moduleIndexMap):
@@ -1905,12 +1905,12 @@ class TypeGeneric(IType):
     def getInstArgs(self):
         return self._instArgs
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
-        indexes = self._genericBaseType.getAllModuleIndexes()
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times
+    def getAllNonUniqueRefModuleIndexes(self):
+        indexes = self._genericBaseType.getAllNonUniqueRefModuleIndexes()
         for i in self._instArgs:
-            indexes += i.getAllModuleIndexes()
-        return sorted(set(indexes))
+            indexes += i.getAllNonUniqueRefModuleIndexes()
+        return indexes
 
     # Update all module indexes according to map old_index->new_index
     def updateModuleIndex(self, moduleIndexMap):
@@ -2017,12 +2017,12 @@ class TypeFNPtr(IType):
     def getRetAndArgs(self):
         return self._retAndArgs
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times
+    def getAllNonUniqueRefModuleIndexes(self):
         indexes = []
         for i in self._retAndArgs:
-            indexes += i.getAllModuleIndexes()
-        return sorted(set(indexes))
+            indexes += i.getAllNonUniqueRefModuleIndexes()
+        return indexes
 
     # Update all module indexes according to map old_index->new_index
     def updateModuleIndex(self, moduleIndexMap):
@@ -2149,14 +2149,26 @@ class GenericMethod:
     def getMethodInstArgs(self):
         return self._methodInstArgs
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
-        indexes = [self._moduleIndex]
-        indexes += self._typeHandle.getAllModuleIndexes()
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times,
+    # except for index of method module, which is included exactly once.
+    #
+    # Method module index should be unique because of the way how method count for modules is done in runtime:
+    # each module ref increments method count in module, except for refs to method module, which is considered only once
+    # (see usage of ELEMENT_TYPE_MODULE_ZAPSIG in zapsig.cpp)
+    def getAllRefModuleIndexes(self):
+        tmpindexes = []
+        tmpindexes += self._typeHandle.getAllNonUniqueRefModuleIndexes()
         if (not self._methodInstArgs is None):
             for i in self._methodInstArgs:
-                indexes += i.getAllModuleIndexes()
-        return sorted(set(indexes))
+                tmpindexes += i.getAllNonUniqueRefModuleIndexes()
+
+        indexes = []
+        for i in tmpindexes:
+            if (i != self._moduleIndex):
+                indexes.append(i)
+        indexes.append(self._moduleIndex)
+
+        return indexes
 
     # Update all module indexes according to map old_index->new_index
     def updateModuleIndex(self, moduleIndexMap):
@@ -2726,8 +2738,9 @@ class Info(ABC):
     def getModuleIndex(self):
         pass
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times,
+    # except for index of module in info directly, which is included exactly once
+    def getAllRefModuleIndexes(self):
         pass
 
     # Check if info is related to generic method
@@ -2797,8 +2810,9 @@ class InfoModuleDependency(Info):
     def getModuleIndex(self):
         return self._moduleIndex
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times,
+    # except for index of module in info directly, which is included exactly once
+    def getAllRefModuleIndexes(self):
         return [self._moduleIndex]
 
     # Get module load level
@@ -2984,8 +2998,9 @@ class InfoNonGenericMethod(Info):
     def getModuleIndex(self):
         return self._moduleIndex
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times,
+    # except for index of module in info directly, which is included exactly once
+    def getAllRefModuleIndexes(self):
         return [self._moduleIndex]
 
     # Get method flags
@@ -3195,9 +3210,10 @@ class InfoGenericMethod(Info): # pylint: disable=too-many-public-methods
     def getModuleIndex(self):
         return self._methodHandle.getModuleIndex()
 
-    # Get all module indexes used in related types
-    def getAllModuleIndexes(self):
-        return self._methodHandle.getAllModuleIndexes()
+    # Get all non-unique indexes of referenced modules used in related types, each index may be included multiple times,
+    # except for index of module in info directly, which is included exactly once
+    def getAllRefModuleIndexes(self):
+        return self._methodHandle.getAllRefModuleIndexes()
 
     # Get method flags
     def getMethodFlags(self):
@@ -3472,7 +3488,7 @@ class MCJProfile: # pylint: disable=too-many-public-methods
             raise ProfileInconsistencyError()
 
         for info in self._moduleOrMethodInfo:
-            indexes = info.getAllModuleIndexes()
+            indexes = set(info.getAllRefModuleIndexes())
             for i in indexes:
                 if (i >= len(self._modules)):
                     raise InternalError()
@@ -3757,7 +3773,7 @@ class MCJProfile: # pylint: disable=too-many-public-methods
 
         for index, info in enumerate(self._moduleOrMethodInfo):
             if (info.isMethodInfo()):
-                indexes = info.getAllModuleIndexes()
+                indexes = set(info.getAllRefModuleIndexes())
 
                 for i in indexes:
                     if (not moduleMap[cIdxSys][i]):
@@ -3827,7 +3843,7 @@ class MCJProfile: # pylint: disable=too-many-public-methods
 
             for info in moduleOrMethodInfo[index]:
                 if (info.isMethodInfo()):
-                    indexes = info.getAllModuleIndexes()
+                    indexes = info.getAllRefModuleIndexes()
                     for i in indexes:
                         moduleRecord = modules[index][i].getModuleRecord()
                         count = moduleRecord.getJitMethodCount()
@@ -3969,7 +3985,7 @@ class MCJProfile: # pylint: disable=too-many-public-methods
             if (info.isMethodInfo()):
                 methodCount += 1
 
-                indexes = info.getAllModuleIndexes()
+                indexes = info.getAllRefModuleIndexes()
                 for i in indexes:
                     moduleRecord = self._modules[i].getModuleRecord()
                     count = moduleRecord.getJitMethodCount()
@@ -4304,84 +4320,93 @@ class CLI:
                 systemModules[i] = moduleName.rstrip("\n")
 
             for filepath in self._args.input:
+                isCorrect = True
+
                 mcjProfile = MCJProfile.readFromFile(filepath)
-                mcjProfileApp, mcjProfileSys = mcjProfile.split(systemModules)
 
-                prevMergedAppFirst = mcjProfile
-                prevMergedSysFirst = mcjProfile
-                prevSplitAppFirstApp = mcjProfileApp
-                prevSplitAppFirstSys = mcjProfileSys
-                prevSplitSysFirstApp = mcjProfileApp
-                prevSplitSysFirstSys = mcjProfileSys
+                mcjProfile2 = mcjProfile.copy()
+                mcjProfile2.merge(mcjProfile)
 
-                isCorrect = True
-                depthCheck = 1
+                if (mcjProfile2 != mcjProfile):
+                    isCorrect = False
 
-                # Note: first split&merge won't match because order changes, but it stabilizes on 2nd merge
-                for depth in range(1,5):
-                    # Merge two prev profiles
-                    mergedAppFirst = prevSplitAppFirstApp.copy()
-                    mergedAppFirst.merge(prevSplitAppFirstSys)
+                if (isCorrect):
+                    mcjProfileApp, mcjProfileSys = mcjProfile.split(systemModules)
 
-                    mergedSysFirst = prevSplitSysFirstSys.copy()
-                    mergedSysFirst.merge(prevSplitSysFirstApp)
+                    prevMergedAppFirst = mcjProfile
+                    prevMergedSysFirst = mcjProfile
+                    prevSplitAppFirstApp = mcjProfileApp
+                    prevSplitAppFirstSys = mcjProfileSys
+                    prevSplitSysFirstApp = mcjProfileApp
+                    prevSplitSysFirstSys = mcjProfileSys
 
-                    if (depth > depthCheck
-                        and (mergedAppFirst != prevMergedAppFirst or mergedSysFirst != prevMergedSysFirst)):
-                        isCorrect = False
-                        break
+                    depthCheck = 1
 
-                    prevMergedAppFirst = mergedAppFirst
-                    prevMergedSysFirst = mergedSysFirst
+                    # Note: first split&merge won't match because order changes, but it stabilizes on 2nd merge
+                    for depth in range(1,5):
+                        # Merge two prev profiles
+                        mergedAppFirst = prevSplitAppFirstApp.copy()
+                        mergedAppFirst.merge(prevSplitAppFirstSys)
 
-                    mergedAppFirst2 = mergedAppFirst.copy()
-                    mergedAppFirst2.merge(mergedSysFirst)
+                        mergedSysFirst = prevSplitSysFirstSys.copy()
+                        mergedSysFirst.merge(prevSplitSysFirstApp)
 
-                    mergedSysFirst2 = mergedSysFirst.copy()
-                    mergedSysFirst2.merge(mergedAppFirst)
+                        if (depth > depthCheck
+                            and (mergedAppFirst != prevMergedAppFirst or mergedSysFirst != prevMergedSysFirst)):
+                            isCorrect = False
+                            break
 
-                    if (mergedAppFirst2 != mergedAppFirst or mergedSysFirst2 != mergedSysFirst):
-                        isCorrect = False
-                        break
+                        prevMergedAppFirst = mergedAppFirst
+                        prevMergedSysFirst = mergedSysFirst
 
-                    # Split cur profiles
-                    splitAppFirstApp, splitAppFirstSys = mergedAppFirst.split(systemModules)
-                    splitSysFirstApp, splitSysFirstSys = mergedSysFirst.split(systemModules)
+                        mergedAppFirst2 = mergedAppFirst.copy()
+                        mergedAppFirst2.merge(mergedSysFirst)
 
-                    if (depth > depthCheck
-                        and (splitAppFirstApp != prevSplitAppFirstApp or splitAppFirstSys != prevSplitAppFirstSys
-                             or splitSysFirstApp != prevSplitSysFirstApp or splitSysFirstSys != prevSplitSysFirstSys)):
-                        isCorrect = False
-                        break
+                        mergedSysFirst2 = mergedSysFirst.copy()
+                        mergedSysFirst2.merge(mergedAppFirst)
 
-                    prevSplitAppFirstApp = splitAppFirstApp
-                    prevSplitAppFirstSys = splitAppFirstSys
-                    prevSplitSysFirstApp = splitSysFirstApp
-                    prevSplitSysFirstSys = splitSysFirstSys
+                        if (mergedAppFirst2 != mergedAppFirst or mergedSysFirst2 != mergedSysFirst):
+                            isCorrect = False
+                            break
 
-                    splitAppFirstApp2, splitAppFirstSys2 = splitAppFirstApp.split(systemModules)
+                        # Split cur profiles
+                        splitAppFirstApp, splitAppFirstSys = mergedAppFirst.split(systemModules)
+                        splitSysFirstApp, splitSysFirstSys = mergedSysFirst.split(systemModules)
 
-                    if (splitAppFirstApp2 != splitAppFirstApp):
-                        isCorrect = False
-                        break
+                        if (depth > depthCheck
+                            and (splitAppFirstApp != prevSplitAppFirstApp or splitAppFirstSys != prevSplitAppFirstSys
+                                 or splitSysFirstApp != prevSplitSysFirstApp or splitSysFirstSys != prevSplitSysFirstSys)):
+                            isCorrect = False
+                            break
 
-                    splitAppFirstApp2, splitAppFirstSys2 = splitAppFirstSys.split(systemModules)
+                        prevSplitAppFirstApp = splitAppFirstApp
+                        prevSplitAppFirstSys = splitAppFirstSys
+                        prevSplitSysFirstApp = splitSysFirstApp
+                        prevSplitSysFirstSys = splitSysFirstSys
 
-                    if (splitAppFirstSys2 != splitAppFirstSys):
-                        isCorrect = False
-                        break
+                        splitAppFirstApp2, splitAppFirstSys2 = splitAppFirstApp.split(systemModules)
 
-                    splitSysFirstApp2, splitSysFirstSys2 = splitSysFirstApp.split(systemModules)
+                        if (splitAppFirstApp2 != splitAppFirstApp):
+                            isCorrect = False
+                            break
 
-                    if (splitSysFirstApp2 != splitSysFirstApp):
-                        isCorrect = False
-                        break
+                        splitAppFirstApp2, splitAppFirstSys2 = splitAppFirstSys.split(systemModules)
 
-                    splitSysFirstApp2, splitSysFirstSys2 = splitSysFirstSys.split(systemModules)
+                        if (splitAppFirstSys2 != splitAppFirstSys):
+                            isCorrect = False
+                            break
 
-                    if (splitSysFirstSys2 != splitSysFirstSys):
-                        isCorrect = False
-                        break
+                        splitSysFirstApp2, splitSysFirstSys2 = splitSysFirstApp.split(systemModules)
+
+                        if (splitSysFirstApp2 != splitSysFirstApp):
+                            isCorrect = False
+                            break
+
+                        splitSysFirstApp2, splitSysFirstSys2 = splitSysFirstSys.split(systemModules)
+
+                        if (splitSysFirstSys2 != splitSysFirstSys):
+                            isCorrect = False
+                            break
 
                 if (isCorrect):
                     print("Split-merge self test passed for " + filepath)