Beispiel #1
0
        internal DictionaryAnalysisData <TKey, TValue> Intersect(
            DictionaryAnalysisData <TKey, TValue> map1,
            DictionaryAnalysisData <TKey, TValue> map2,
            Func <TValue, TValue, TValue> intersect)
        {
            var result = new DictionaryAnalysisData <TKey, TValue>();

            foreach (var kvp in map1)
            {
                if (!map2.TryGetValue(kvp.Key, out var value2))
                {
                    value2 = ValueDomain.UnknownOrMayBeValue;
                }

                result.Add(kvp.Key, intersect(kvp.Value, value2));
            }

            foreach (var key in map2.Keys)
            {
                if (!result.ContainsKey(key))
                {
                    result.Add(key, ValueDomain.UnknownOrMayBeValue);
                }
            }

            return(result);
        }
Beispiel #2
0
        private static DictionaryAnalysisData <AnalysisEntity, PerEntityPredicatedAnalysisData> MergeForPredicatedDataInBothBranches(
            DictionaryAnalysisData <AnalysisEntity, PerEntityPredicatedAnalysisData> predicatedData1,
            DictionaryAnalysisData <AnalysisEntity, PerEntityPredicatedAnalysisData> predicatedData2,
            DictionaryAnalysisData <TKey, TValue> coreAnalysisData1,
            DictionaryAnalysisData <TKey, TValue> coreAnalysisData2,
            MapAbstractDomain <TKey, TValue> coreDataAnalysisDomain,
            Action <DictionaryAnalysisData <TKey, TValue>, DictionaryAnalysisData <TKey, TValue> > applyPredicatedData)
        {
            Debug.Assert(predicatedData1 != null);
            Debug.Assert(predicatedData2 != null);
            Debug.Assert(coreAnalysisData1 != null);
            Debug.Assert(coreAnalysisData2 != null);

            var result = new DictionaryAnalysisData <AnalysisEntity, PerEntityPredicatedAnalysisData>();

            foreach (var kvp in predicatedData1)
            {
                DictionaryAnalysisData <TKey, TValue> resultTruePredicatedData;
                DictionaryAnalysisData <TKey, TValue> resultFalsePredicatedData;
                if (!predicatedData2.TryGetValue(kvp.Key, out var value2))
                {
                    // Data predicated by the analysis entity present in only one branch.
                    // We should merge with the core non-predicate data in other branch.
                    resultTruePredicatedData  = MergeForPredicatedDataInOneBranch(kvp.Value.TruePredicatedData, coreAnalysisData2, coreDataAnalysisDomain);
                    resultFalsePredicatedData = MergeForPredicatedDataInOneBranch(kvp.Value.FalsePredicatedData, coreAnalysisData2, coreDataAnalysisDomain);
                }
                else
                {
                    // Data predicated by the analysis entity present in both branches.
                    resultTruePredicatedData = Merge(kvp.Value.TruePredicatedData, value2.TruePredicatedData,
                                                     coreAnalysisData1, coreAnalysisData2, coreDataAnalysisDomain, applyPredicatedData);
                    resultFalsePredicatedData = Merge(kvp.Value.FalsePredicatedData, value2.FalsePredicatedData,
                                                      coreAnalysisData1, coreAnalysisData2, coreDataAnalysisDomain, applyPredicatedData);
                }

                var perEntityPredicatedData = new PerEntityPredicatedAnalysisData(resultTruePredicatedData, resultFalsePredicatedData);
                result.Add(kvp.Key, perEntityPredicatedData);
            }

            foreach (var kvp in predicatedData2)
            {
                if (!predicatedData1.TryGetValue(kvp.Key, out var value2))
                {
                    // Data predicated by the analysis entity present in only one branch.
                    // We should merge with the core non-predicate data in other branch.
                    var resultTruePredicatedData  = MergeForPredicatedDataInOneBranch(kvp.Value.TruePredicatedData, coreAnalysisData1, coreDataAnalysisDomain);
                    var resultFalsePredicatedData = MergeForPredicatedDataInOneBranch(kvp.Value.FalsePredicatedData, coreAnalysisData1, coreDataAnalysisDomain);
                    var perEntityPredicatedData   = new PerEntityPredicatedAnalysisData(resultTruePredicatedData, resultFalsePredicatedData);
                    result.Add(kvp.Key, perEntityPredicatedData);
                }
            }

            return(result);
        }
Beispiel #3
0
#pragma warning restore CA1030 // Use events where appropriate

        public override DictionaryAnalysisData <TKey, TValue> Merge(DictionaryAnalysisData <TKey, TValue> value1, DictionaryAnalysisData <TKey, TValue> value2)
        {
            Debug.Assert(value1 != null);
            Debug.Assert(value2 != null);

            var result = new DictionaryAnalysisData <TKey, TValue>(value1);

            foreach (var entry in value2)
            {
                if (result.TryGetValue(entry.Key, out TValue value))
                {
                    value = ValueDomain.Merge(value, entry.Value);

                    if (value != null)
                    {
                        result[entry.Key] = value;
                    }
                    else
                    {
                        result.Remove(entry.Key);
                    }
                }
                else
                {
                    result.Add(entry.Key, entry.Value);
                }
            }

            return(result);
        }
