svf-tools 1.0.289 → 1.0.293
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +1 -0
- package/SVF-doxygen/html/html/AndersenHCD_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/AndersenHLCD_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/AndersenLCD_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/AndersenSCD_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/AndersenSFR_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/AndersenSFR_8h_source.html +2 -2
- package/SVF-doxygen/html/html/AndersenStat_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/AndersenWaveDiffWithType_8cpp_source.html +5 -5
- package/SVF-doxygen/html/html/AndersenWaveDiff_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/Andersen_8cpp_source.html +45 -29
- package/SVF-doxygen/html/html/Andersen_8h_source.html +50 -50
- package/SVF-doxygen/html/html/BasicTypes_8h_source.html +2 -2
- package/SVF-doxygen/html/html/ConditionalPT_8h_source.html +9 -9
- package/SVF-doxygen/html/html/ConsG_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/ContextDDA_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/ContextDDA_8h_source.html +1 -1
- package/SVF-doxygen/html/html/DDAClient_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/DDAStat_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/DDAVFSolver_8h_source.html +2 -2
- package/SVF-doxygen/html/html/DoubleFreeChecker_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/FSMPTA_8cpp_source.html +5 -5
- package/SVF-doxygen/html/html/FileChecker_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/FlowDDA_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/FlowDDA_8h_source.html +1 -1
- package/SVF-doxygen/html/html/FlowSensitiveStat_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/FlowSensitiveTBHC_8cpp_source.html +22 -22
- package/SVF-doxygen/html/html/FlowSensitive_8cpp_source.html +52 -32
- package/SVF-doxygen/html/html/FlowSensitive_8h_source.html +58 -55
- package/SVF-doxygen/html/html/ICFG_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/LeakChecker_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/LockResultValidator_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/MTAAnnotator_8cpp_source.html +4 -4
- package/SVF-doxygen/html/html/MTA_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/MemRegion_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/MutablePointsToDS_8h_source.html +2 -2
- package/SVF-doxygen/html/html/NodeIDAllocator_8cpp_source.html +64 -11
- package/SVF-doxygen/html/html/NodeIDAllocator_8h.html +5 -1
- package/SVF-doxygen/html/html/NodeIDAllocator_8h_source.html +52 -15
- package/SVF-doxygen/html/html/PAG_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/PersistentPointsToDS_8h_source.html +2 -2
- package/SVF-doxygen/html/html/PointerAnalysisImpl_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/PointerAnalysisImpl_8h_source.html +1 -1
- package/SVF-doxygen/html/html/PointerAnalysis_8h_source.html +1 -1
- package/SVF-doxygen/html/html/PointsTo_8cpp_source.html +34 -33
- package/SVF-doxygen/html/html/PointsTo_8h_source.html +32 -32
- package/SVF-doxygen/html/html/ProgSlice_8cpp_source.html +4 -12
- package/SVF-doxygen/html/html/ProgSlice_8h_source.html +33 -35
- package/SVF-doxygen/html/html/SVFGOPT_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/SVFG_8cpp_source.html +31 -36
- package/SVF-doxygen/html/html/SVFG_8h_source.html +19 -19
- package/SVF-doxygen/html/html/SVFUtil_8cpp_source.html +15 -7
- package/SVF-doxygen/html/html/SVFUtil_8h.html +3 -0
- package/SVF-doxygen/html/html/SVFUtil_8h_source.html +10 -8
- package/SVF-doxygen/html/html/SaberAnnotator_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/SaberSVFGBuilder_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/SrcSnkDDA_8cpp_source.html +2 -2
- package/SVF-doxygen/html/html/SymbolTableInfo_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/TypeBasedHeapCloning_8cpp_source.html +3 -3
- package/SVF-doxygen/html/html/VFG_8cpp_source.html +17 -11
- package/SVF-doxygen/html/html/VersionedFlowSensitiveStat_8cpp_source.html +1 -1
- package/SVF-doxygen/html/html/VersionedFlowSensitive_8cpp_source.html +51 -43
- package/SVF-doxygen/html/html/VersionedFlowSensitive_8h_source.html +34 -33
- package/SVF-doxygen/html/html/WPAPass_8cpp_source.html +5 -5
- package/SVF-doxygen/html/html/annotated.html +2 -1
- package/SVF-doxygen/html/html/classSVF_1_1AddrPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1AddrVFGNode-members.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1AddrVFGNode.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1Andersen-members.html +213 -212
- package/SVF-doxygen/html/html/classSVF_1_1Andersen.html +124 -72
- package/SVF-doxygen/html/html/classSVF_1_1AndersenBase.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1AndersenHCD-members.html +223 -222
- package/SVF-doxygen/html/html/classSVF_1_1AndersenHCD.html +36 -34
- package/SVF-doxygen/html/html/classSVF_1_1AndersenHLCD-members.html +232 -231
- package/SVF-doxygen/html/html/classSVF_1_1AndersenHLCD.html +21 -19
- package/SVF-doxygen/html/html/classSVF_1_1AndersenLCD-members.html +220 -219
- package/SVF-doxygen/html/html/classSVF_1_1AndersenLCD.html +38 -36
- package/SVF-doxygen/html/html/classSVF_1_1AndersenSCD-members.html +221 -220
- package/SVF-doxygen/html/html/classSVF_1_1AndersenSCD.html +11 -9
- package/SVF-doxygen/html/html/classSVF_1_1AndersenSFR-members.html +232 -231
- package/SVF-doxygen/html/html/classSVF_1_1AndersenSFR.html +6 -4
- package/SVF-doxygen/html/html/classSVF_1_1AndersenStat.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1AndersenWaveDiff-members.html +220 -219
- package/SVF-doxygen/html/html/classSVF_1_1AndersenWaveDiff.html +21 -19
- package/SVF-doxygen/html/html/classSVF_1_1AndersenWaveDiffWithType-members.html +227 -226
- package/SVF-doxygen/html/html/classSVF_1_1AndersenWaveDiffWithType.html +26 -24
- package/SVF-doxygen/html/html/classSVF_1_1ArgumentVFGNode.html +2 -3
- package/SVF-doxygen/html/html/classSVF_1_1BVDataPTAImpl.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1BinaryOPPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1BinaryOPVFGNode.html +3 -4
- package/SVF-doxygen/html/html/classSVF_1_1CallBlockNode.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1CallPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1CmpPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1CmpVFGNode.html +3 -4
- package/SVF-doxygen/html/html/classSVF_1_1ContextDDA.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1CopyPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1CopyVFGNode-members.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1CopyVFGNode.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1DDAStat.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1DDAVFSolver.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1DoubleFreeChecker.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1FIObjPN.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1FSMPTA-members.html +110 -107
- package/SVF-doxygen/html/html/classSVF_1_1FSMPTA.html +12 -4
- package/SVF-doxygen/html/html/classSVF_1_1FileChecker.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1FlowDDA.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1FlowSensitive-members.html +109 -106
- package/SVF-doxygen/html/html/classSVF_1_1FlowSensitive.html +286 -157
- package/SVF-doxygen/html/html/classSVF_1_1FlowSensitiveStat.html +30 -30
- package/SVF-doxygen/html/html/classSVF_1_1FlowSensitiveTBHC-members.html +121 -118
- package/SVF-doxygen/html/html/classSVF_1_1FlowSensitiveTBHC.html +36 -28
- package/SVF-doxygen/html/html/classSVF_1_1FormalOUTSVFGNode.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1FunptrDDAClient.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1GepObjPN.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1GepPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1GepVFGNode-members.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1GepVFGNode.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1GepValPN.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1InterPHIVFGNode.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1IntraBlockNode.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1IntraPHIVFGNode.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1LeakChecker.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1LoadPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1LoadVFGNode-members.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1LoadVFGNode.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1LockResultValidator.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1MRGenerator.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1MTA.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1MTAAnnotator.html +4 -4
- package/SVF-doxygen/html/html/classSVF_1_1MTASVFGBuilder.html +5 -5
- package/SVF-doxygen/html/html/classSVF_1_1MutablePTData.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator-members.html +11 -10
- package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator.html +74 -34
- package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator_1_1Clusterer-members.html +109 -0
- package/SVF-doxygen/html/html/classSVF_1_1NodeIDAllocator_1_1Clusterer.html +1188 -0
- package/SVF-doxygen/html/html/classSVF_1_1NormalGepPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1ObjPN.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1PHIVFGNode.html +3 -4
- package/SVF-doxygen/html/html/classSVF_1_1PersistentIncDFPTData.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1PersistentPTData.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1PointsTo.html +77 -66
- package/SVF-doxygen/html/html/classSVF_1_1PointsTo_1_1PointsToIterator.html +32 -26
- package/SVF-doxygen/html/html/classSVF_1_1ProgSlice-members.html +36 -37
- package/SVF-doxygen/html/html/classSVF_1_1ProgSlice.html +121 -153
- package/SVF-doxygen/html/html/classSVF_1_1RetBlockNode.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1RetPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1SVFFunction.html +4 -4
- package/SVF-doxygen/html/html/classSVF_1_1SVFG.html +49 -49
- package/SVF-doxygen/html/html/classSVF_1_1SVFGBuilder.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1SVFGOPT.html +9 -9
- package/SVF-doxygen/html/html/classSVF_1_1SaberAnnotator.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1SaberSVFGBuilder.html +6 -6
- package/SVF-doxygen/html/html/classSVF_1_1SrcSnkDDA.html +2 -2
- package/SVF-doxygen/html/html/classSVF_1_1StmtVFGNode-members.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1StmtVFGNode.html +8 -9
- package/SVF-doxygen/html/html/classSVF_1_1StorePE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1StoreVFGNode-members.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1StoreVFGNode.html +3 -3
- package/SVF-doxygen/html/html/classSVF_1_1SymbolTableInfo.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1TDForkPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1TDJoinPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1TypeBasedHeapCloning.html +4 -4
- package/SVF-doxygen/html/html/classSVF_1_1UnaryOPPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1UnaryOPVFGNode.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1VFGNode.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1ValPN.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1VariantGepPE.html +1 -1
- package/SVF-doxygen/html/html/classSVF_1_1VersionedFlowSensitive-members.html +132 -129
- package/SVF-doxygen/html/html/classSVF_1_1VersionedFlowSensitive.html +171 -116
- package/SVF-doxygen/html/html/classSVF_1_1VersionedFlowSensitiveStat.html +37 -37
- package/SVF-doxygen/html/html/classSVF_1_1WPAPass.html +5 -5
- package/SVF-doxygen/html/html/classes.html +62 -62
- package/SVF-doxygen/html/html/functions_b.html +10 -5
- package/SVF-doxygen/html/html/functions_c.html +36 -22
- package/SVF-doxygen/html/html/functions_d.html +12 -0
- package/SVF-doxygen/html/html/functions_e.html +9 -3
- package/SVF-doxygen/html/html/functions_f.html +21 -18
- package/SVF-doxygen/html/html/functions_func_c.html +19 -10
- package/SVF-doxygen/html/html/functions_func_d.html +3 -0
- package/SVF-doxygen/html/html/functions_func_e.html +3 -0
- package/SVF-doxygen/html/html/functions_func_g.html +16 -10
- package/SVF-doxygen/html/html/functions_func_p.html +6 -2
- package/SVF-doxygen/html/html/functions_func_r.html +7 -1
- package/SVF-doxygen/html/html/functions_func_t.html +3 -0
- package/SVF-doxygen/html/html/functions_g.html +15 -9
- package/SVF-doxygen/html/html/functions_l.html +10 -7
- package/SVF-doxygen/html/html/functions_n.html +21 -3
- package/SVF-doxygen/html/html/functions_o.html +16 -8
- package/SVF-doxygen/html/html/functions_p.html +23 -17
- package/SVF-doxygen/html/html/functions_r.html +13 -6
- package/SVF-doxygen/html/html/functions_s.html +9 -9
- package/SVF-doxygen/html/html/functions_t.html +18 -9
- package/SVF-doxygen/html/html/functions_type_d.html +3 -0
- package/SVF-doxygen/html/html/functions_v.html +3 -3
- package/SVF-doxygen/html/html/functions_vars_b.html +3 -0
- package/SVF-doxygen/html/html/functions_vars_c.html +3 -0
- package/SVF-doxygen/html/html/functions_vars_d.html +6 -0
- package/SVF-doxygen/html/html/functions_vars_e.html +3 -0
- package/SVF-doxygen/html/html/functions_vars_f.html +3 -0
- package/SVF-doxygen/html/html/functions_vars_l.html +3 -0
- package/SVF-doxygen/html/html/functions_vars_n.html +18 -0
- package/SVF-doxygen/html/html/functions_vars_o.html +6 -0
- package/SVF-doxygen/html/html/functions_vars_r.html +3 -0
- package/SVF-doxygen/html/html/functions_vars_t.html +6 -0
- package/SVF-doxygen/html/html/functions_w.html +8 -6
- package/SVF-doxygen/html/html/globals_f.html +3 -3
- package/SVF-doxygen/html/html/hierarchy.html +413 -412
- package/SVF-doxygen/html/html/menudata.js +2 -0
- package/SVF-doxygen/html/html/namespaceSVF.html +8 -8
- package/SVF-doxygen/html/html/namespaceSVF_1_1SVFUtil.html +47 -16
- package/SVF-doxygen/html/html/namespacemembers_func.html +17 -10
- package/SVF-doxygen/html/html/namespacemembers_h.html +76 -0
- package/SVF-doxygen/html/html/search/all_10.js +9 -8
- package/SVF-doxygen/html/html/search/all_12.js +5 -2
- package/SVF-doxygen/html/html/search/all_13.js +7 -7
- package/SVF-doxygen/html/html/search/all_14.js +8 -5
- package/SVF-doxygen/html/html/search/all_15.js +1 -1
- package/SVF-doxygen/html/html/search/all_16.js +1 -1
- package/SVF-doxygen/html/html/search/all_17.js +1 -1
- package/SVF-doxygen/html/html/search/all_2.js +1 -0
- package/SVF-doxygen/html/html/search/all_3.js +4 -0
- package/SVF-doxygen/html/html/search/all_4.js +4 -0
- package/SVF-doxygen/html/html/search/all_5.js +2 -0
- package/SVF-doxygen/html/html/search/all_6.js +4 -3
- package/SVF-doxygen/html/html/search/all_7.js +4 -2
- package/SVF-doxygen/html/html/search/all_8.js +1 -0
- package/SVF-doxygen/html/html/search/all_c.js +4 -3
- package/SVF-doxygen/html/html/search/all_d.js +1 -1
- package/SVF-doxygen/html/html/search/all_e.js +9 -4
- package/SVF-doxygen/html/html/search/all_f.js +4 -2
- package/SVF-doxygen/html/html/search/classes_2.js +1 -0
- package/SVF-doxygen/html/html/search/functions_10.js +1 -1
- package/SVF-doxygen/html/html/search/functions_11.js +1 -0
- package/SVF-doxygen/html/html/search/functions_2.js +2 -0
- package/SVF-doxygen/html/html/search/functions_3.js +1 -0
- package/SVF-doxygen/html/html/search/functions_4.js +1 -0
- package/SVF-doxygen/html/html/search/functions_6.js +4 -2
- package/SVF-doxygen/html/html/search/functions_7.js +1 -0
- package/SVF-doxygen/html/html/search/functions_e.js +3 -2
- package/SVF-doxygen/html/html/search/functions_f.js +2 -0
- package/SVF-doxygen/html/html/search/typedefs_3.js +1 -0
- package/SVF-doxygen/html/html/search/variables_12.js +1 -0
- package/SVF-doxygen/html/html/search/variables_14.js +3 -1
- package/SVF-doxygen/html/html/search/variables_15.js +1 -1
- package/SVF-doxygen/html/html/search/variables_2.js +1 -0
- package/SVF-doxygen/html/html/search/variables_3.js +1 -0
- package/SVF-doxygen/html/html/search/variables_4.js +2 -0
- package/SVF-doxygen/html/html/search/variables_5.js +1 -0
- package/SVF-doxygen/html/html/search/variables_6.js +1 -0
- package/SVF-doxygen/html/html/search/variables_c.js +1 -0
- package/SVF-doxygen/html/html/search/variables_d.js +1 -1
- package/SVF-doxygen/html/html/search/variables_e.js +7 -2
- package/SVF-doxygen/html/html/search/variables_f.js +2 -0
- package/SVF-doxygen/html/html/structllvm_1_1DOTGraphTraits_3_01ConstraintGraph_01_5_01_4.html +1 -1
- package/SVF-doxygen/html/html/structllvm_1_1DOTGraphTraits_3_01ICFG_01_5_01_4.html +1 -1
- package/SVF-doxygen/html/html/structllvm_1_1DOTGraphTraits_3_01SVFG_01_5_01_4.html +20 -20
- package/SVF-doxygen/html/html/structllvm_1_1DOTGraphTraits_3_01VFG_01_5_01_4.html +18 -18
- package/SVF-doxygen/html/html/structstd_1_1hash_3_01SVF_1_1PointsTo_01_4.html +1 -1
- package/include/SABER/ProgSlice.h +0 -3
- package/include/Util/NodeIDAllocator.h +94 -0
- package/include/Util/SVFUtil.h +3 -0
- package/include/WPA/Andersen.h +4 -0
- package/include/WPA/FlowSensitive.h +9 -0
- package/include/WPA/VersionedFlowSensitive.h +3 -0
- package/lib/Graphs/SVFG.cpp +0 -20
- package/lib/Graphs/VFG.cpp +18 -0
- package/lib/MemoryModel/PointsTo.cpp +76 -19
- package/lib/SABER/ProgSlice.cpp +0 -37
- package/lib/SABER/SaberAnnotator.cpp +1 -1
- package/lib/Util/NodeIDAllocator.cpp +548 -1
- package/lib/Util/SVFUtil.cpp +19 -0
- package/lib/WPA/Andersen.cpp +34 -0
- package/lib/WPA/FlowSensitive.cpp +70 -0
- package/lib/WPA/VersionedFlowSensitive.cpp +20 -0
- package/package.json +1 -1
|
@@ -153,4 +153,551 @@ namespace SVF
|
|
|
153
153
|
numSymbols = numNodes;
|
|
154
154
|
}
|
|
155
155
|
|
|
156
|
-
|
|
156
|
+
const std::string NodeIDAllocator::Clusterer::NumObjects = "NumObjects";
|
|
157
|
+
const std::string NodeIDAllocator::Clusterer::RegioningTime = "RegioningTime";
|
|
158
|
+
const std::string NodeIDAllocator::Clusterer::DistanceMatrixTime = "DistanceMatrixTime";
|
|
159
|
+
const std::string NodeIDAllocator::Clusterer::FastClusterTime = "FastClusterTime";
|
|
160
|
+
const std::string NodeIDAllocator::Clusterer::DendrogramTraversalTime = "DendrogramTravTime";
|
|
161
|
+
const std::string NodeIDAllocator::Clusterer::EvalTime = "EvalTime";
|
|
162
|
+
const std::string NodeIDAllocator::Clusterer::TotalTime = "TotalTime";
|
|
163
|
+
const std::string NodeIDAllocator::Clusterer::TheoreticalNumWords = "TheoreticalWords";
|
|
164
|
+
const std::string NodeIDAllocator::Clusterer::OriginalBvNumWords = "OriginalBvWords";
|
|
165
|
+
const std::string NodeIDAllocator::Clusterer::OriginalSbvNumWords = "OriginalSbvWords";
|
|
166
|
+
const std::string NodeIDAllocator::Clusterer::NewBvNumWords = "NewBvWords";
|
|
167
|
+
const std::string NodeIDAllocator::Clusterer::NewSbvNumWords = "NewSbvWords";
|
|
168
|
+
const std::string NodeIDAllocator::Clusterer::NumRegions = "NumRegions";
|
|
169
|
+
const std::string NodeIDAllocator::Clusterer::NumGtIntRegions = "NumGtIntRegions";
|
|
170
|
+
const std::string NodeIDAllocator::Clusterer::LargestRegion = "LargestRegion";
|
|
171
|
+
const std::string NodeIDAllocator::Clusterer::BestCandidate = "BestCandidate";
|
|
172
|
+
const std::string NodeIDAllocator::Clusterer::NumNonTrivialRegionObjects = "NumNonTrivObj";
|
|
173
|
+
|
|
174
|
+
std::vector<NodeID> NodeIDAllocator::Clusterer::cluster(BVDataPTAImpl *pta, const std::vector<std::pair<NodeID, unsigned>> keys, std::vector<std::pair<hclust_fast_methods, std::vector<NodeID>>> &candidates, std::string evalSubtitle)
|
|
175
|
+
{
|
|
176
|
+
assert(pta != nullptr && "Clusterer::cluster: given null BVDataPTAImpl");
|
|
177
|
+
assert(Options::NodeAllocStrat == Strategy::DENSE && "Clusterer::cluster: only dense allocation clustering currently supported");
|
|
178
|
+
|
|
179
|
+
Map<std::string, std::string> overallStats;
|
|
180
|
+
double totalTime = 0.0;
|
|
181
|
+
double fastClusterTime = 0.0;
|
|
182
|
+
double distanceMatrixTime = 0.0;
|
|
183
|
+
double dendrogramTraversalTime = 0.0;
|
|
184
|
+
double regioningTime = 0.0;
|
|
185
|
+
double evalTime = 0.0;
|
|
186
|
+
|
|
187
|
+
// Pair of nodes to their (minimum) distance and the number of occurrences of that distance.
|
|
188
|
+
Map<std::pair<NodeID, NodeID>, std::pair<unsigned, unsigned>> distances;
|
|
189
|
+
|
|
190
|
+
double clkStart = PTAStat::getClk(true);
|
|
191
|
+
|
|
192
|
+
// Map points-to sets to occurrences.
|
|
193
|
+
Map<PointsTo, unsigned> pointsToSets;
|
|
194
|
+
|
|
195
|
+
// Objects each object shares at least a points-to set with.
|
|
196
|
+
Map<NodeID, Set<NodeID>> coPointeeGraph;
|
|
197
|
+
for (const std::pair<NodeID, unsigned> &keyOcc : keys)
|
|
198
|
+
{
|
|
199
|
+
const PointsTo &pts = pta->getPts(keyOcc.first);
|
|
200
|
+
const size_t oldSize = pointsToSets.size();
|
|
201
|
+
pointsToSets[pts] += keyOcc.second;;
|
|
202
|
+
|
|
203
|
+
// Edges in this graph have no weight or uniqueness, so we only need to
|
|
204
|
+
// do this for each points-to set once.
|
|
205
|
+
if (oldSize != pointsToSets.size())
|
|
206
|
+
{
|
|
207
|
+
NodeID firstO = !pts.empty() ? *(pts.begin()) : 0;
|
|
208
|
+
Set<NodeID> &firstOsNeighbours = coPointeeGraph[firstO];
|
|
209
|
+
for (const NodeID o : pts)
|
|
210
|
+
{
|
|
211
|
+
if (o != firstO)
|
|
212
|
+
{
|
|
213
|
+
firstOsNeighbours.insert(o);
|
|
214
|
+
coPointeeGraph[o].insert(firstO);
|
|
215
|
+
}
|
|
216
|
+
}
|
|
217
|
+
}
|
|
218
|
+
}
|
|
219
|
+
|
|
220
|
+
size_t numObjects = NodeIDAllocator::get()->numObjects;
|
|
221
|
+
overallStats[NumObjects] = std::to_string(numObjects);
|
|
222
|
+
|
|
223
|
+
size_t numRegions = 0;
|
|
224
|
+
std::vector<unsigned> objectsRegion;
|
|
225
|
+
if (Options::RegionedClustering)
|
|
226
|
+
{
|
|
227
|
+
objectsRegion = regionObjects(coPointeeGraph, numObjects, numRegions);
|
|
228
|
+
}
|
|
229
|
+
else
|
|
230
|
+
{
|
|
231
|
+
// Just a single big region (0).
|
|
232
|
+
objectsRegion.insert(objectsRegion.end(), numObjects, 0);
|
|
233
|
+
numRegions = 1;
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
// Set needs to be ordered because getDistanceMatrix, in its n^2 iteration, expects
|
|
237
|
+
// sets to be ordered (we are building a condensed matrix, not a full matrix, so it
|
|
238
|
+
// matters). In getDistanceMatrix, doing regionReverseMapping for oi and oj, where
|
|
239
|
+
// oi < oj, and getting a result moi > moj gives incorrect results.
|
|
240
|
+
// In the condensed matrix, [b][a] where b >= a, is incorrect.
|
|
241
|
+
std::vector<OrderedSet<NodeID>> regionsObjects(numRegions);
|
|
242
|
+
for (NodeID o = 0; o < numObjects; ++o) regionsObjects[objectsRegion[o]].insert(o);
|
|
243
|
+
|
|
244
|
+
// Size of the return node mapping. It is potentially larger than the number of
|
|
245
|
+
// objects because we align each region to NATIVE_INT_SIZE.
|
|
246
|
+
size_t numMappings = 0;
|
|
247
|
+
|
|
248
|
+
// Maps a region to a mapping which maps 0 to n to all objects
|
|
249
|
+
// in that region.
|
|
250
|
+
std::vector<std::vector<NodeID>> regionMappings(numRegions);
|
|
251
|
+
// The reverse: region to mapping of objects to a 0 to n from above.
|
|
252
|
+
std::vector<Map<NodeID, unsigned>> regionReverseMappings(numRegions);
|
|
253
|
+
// We can thus use 0 to n for each region to create smaller distance matrices.
|
|
254
|
+
for (unsigned region = 0; region < numRegions; ++region)
|
|
255
|
+
{
|
|
256
|
+
size_t curr = 0;
|
|
257
|
+
// With the OrderedSet above, o1 < o2 => map[o1] < map[o2].
|
|
258
|
+
for (NodeID o : regionsObjects[region])
|
|
259
|
+
{
|
|
260
|
+
// push_back here is just like p...[region][curr] = o.
|
|
261
|
+
regionMappings[region].push_back(o);
|
|
262
|
+
regionReverseMappings[region][o] = curr++;
|
|
263
|
+
}
|
|
264
|
+
|
|
265
|
+
// curr is the number of objects. A region with no objects makes no sense.
|
|
266
|
+
assert(curr != 0);
|
|
267
|
+
|
|
268
|
+
// Number of bits needed for this region if we were
|
|
269
|
+
// to start assigning from 0 rounded up to the fewest needed
|
|
270
|
+
// native ints. This is added to the number of mappings since
|
|
271
|
+
// we align each region to a native int.
|
|
272
|
+
numMappings += requiredBits(regionsObjects[region].size());
|
|
273
|
+
}
|
|
274
|
+
|
|
275
|
+
// Points-to sets which are relevant to a region, i.e., those whose elements
|
|
276
|
+
// belong to that region. Pair is for occurences.
|
|
277
|
+
std::vector<std::vector<std::pair<const PointsTo *, unsigned>>> regionsPointsTos(numRegions);
|
|
278
|
+
for (const Map<PointsTo, unsigned>::value_type &ptocc : pointsToSets)
|
|
279
|
+
{
|
|
280
|
+
const PointsTo &pt = ptocc.first;
|
|
281
|
+
const unsigned occ = ptocc.second;
|
|
282
|
+
if (pt.empty()) continue;
|
|
283
|
+
// Guaranteed that begin() != end() because of the continue above. All objects in pt
|
|
284
|
+
// will be relevant to the same region.
|
|
285
|
+
unsigned region = objectsRegion[*(pt.begin())];
|
|
286
|
+
// In our "graph", objects in the same points-to set have an edge between them,
|
|
287
|
+
// so they are all in the same connected component/region.
|
|
288
|
+
regionsPointsTos[region].push_back(std::make_pair(&pt, occ));
|
|
289
|
+
}
|
|
290
|
+
|
|
291
|
+
double clkEnd = PTAStat::getClk(true);
|
|
292
|
+
regioningTime = (clkEnd - clkStart) / TIMEINTERVAL;
|
|
293
|
+
overallStats[RegioningTime] = std::to_string(regioningTime);
|
|
294
|
+
overallStats[NumRegions] = std::to_string(numRegions);
|
|
295
|
+
|
|
296
|
+
std::vector<hclust_fast_methods> methods;
|
|
297
|
+
if (Options::ClusterMethod == HCLUST_METHOD_SVF_BEST)
|
|
298
|
+
{
|
|
299
|
+
methods.push_back(HCLUST_METHOD_SINGLE);
|
|
300
|
+
methods.push_back(HCLUST_METHOD_COMPLETE);
|
|
301
|
+
methods.push_back(HCLUST_METHOD_AVERAGE);
|
|
302
|
+
}
|
|
303
|
+
else
|
|
304
|
+
{
|
|
305
|
+
methods.push_back(Options::ClusterMethod);
|
|
306
|
+
}
|
|
307
|
+
|
|
308
|
+
for (const hclust_fast_methods method : methods)
|
|
309
|
+
{
|
|
310
|
+
std::vector<NodeID> nodeMap(numObjects, UINT_MAX);
|
|
311
|
+
|
|
312
|
+
unsigned numGtIntRegions = 0;
|
|
313
|
+
unsigned largestRegion = 0;
|
|
314
|
+
unsigned nonTrivialRegionObjects = 0;
|
|
315
|
+
unsigned allocCounter = 0;
|
|
316
|
+
for (unsigned region = 0; region < numRegions; ++region)
|
|
317
|
+
{
|
|
318
|
+
const size_t regionNumObjects = regionsObjects[region].size();
|
|
319
|
+
// Round up to next Word: ceiling of current allocation to get how
|
|
320
|
+
// many words and multiply to get the number of bits; if we're aligning.
|
|
321
|
+
if (Options::RegionAlign)
|
|
322
|
+
{
|
|
323
|
+
allocCounter =
|
|
324
|
+
((allocCounter + NATIVE_INT_SIZE - 1) / NATIVE_INT_SIZE) * NATIVE_INT_SIZE;
|
|
325
|
+
}
|
|
326
|
+
|
|
327
|
+
if (regionNumObjects > largestRegion) largestRegion = regionNumObjects;
|
|
328
|
+
|
|
329
|
+
// For regions with fewer than 64 objects, we can just allocate them
|
|
330
|
+
// however as they will be in the one int regardless..
|
|
331
|
+
if (regionNumObjects < NATIVE_INT_SIZE)
|
|
332
|
+
{
|
|
333
|
+
for (NodeID o : regionsObjects[region]) nodeMap[o] = allocCounter++;
|
|
334
|
+
continue;
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
++numGtIntRegions;
|
|
338
|
+
nonTrivialRegionObjects += regionNumObjects;
|
|
339
|
+
|
|
340
|
+
double *distMatrix = getDistanceMatrix(regionsPointsTos[region], regionNumObjects,
|
|
341
|
+
regionReverseMappings[region], distanceMatrixTime);
|
|
342
|
+
|
|
343
|
+
clkStart = PTAStat::getClk(true);
|
|
344
|
+
int *dendrogram = new int[2 * (regionNumObjects - 1)];
|
|
345
|
+
double *height = new double[regionNumObjects - 1];
|
|
346
|
+
hclust_fast(regionNumObjects, distMatrix, method, dendrogram, height);
|
|
347
|
+
delete[] distMatrix;
|
|
348
|
+
delete[] height;
|
|
349
|
+
clkEnd = PTAStat::getClk(true);
|
|
350
|
+
fastClusterTime += (clkEnd - clkStart) / TIMEINTERVAL;
|
|
351
|
+
|
|
352
|
+
clkStart = PTAStat::getClk(true);
|
|
353
|
+
Set<int> visited;
|
|
354
|
+
traverseDendrogram(nodeMap, dendrogram, regionNumObjects, allocCounter,
|
|
355
|
+
visited, regionNumObjects - 1, regionMappings[region]);
|
|
356
|
+
delete[] dendrogram;
|
|
357
|
+
clkEnd = PTAStat::getClk(true);
|
|
358
|
+
dendrogramTraversalTime += (clkEnd - clkStart) / TIMEINTERVAL;
|
|
359
|
+
}
|
|
360
|
+
|
|
361
|
+
candidates.push_back(std::make_pair(method, nodeMap));
|
|
362
|
+
|
|
363
|
+
// Though we "update" these in the loop, they will be the same every iteration.
|
|
364
|
+
overallStats[NumGtIntRegions] = std::to_string(numGtIntRegions);
|
|
365
|
+
overallStats[LargestRegion] = std::to_string(largestRegion);
|
|
366
|
+
overallStats[NumNonTrivialRegionObjects] = std::to_string(nonTrivialRegionObjects);
|
|
367
|
+
}
|
|
368
|
+
|
|
369
|
+
// Work out which of the mappings we generated looks best.
|
|
370
|
+
std::pair<hclust_fast_methods, std::vector<NodeID>> bestMapping = determineBestMapping(candidates, pointsToSets,
|
|
371
|
+
evalSubtitle, evalTime);
|
|
372
|
+
|
|
373
|
+
overallStats[DistanceMatrixTime] = std::to_string(distanceMatrixTime);
|
|
374
|
+
overallStats[DendrogramTraversalTime] = std::to_string(dendrogramTraversalTime);
|
|
375
|
+
overallStats[FastClusterTime] = std::to_string(fastClusterTime);
|
|
376
|
+
overallStats[EvalTime] = std::to_string(evalTime);
|
|
377
|
+
overallStats[TotalTime] = std::to_string(distanceMatrixTime + dendrogramTraversalTime + fastClusterTime + regioningTime + evalTime);
|
|
378
|
+
|
|
379
|
+
overallStats[BestCandidate] = SVFUtil::hclustMethodToString(bestMapping.first);
|
|
380
|
+
printStats(evalSubtitle + ": overall", overallStats);
|
|
381
|
+
|
|
382
|
+
return bestMapping.second;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
std::vector<NodeID> NodeIDAllocator::Clusterer::getReverseNodeMapping(const std::vector<NodeID> &nodeMapping)
|
|
386
|
+
{
|
|
387
|
+
// nodeMapping.size() may not be big enough because we leave some gaps, but it's a start.
|
|
388
|
+
std::vector<NodeID> reverseNodeMapping(nodeMapping.size(), UINT_MAX);
|
|
389
|
+
for (size_t i = 0; i < nodeMapping.size(); ++i)
|
|
390
|
+
{
|
|
391
|
+
const NodeID mapsTo = nodeMapping.at(i);
|
|
392
|
+
if (mapsTo >= reverseNodeMapping.size()) reverseNodeMapping.resize(mapsTo + 1, UINT_MAX);
|
|
393
|
+
reverseNodeMapping.at(mapsTo) = i;
|
|
394
|
+
}
|
|
395
|
+
|
|
396
|
+
return reverseNodeMapping;
|
|
397
|
+
}
|
|
398
|
+
|
|
399
|
+
size_t NodeIDAllocator::Clusterer::condensedIndex(size_t n, size_t i, size_t j)
|
|
400
|
+
{
|
|
401
|
+
// From https://stackoverflow.com/a/14839010
|
|
402
|
+
return n*(n-1)/2 - (n-i)*(n-i-1)/2 + j - i - 1;
|
|
403
|
+
}
|
|
404
|
+
|
|
405
|
+
unsigned NodeIDAllocator::Clusterer::requiredBits(const PointsTo &pts)
|
|
406
|
+
{
|
|
407
|
+
return requiredBits(pts.count());
|
|
408
|
+
}
|
|
409
|
+
|
|
410
|
+
unsigned NodeIDAllocator::Clusterer::requiredBits(const size_t n)
|
|
411
|
+
{
|
|
412
|
+
if (n == 0) return 0;
|
|
413
|
+
// Ceiling of number of bits amongst each native integer gives needed native ints,
|
|
414
|
+
// so we then multiply again by the number of bits in each native int.
|
|
415
|
+
return ((n - 1) / NATIVE_INT_SIZE + 1) * NATIVE_INT_SIZE;
|
|
416
|
+
}
|
|
417
|
+
|
|
418
|
+
double *NodeIDAllocator::Clusterer::getDistanceMatrix(const std::vector<std::pair<const PointsTo *, unsigned>> pointsToSets,
|
|
419
|
+
const size_t numObjects, const Map<NodeID, unsigned> &nodeMap,
|
|
420
|
+
double &distanceMatrixTime)
|
|
421
|
+
{
|
|
422
|
+
const double clkStart = PTAStat::getClk(true);
|
|
423
|
+
size_t condensedSize = (numObjects * (numObjects - 1)) / 2;
|
|
424
|
+
double *distMatrix = new double[condensedSize];
|
|
425
|
+
for (size_t i = 0; i < condensedSize; ++i) distMatrix[i] = numObjects * numObjects;
|
|
426
|
+
|
|
427
|
+
// TODO: maybe use machine epsilon?
|
|
428
|
+
// For reducing distance due to extra occurrences.
|
|
429
|
+
// Can differentiate ~9999 occurrences.
|
|
430
|
+
double occurrenceEpsilon = 0.0001;
|
|
431
|
+
|
|
432
|
+
for (const std::pair<const PointsTo *, unsigned> &ptsOcc : pointsToSets)
|
|
433
|
+
{
|
|
434
|
+
const PointsTo *pts = ptsOcc.first;
|
|
435
|
+
assert(pts != nullptr);
|
|
436
|
+
const unsigned occ = ptsOcc.second;
|
|
437
|
+
|
|
438
|
+
// Distance between each element of pts.
|
|
439
|
+
unsigned distance = requiredBits(*pts) / NATIVE_INT_SIZE;
|
|
440
|
+
|
|
441
|
+
// Use a vector so we can index into pts.
|
|
442
|
+
std::vector<NodeID> ptsVec;
|
|
443
|
+
for (const NodeID o : *pts) ptsVec.push_back(o);
|
|
444
|
+
for (size_t i = 0; i < ptsVec.size(); ++i)
|
|
445
|
+
{
|
|
446
|
+
const NodeID oi = ptsVec[i];
|
|
447
|
+
const Map<NodeID, unsigned>::const_iterator moi = nodeMap.find(oi);
|
|
448
|
+
assert(moi != nodeMap.end());
|
|
449
|
+
for (size_t j = i + 1; j < ptsVec.size(); ++j)
|
|
450
|
+
{
|
|
451
|
+
const NodeID oj = ptsVec[j];
|
|
452
|
+
const Map<NodeID, unsigned>::const_iterator moj = nodeMap.find(oj);
|
|
453
|
+
assert(moj != nodeMap.end());
|
|
454
|
+
double &existingDistance = distMatrix[condensedIndex(numObjects, moi->second, moj->second)];
|
|
455
|
+
|
|
456
|
+
// Subtract extra occurrenceEpsilon to make upcoming logic simpler.
|
|
457
|
+
// When existingDistance is never whole, it is always between two distances.
|
|
458
|
+
if (distance < existingDistance) existingDistance = distance - occurrenceEpsilon;
|
|
459
|
+
|
|
460
|
+
if (distance == std::ceil(existingDistance))
|
|
461
|
+
{
|
|
462
|
+
// We have something like distance == x, existingDistance == x - e, for some e < 1
|
|
463
|
+
// (potentially even set during this iteration).
|
|
464
|
+
// So, the new distance is an occurrence the existingDistance being tracked, it just
|
|
465
|
+
// had some reductions because of multiple occurences.
|
|
466
|
+
// If there is not room within this distance to reduce more (increase priority),
|
|
467
|
+
// just ignore it. TODO: maybe warn?
|
|
468
|
+
if (existingDistance - occ * occurrenceEpsilon > std::floor(existingDistance))
|
|
469
|
+
{
|
|
470
|
+
existingDistance -= occ * occurrenceEpsilon;
|
|
471
|
+
}
|
|
472
|
+
else
|
|
473
|
+
{
|
|
474
|
+
// Reached minimum.
|
|
475
|
+
existingDistance = std::floor(existingDistance) + occurrenceEpsilon;
|
|
476
|
+
}
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
}
|
|
480
|
+
|
|
481
|
+
}
|
|
482
|
+
|
|
483
|
+
const double clkEnd = PTAStat::getClk(true);
|
|
484
|
+
distanceMatrixTime += (clkEnd - clkStart) / TIMEINTERVAL;
|
|
485
|
+
|
|
486
|
+
return distMatrix;
|
|
487
|
+
}
|
|
488
|
+
|
|
489
|
+
void NodeIDAllocator::Clusterer::traverseDendrogram(std::vector<NodeID> &nodeMap, const int *dendrogram, const size_t numObjects, unsigned &allocCounter, Set<int> &visited, const int index, const std::vector<NodeID> ®ionNodeMap)
|
|
490
|
+
{
|
|
491
|
+
if (visited.find(index) != visited.end()) return;
|
|
492
|
+
visited.insert(index);
|
|
493
|
+
|
|
494
|
+
int left = dendrogram[index - 1];
|
|
495
|
+
if (left < 0)
|
|
496
|
+
{
|
|
497
|
+
// Reached a leaf.
|
|
498
|
+
// -1 because the items start from 1 per fastcluster (TODO).
|
|
499
|
+
nodeMap[regionNodeMap[std::abs(left) - 1]] = allocCounter;
|
|
500
|
+
++allocCounter;
|
|
501
|
+
}
|
|
502
|
+
else
|
|
503
|
+
{
|
|
504
|
+
traverseDendrogram(nodeMap, dendrogram, numObjects, allocCounter, visited, left, regionNodeMap);
|
|
505
|
+
}
|
|
506
|
+
|
|
507
|
+
// Repeat for the right child.
|
|
508
|
+
int right = dendrogram[(numObjects - 1) + index - 1];
|
|
509
|
+
if (right < 0)
|
|
510
|
+
{
|
|
511
|
+
nodeMap[regionNodeMap[std::abs(right) - 1]] = allocCounter;
|
|
512
|
+
++allocCounter;
|
|
513
|
+
}
|
|
514
|
+
else
|
|
515
|
+
{
|
|
516
|
+
traverseDendrogram(nodeMap, dendrogram, numObjects, allocCounter, visited, right, regionNodeMap);
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
std::vector<NodeID> NodeIDAllocator::Clusterer::regionObjects(const Map<NodeID, Set<NodeID>> &graph, size_t numObjects, size_t &numLabels)
|
|
521
|
+
{
|
|
522
|
+
unsigned label = UINT_MAX;
|
|
523
|
+
std::vector<NodeID> labels(numObjects, UINT_MAX);
|
|
524
|
+
Set<NodeID> labelled;
|
|
525
|
+
for (const Map<NodeID, Set<NodeID>>::value_type &oos : graph)
|
|
526
|
+
{
|
|
527
|
+
const NodeID o = oos.first;
|
|
528
|
+
if (labels[o] != UINT_MAX) continue;
|
|
529
|
+
std::queue<NodeID> bfsQueue;
|
|
530
|
+
bfsQueue.push(o);
|
|
531
|
+
++label;
|
|
532
|
+
while (!bfsQueue.empty())
|
|
533
|
+
{
|
|
534
|
+
const NodeID o = bfsQueue.front();
|
|
535
|
+
bfsQueue.pop();
|
|
536
|
+
if (labels[o] != UINT_MAX)
|
|
537
|
+
{
|
|
538
|
+
assert(labels[o] == label);
|
|
539
|
+
continue;
|
|
540
|
+
}
|
|
541
|
+
|
|
542
|
+
labels[o] = label;
|
|
543
|
+
Map<NodeID, Set<NodeID>>::const_iterator neighboursIt = graph.find(o);
|
|
544
|
+
assert(neighboursIt != graph.end());
|
|
545
|
+
for (const NodeID neighbour : neighboursIt->second) bfsQueue.push(neighbour);
|
|
546
|
+
}
|
|
547
|
+
}
|
|
548
|
+
|
|
549
|
+
// The remaining objects have no relation with others: they get their own label.
|
|
550
|
+
for (size_t o = 0; o < numObjects; ++o)
|
|
551
|
+
{
|
|
552
|
+
if (labels[o] == UINT_MAX) labels[o] = ++label;
|
|
553
|
+
}
|
|
554
|
+
|
|
555
|
+
numLabels = label + 1;
|
|
556
|
+
|
|
557
|
+
return labels;
|
|
558
|
+
}
|
|
559
|
+
|
|
560
|
+
void NodeIDAllocator::Clusterer::evaluate(const std::vector<NodeID> &nodeMap, const Map<PointsTo, unsigned> pointsToSets, Map<std::string, std::string> &stats, bool accountForOcc)
|
|
561
|
+
{
|
|
562
|
+
u64_t totalTheoretical = 0;
|
|
563
|
+
u64_t totalOriginalSbv = 0;
|
|
564
|
+
u64_t totalOriginalBv = 0;
|
|
565
|
+
u64_t totalNewSbv = 0;
|
|
566
|
+
u64_t totalNewBv = 0;
|
|
567
|
+
|
|
568
|
+
for (const Map<PointsTo, unsigned>::value_type &ptsOcc : pointsToSets)
|
|
569
|
+
{
|
|
570
|
+
const PointsTo &pts = ptsOcc.first;
|
|
571
|
+
const unsigned occ = ptsOcc.second;
|
|
572
|
+
if (pts.count() == 0) continue;
|
|
573
|
+
|
|
574
|
+
u64_t theoretical = requiredBits(pts) / NATIVE_INT_SIZE;
|
|
575
|
+
if (accountForOcc) theoretical *= occ;
|
|
576
|
+
|
|
577
|
+
// Check number of words for original SBV.
|
|
578
|
+
Set<unsigned> words;
|
|
579
|
+
// TODO: nasty hardcoding.
|
|
580
|
+
for (const NodeID o : pts) words.insert(o / 128);
|
|
581
|
+
u64_t originalSbv = words.size() * 2;
|
|
582
|
+
if (accountForOcc) originalSbv *= occ;
|
|
583
|
+
|
|
584
|
+
// Check number of words for original BV.
|
|
585
|
+
NodeID min = UINT_MAX;
|
|
586
|
+
NodeID max = 0;
|
|
587
|
+
for (NodeID o : pts)
|
|
588
|
+
{
|
|
589
|
+
if (o < min) min = o;
|
|
590
|
+
if (o > max) max = o;
|
|
591
|
+
}
|
|
592
|
+
words.clear();
|
|
593
|
+
for (NodeID b = min; b <= max; ++b)
|
|
594
|
+
{
|
|
595
|
+
words.insert(b / NATIVE_INT_SIZE);
|
|
596
|
+
}
|
|
597
|
+
u64_t originalBv = words.size();
|
|
598
|
+
if (accountForOcc) originalBv *= occ;
|
|
599
|
+
|
|
600
|
+
// Check number of words for new SBV.
|
|
601
|
+
words.clear();
|
|
602
|
+
// TODO: nasty hardcoding.
|
|
603
|
+
for (const NodeID o : pts) words.insert(nodeMap[o] / 128);
|
|
604
|
+
u64_t newSbv = words.size() * 2;
|
|
605
|
+
if (accountForOcc) newSbv *= occ;
|
|
606
|
+
|
|
607
|
+
// Check number of words for new BV.
|
|
608
|
+
min = UINT_MAX;
|
|
609
|
+
max = 0;
|
|
610
|
+
for (const NodeID o : pts)
|
|
611
|
+
{
|
|
612
|
+
const NodeID mappedO = nodeMap[o];
|
|
613
|
+
if (mappedO < min) min = mappedO;
|
|
614
|
+
if (mappedO > max) max = mappedO;
|
|
615
|
+
}
|
|
616
|
+
|
|
617
|
+
words.clear();
|
|
618
|
+
// No nodeMap[b] because min and max and from nodeMap.
|
|
619
|
+
for (NodeID b = min; b <= max; ++b) words.insert(b / NATIVE_INT_SIZE);
|
|
620
|
+
u64_t newBv = words.size();
|
|
621
|
+
if (accountForOcc) newBv *= occ;
|
|
622
|
+
|
|
623
|
+
totalTheoretical += theoretical;
|
|
624
|
+
totalOriginalSbv += originalSbv;
|
|
625
|
+
totalOriginalBv += originalBv;
|
|
626
|
+
totalNewSbv += newSbv;
|
|
627
|
+
totalNewBv += newBv;
|
|
628
|
+
}
|
|
629
|
+
|
|
630
|
+
stats[TheoreticalNumWords] = std::to_string(totalTheoretical);
|
|
631
|
+
stats[OriginalSbvNumWords] = std::to_string(totalOriginalSbv);
|
|
632
|
+
stats[OriginalBvNumWords] = std::to_string(totalOriginalBv);
|
|
633
|
+
stats[NewSbvNumWords] = std::to_string(totalNewSbv);
|
|
634
|
+
stats[NewBvNumWords] = std::to_string(totalNewBv);
|
|
635
|
+
}
|
|
636
|
+
|
|
637
|
+
// Work out which of the mappings we generated looks best.
|
|
638
|
+
std::pair<hclust_fast_methods, std::vector<NodeID>> NodeIDAllocator::Clusterer::determineBestMapping(
|
|
639
|
+
const std::vector<std::pair<hclust_fast_methods, std::vector<NodeID>>> &candidates,
|
|
640
|
+
Map<PointsTo, unsigned> pointsToSets, const std::string &evalSubtitle, double &evalTime)
|
|
641
|
+
{
|
|
642
|
+
// In case we're not comparing anything, set to first "candidate".
|
|
643
|
+
std::pair<hclust_fast_methods, std::vector<NodeID>> bestMapping = candidates[0];
|
|
644
|
+
// Number of bits required for the best candidate.
|
|
645
|
+
size_t bestWords = std::numeric_limits<size_t>::max();
|
|
646
|
+
if (evalSubtitle != "" || Options::ClusterMethod == HCLUST_METHOD_SVF_BEST)
|
|
647
|
+
{
|
|
648
|
+
for (const std::pair<hclust_fast_methods, std::vector<NodeID>> &candidate : candidates)
|
|
649
|
+
{
|
|
650
|
+
Map<std::string, std::string> candidateStats;
|
|
651
|
+
hclust_fast_methods candidateMethod = candidate.first;
|
|
652
|
+
std::string candidateMethodName = SVFUtil::hclustMethodToString(candidateMethod);
|
|
653
|
+
std::vector<NodeID> candidateMapping = candidate.second;
|
|
654
|
+
|
|
655
|
+
// TODO: parameterise final arg.
|
|
656
|
+
const double clkStart = PTAStat::getClk(true);
|
|
657
|
+
evaluate(candidateMapping, pointsToSets, candidateStats, true);
|
|
658
|
+
const double clkEnd = PTAStat::getClk(true);
|
|
659
|
+
evalTime += (clkEnd - clkStart) / TIMEINTERVAL;
|
|
660
|
+
printStats(evalSubtitle + ": candidate " + candidateMethodName, candidateStats);
|
|
661
|
+
|
|
662
|
+
size_t candidateWords = 0;
|
|
663
|
+
if (Options::PtType == PointsTo::SBV) candidateWords = std::stoull(candidateStats[NewSbvNumWords]);
|
|
664
|
+
else if (Options::PtType == PointsTo::CBV) candidateWords = std::stoull(candidateStats[NewBvNumWords]);
|
|
665
|
+
else assert(false && "Clusterer::cluster: unsupported BV type for clustering.");
|
|
666
|
+
|
|
667
|
+
if (candidateWords < bestWords)
|
|
668
|
+
{
|
|
669
|
+
bestWords = candidateWords;
|
|
670
|
+
bestMapping = candidate;
|
|
671
|
+
}
|
|
672
|
+
}
|
|
673
|
+
}
|
|
674
|
+
|
|
675
|
+
return bestMapping;
|
|
676
|
+
}
|
|
677
|
+
|
|
678
|
+
void NodeIDAllocator::Clusterer::printStats(std::string subtitle, Map<std::string, std::string> &stats)
|
|
679
|
+
{
|
|
680
|
+
// When not in order, it is too hard to compare original/new SBV/BV words, so this array forces an order.
|
|
681
|
+
const static std::array<std::string, 17> statKeys =
|
|
682
|
+
{ NumObjects, TheoreticalNumWords, OriginalSbvNumWords, OriginalBvNumWords,
|
|
683
|
+
NewSbvNumWords, NewBvNumWords, NumRegions, NumGtIntRegions,
|
|
684
|
+
NumNonTrivialRegionObjects, LargestRegion, RegioningTime,
|
|
685
|
+
DistanceMatrixTime, FastClusterTime, DendrogramTraversalTime,
|
|
686
|
+
EvalTime, TotalTime, BestCandidate };
|
|
687
|
+
|
|
688
|
+
const unsigned fieldWidth = 20;
|
|
689
|
+
std::cout.flags(std::ios::left);
|
|
690
|
+
std::cout << "****Clusterer Statistics: " << subtitle << "****\n";
|
|
691
|
+
for (const std::string &statKey : statKeys)
|
|
692
|
+
{
|
|
693
|
+
Map<std::string, std::string>::const_iterator stat = stats.find(statKey);
|
|
694
|
+
if (stat != stats.end())
|
|
695
|
+
{
|
|
696
|
+
std::cout << std::setw(fieldWidth) << statKey << " " << stat->second << "\n";
|
|
697
|
+
}
|
|
698
|
+
}
|
|
699
|
+
|
|
700
|
+
std::cout.flush();
|
|
701
|
+
}
|
|
702
|
+
|
|
703
|
+
}; // namespace SVF.
|
package/lib/Util/SVFUtil.cpp
CHANGED
|
@@ -362,6 +362,25 @@ std::string SVFUtil::getSourceLoc(const Value* val)
|
|
|
362
362
|
return rawstr.str();
|
|
363
363
|
}
|
|
364
364
|
|
|
365
|
+
std::string SVFUtil::hclustMethodToString(hclust_fast_methods method)
|
|
366
|
+
{
|
|
367
|
+
switch (method)
|
|
368
|
+
{
|
|
369
|
+
case HCLUST_METHOD_SINGLE:
|
|
370
|
+
return "single";
|
|
371
|
+
case HCLUST_METHOD_COMPLETE:
|
|
372
|
+
return "complete";
|
|
373
|
+
case HCLUST_METHOD_AVERAGE:
|
|
374
|
+
return "average";
|
|
375
|
+
case HCLUST_METHOD_MEDIAN:
|
|
376
|
+
return "median";
|
|
377
|
+
case HCLUST_METHOD_SVF_BEST:
|
|
378
|
+
return "svf-best";
|
|
379
|
+
default:
|
|
380
|
+
assert(false && "SVFUtil::hclustMethodToString: unknown method");
|
|
381
|
+
}
|
|
382
|
+
}
|
|
383
|
+
|
|
365
384
|
/*!
|
|
366
385
|
* return string of an LLVM Value
|
|
367
386
|
*/
|
package/lib/WPA/Andersen.cpp
CHANGED
|
@@ -178,6 +178,9 @@ void Andersen::initialize()
|
|
|
178
178
|
setDiffOpt(Options::PtsDiff);
|
|
179
179
|
setPWCOpt(Options::MergePWC);
|
|
180
180
|
AndersenBase::initialize();
|
|
181
|
+
|
|
182
|
+
if (Options::ClusterAnder) cluster();
|
|
183
|
+
|
|
181
184
|
/// Initialize worklist
|
|
182
185
|
processAllAddr();
|
|
183
186
|
}
|
|
@@ -187,6 +190,18 @@ void Andersen::initialize()
|
|
|
187
190
|
*/
|
|
188
191
|
void Andersen::finalize()
|
|
189
192
|
{
|
|
193
|
+
// TODO: check -stat too.
|
|
194
|
+
// TODO: broken
|
|
195
|
+
if (Options::ClusterAnder)
|
|
196
|
+
{
|
|
197
|
+
Map<std::string, std::string> stats;
|
|
198
|
+
const PTDataTy *ptd = getPTDataTy();
|
|
199
|
+
// TODO: should we use liveOnly?
|
|
200
|
+
// TODO: parameterise final arg.
|
|
201
|
+
NodeIDAllocator::Clusterer::evaluate(*PointsTo::getCurrentBestNodeMapping(), ptd->getAllPts(true), stats, true);
|
|
202
|
+
NodeIDAllocator::Clusterer::printStats("post-main", stats);
|
|
203
|
+
}
|
|
204
|
+
|
|
190
205
|
/// sanitize field insensitive obj
|
|
191
206
|
/// TODO: Fields has been collapsed during Andersen::collapseField().
|
|
192
207
|
// sanitizePts();
|
|
@@ -811,6 +826,25 @@ void Andersen::updateNodeRepAndSubs(NodeID nodeId, NodeID newRepId)
|
|
|
811
826
|
consCG->resetSubs(nodeId);
|
|
812
827
|
}
|
|
813
828
|
|
|
829
|
+
void Andersen::cluster(void) const
|
|
830
|
+
{
|
|
831
|
+
assert(Options::MaxFieldLimit == 0 && "Andersen::cluster: clustering for Andersen's is currently only supported in field-insesnsitive analysis");
|
|
832
|
+
Steensgaard *steens = Steensgaard::createSteensgaard(pag);
|
|
833
|
+
std::vector<std::pair<unsigned, unsigned>> keys;
|
|
834
|
+
for (PAG::iterator pit = pag->begin(); pit != pag->end(); ++pit)
|
|
835
|
+
{
|
|
836
|
+
keys.push_back(std::make_pair(pit->first, 1));
|
|
837
|
+
}
|
|
838
|
+
|
|
839
|
+
std::vector<std::pair<hclust_fast_methods, std::vector<NodeID>>> candidates;
|
|
840
|
+
PointsTo::MappingPtr nodeMapping =
|
|
841
|
+
std::make_shared<std::vector<NodeID>>(NodeIDAllocator::Clusterer::cluster(steens, keys, candidates, "aux-steens"));
|
|
842
|
+
PointsTo::MappingPtr reverseNodeMapping =
|
|
843
|
+
std::make_shared<std::vector<NodeID>>(NodeIDAllocator::Clusterer::getReverseNodeMapping(*nodeMapping));
|
|
844
|
+
|
|
845
|
+
PointsTo::setCurrentBestNodeMapping(nodeMapping, reverseNodeMapping);
|
|
846
|
+
}
|
|
847
|
+
|
|
814
848
|
/*!
|
|
815
849
|
* Print pag nodes' pts by an ascending order
|
|
816
850
|
*/
|