Beispiel #4
0
        private static DictionaryAnalysisData <AnalysisEntity, PerEntityPredicatedAnalysisData> Clone(DictionaryAnalysisData <AnalysisEntity, PerEntityPredicatedAnalysisData> fromData)
        {
            if (fromData == null)
            {
                return(null);
            }

            var clonedMap = new DictionaryAnalysisData <AnalysisEntity, PerEntityPredicatedAnalysisData>();

            foreach (var kvp in fromData)
            {
                clonedMap.Add(kvp.Key, new PerEntityPredicatedAnalysisData(kvp.Value));
            }

            return(clonedMap);
        }
Beispiel #5
0
        private static DictionaryAnalysisData <AnalysisEntity, PerEntityPredicatedAnalysisData> MergeForPredicatedDataInOneBranch(
            DictionaryAnalysisData <AnalysisEntity, PerEntityPredicatedAnalysisData> predicatedData,
            DictionaryAnalysisData <TKey, TValue> coreAnalysisDataForOtherBranch,
            MapAbstractDomain <TKey, TValue> coreDataAnalysisDomain)
        {
            Debug.Assert(predicatedData != null);
            Debug.Assert(coreAnalysisDataForOtherBranch != null);

            var result = new DictionaryAnalysisData <AnalysisEntity, PerEntityPredicatedAnalysisData>();

            foreach (var kvp in predicatedData)
            {
                var resultTruePredicatedData  = MergeForPredicatedDataInOneBranch(kvp.Value.TruePredicatedData, coreAnalysisDataForOtherBranch, coreDataAnalysisDomain);
                var resultFalsePredicatedData = MergeForPredicatedDataInOneBranch(kvp.Value.FalsePredicatedData, coreAnalysisDataForOtherBranch, coreDataAnalysisDomain);
                var perEntityPredicatedData   = new PerEntityPredicatedAnalysisData(resultTruePredicatedData, resultFalsePredicatedData);
                result.Add(kvp.Key, perEntityPredicatedData);
            }

            return(result);
        }
Beispiel #6
0
        internal static DictionaryAnalysisData <TKey, TValue> Intersect(
            DictionaryAnalysisData <TKey, TValue> map1,
            DictionaryAnalysisData <TKey, TValue> map2,
            Func <TValue, TValue, TValue> intersect)
        {
            var result = new DictionaryAnalysisData <TKey, TValue>();

            if (map1.Count == 0 || map2.Count == 0)
            {
                return(result);
            }

            foreach (var kvp in map1)
            {
                if (map2.TryGetValue(kvp.Key, out var value2))
                {
                    result.Add(kvp.Key, intersect(kvp.Value, value2));
                }
            }

            return(result);
        }
Beispiel #7
0
        public override DictionaryAnalysisData <AnalysisEntity, TValue> Merge(DictionaryAnalysisData <AnalysisEntity, TValue> map1, DictionaryAnalysisData <AnalysisEntity, TValue> map2)
        {
            Debug.Assert(map1 != null);
            AssertValidAnalysisData(map1);
            Debug.Assert(map2 != null);
            AssertValidAnalysisData(map2);

            TValue GetMergedValueForEntityPresentInOneMap(AnalysisEntity key, TValue value)
            {
                if (key.HasConstantValue)
                {
                    return(value);
                }

                var defaultValue = GetDefaultValue(key);

                return(ValueDomain.Merge(value, defaultValue));
            }

            var resultMap = new DictionaryAnalysisData <AnalysisEntity, TValue>();
            var newKeys   = PooledHashSet <AnalysisEntity> .GetInstance();

            var map2LookupIgnoringInstanceLocation = map2.Keys.Where(IsAnalysisEntityForFieldOrProperty)
                                                     .ToLookup(entity => entity.EqualsIgnoringInstanceLocationId);

            foreach (var entry1 in map1)
            {
                AnalysisEntity key1   = entry1.Key;
                TValue         value1 = entry1.Value;

                if (map2LookupIgnoringInstanceLocation.Count > 0 && IsAnalysisEntityForFieldOrProperty(key1))
                {
                    var equivalentKeys2 = map2LookupIgnoringInstanceLocation[key1.EqualsIgnoringInstanceLocationId];
                    if (!equivalentKeys2.Any())
                    {
                        TValue mergedValue = GetMergedValueForEntityPresentInOneMap(key1, value1);
                        Debug.Assert(!map2.ContainsKey(key1));
                        Debug.Assert(ValueDomain.Compare(value1, mergedValue) <= 0);
                        AssertValidEntryForMergedMap(key1, mergedValue);
                        resultMap.Add(key1, mergedValue);
                        continue;
                    }

                    foreach (AnalysisEntity key2 in equivalentKeys2)
                    {
                        // Confirm that key2 and key1 are indeed EqualsIgnoringInstanceLocation
                        // This ensures that we handle hash code clashes of EqualsIgnoringInstanceLocationId.
                        if (!key1.EqualsIgnoringInstanceLocation(key2))
                        {
                            continue;
                        }

                        TValue value2      = map2[key2];
                        TValue mergedValue = ValueDomain.Merge(value1, value2);
                        Debug.Assert(ValueDomain.Compare(value1, mergedValue) <= 0);
                        Debug.Assert(ValueDomain.Compare(value2, mergedValue) <= 0);

                        if (key1.InstanceLocation.Equals(key2.InstanceLocation))
                        {
                            AssertValidEntryForMergedMap(key1, mergedValue);
                            resultMap[key1] = mergedValue;
                        }
                        else
                        {
                            if (key1.SymbolOpt == null || key1.SymbolOpt != key2.SymbolOpt)
                            {
                                // PERF: Do not add a new key-value pair to the resultMap for unrelated entities or non-symbol based entities.
                                continue;
                            }

                            AnalysisEntity mergedKey             = key1.WithMergedInstanceLocation(key2);
                            TValue         newMergedValue        = mergedValue;
                            var            isExistingKeyInInput  = false;
                            var            isExistingKeyInResult = false;
                            if (resultMap.TryGetValue(mergedKey, out var existingValue))
                            {
                                newMergedValue        = ValueDomain.Merge(newMergedValue, existingValue);
                                isExistingKeyInResult = true;
                            }

                            if (map1.TryGetValue(mergedKey, out existingValue))
                            {
                                newMergedValue       = ValueDomain.Merge(newMergedValue, existingValue);
                                isExistingKeyInInput = true;
                            }

                            if (map2.TryGetValue(mergedKey, out existingValue))
                            {
                                newMergedValue       = ValueDomain.Merge(newMergedValue, existingValue);
                                isExistingKeyInInput = true;
                            }

                            Debug.Assert(ValueDomain.Compare(value1, newMergedValue) <= 0);
                            Debug.Assert(ValueDomain.Compare(value2, newMergedValue) <= 0);
                            Debug.Assert(ValueDomain.Compare(mergedValue, newMergedValue) <= 0);
                            mergedValue = newMergedValue;

                            if (!isExistingKeyInInput && !isExistingKeyInResult && CanSkipNewEntry(mergedKey, mergedValue))
                            {
                                // PERF: Do not add a new key-value pair to the resultMap if the value can be skipped.
                                continue;
                            }

                            if (!isExistingKeyInInput)
                            {
                                newKeys.Add(mergedKey);
                            }

                            AssertValidEntryForMergedMap(mergedKey, mergedValue);
                            resultMap[mergedKey] = mergedValue;
                        }
                    }
                }
                else if (map2.TryGetValue(key1, out var value2))
                {
                    TValue mergedValue = ValueDomain.Merge(value1, value2);
                    Debug.Assert(ValueDomain.Compare(value1, mergedValue) <= 0);
                    Debug.Assert(ValueDomain.Compare(value2, mergedValue) <= 0);
                    resultMap.Add(key1, mergedValue);
                    continue;
                }

                if (!resultMap.ContainsKey(key1))
                {
                    TValue mergedValue = GetMergedValueForEntityPresentInOneMap(key1, value1);
                    Debug.Assert(ValueDomain.Compare(value1, mergedValue) <= 0);
                    AssertValidEntryForMergedMap(key1, mergedValue);
                    resultMap.Add(key1, mergedValue);
                }
            }

            foreach (var kvp in map2)
            {
                var key2   = kvp.Key;
                var value2 = kvp.Value;
                if (!resultMap.ContainsKey(key2))
                {
                    TValue mergedValue = GetMergedValueForEntityPresentInOneMap(key2, value2);
                    Debug.Assert(ValueDomain.Compare(value2, mergedValue) <= 0);
                    AssertValidEntryForMergedMap(key2, mergedValue);
                    resultMap.Add(key2, mergedValue);
                }
            }

            foreach (var newKey in newKeys)
            {
                Debug.Assert(!map1.ContainsKey(newKey));
                Debug.Assert(!map2.ContainsKey(newKey));
                if (ReferenceEquals(resultMap[newKey], GetDefaultValue(newKey)))
                {
                    resultMap.Remove(newKey);
                }
            }

            newKeys.Free();

            Debug.Assert(Compare(map1, resultMap) <= 0);
            Debug.Assert(Compare(map2, resultMap) <= 0);
            AssertValidAnalysisData(resultMap);

            return(resultMap);

            bool IsAnalysisEntityForFieldOrProperty(AnalysisEntity entity)
            => entity.SymbolOpt?.Kind == SymbolKind.Field || entity.SymbolOpt?.Kind == SymbolKind.Property;
        }