コード例 #1
0
        /// <summary>
        /// Tries to get an analysis result of a particular type.
        /// </summary>
        /// <param name="graph">
        /// The current flow graph.
        /// </param>
        /// <param name="result">
        /// The analysis result, if one can be fetched or computed.
        /// </param>
        /// <typeparam name="T">
        /// The type of analysis result to fetch or compute.
        /// </typeparam>
        /// <returns>
        /// <c>true</c> if there is an analyzer to compute the result;
        /// otherwise, <c>false</c>.
        /// </returns>
        public bool TryGetResultAs <T>(FlowGraph graph, out T result)
        {
            var t = typeof(T);

            FlowGraphAnalysisCache cache = null;

            updateLock.EnterReadLock();
            try
            {
                int cacheIndex;
                if (cacheIndices.TryGetValue(t, out cacheIndex))
                {
                    cache = distinctCaches[cacheIndex];
                }
            }
            finally
            {
                updateLock.ExitReadLock();
            }

            if (cache != null || TryRegisterDefaultAnalysis(t, graph, out cache))
            {
                result = cache.GetResultAs <T>(graph);
                return(true);
            }
            else
            {
                result = default(T);
                return(false);
            }
        }
コード例 #2
0
 /// <summary>
 /// Creates a new analysis cache that incorporates a particular
 /// analysis.
 /// </summary>
 /// <param name="analysis">
 /// The analysis to include in the new analysis cache.
 /// </param>
 /// <typeparam name="T">
 /// The result type of the analysis.
 /// </typeparam>
 /// <returns>
 /// A new analysis cache.
 /// </returns>
 public MacroAnalysisCache WithAnalysis <T>(IFlowGraphAnalysis <T> analysis)
 {
     updateLock.EnterReadLock();
     try
     {
         var cache = new FlowGraphAnalysisCache <T>(analysis);
         return(WithAnalysis(typeof(T), cache, true));
     }
     finally
     {
         updateLock.ExitReadLock();
     }
 }
コード例 #3
0
ファイル: DefaultAnalyses.cs プロジェクト: anthrax3/Flame
        /// <summary>
        /// Creates the default flow graph analysis cache for a particular type of analysis,
        /// given a particular control-flow graph. Returns a Boolean that tells if this
        /// function was successful.
        /// </summary>
        /// <param name="type">The type of analysis to get an analysis cache for.</param>
        /// <param name="graph">The graph to tailor the analysis to.</param>
        /// <param name="result">An analysis cache, if one can be created.</param>
        /// <returns>
        /// <c>true</c> if a default analysis is registered for <paramref name="type"/>;
        /// otherwise, <c>false</c>.</returns>
        internal static bool TryGetDefaultAnalysisCache(
            Type type, FlowGraph graph, out FlowGraphAnalysisCache result)
        {
            Func <FlowGraph, FlowGraphAnalysisCache> create;

            if (defaults.TryGetValue(type, out create))
            {
                result = create(graph);
                return(true);
            }
            else
            {
                result = null;
                return(false);
            }
        }
コード例 #4
0
 private bool TryRegisterDefaultAnalysis(Type t, FlowGraph graph, out FlowGraphAnalysisCache cache)
 {
     updateLock.EnterWriteLock();
     try
     {
         if (DefaultAnalyses.TryGetDefaultAnalysisCache(t, graph, out cache))
         {
             var newMacroCache = WithAnalysis(t, cache, false);
             this.cacheIndices   = newMacroCache.cacheIndices;
             this.cacheRefCounts = newMacroCache.cacheRefCounts;
             this.distinctCaches = newMacroCache.distinctCaches;
             return(true);
         }
         else
         {
             return(false);
         }
     }
     finally
     {
         updateLock.ExitWriteLock();
     }
 }
コード例 #5
0
        private MacroAnalysisCache WithAnalysis(
            Type t,
            FlowGraphAnalysisCache cache,
            bool overwrite)
        {
            // Figure out which types the analysis is assignable to.
            var resultTypes = GetAssignableTypes(t);

            // Decrement reference counts for those types and maintain
            // a list of all cache indices with a reference count of zero.
            var cacheRefCountsBuilder = cacheRefCounts.ToBuilder();

            var danglingCaches = new List <int>();

            if (overwrite)
            {
                // Decrement analysis cache reference counts. Add unreferenced
                // analysis caches to a list of dangling caches.
                foreach (var type in resultTypes)
                {
                    int cacheIndex;
                    if (cacheIndices.TryGetValue(type, out cacheIndex))
                    {
                        int refCount = cacheRefCountsBuilder[cacheIndex];
                        refCount--;
                        cacheRefCountsBuilder[cacheIndex] = refCount;
                        if (refCount == 0)
                        {
                            danglingCaches.Add(cacheIndex);
                        }
                    }
                }
            }

            // The next thing we want to do is insert the new analysis cache
            // and maybe do some cleanup if we really have to.
            int newCacheIndex;
            var newCaches = new List <FlowGraphAnalysisCache>(distinctCaches);

            var cacheIndicesBuilder = cacheIndices.ToBuilder();

            int danglingCacheCount = danglingCaches.Count;

            if (danglingCacheCount > 0)
            {
                // If at least one cache has become a dangling cache, then
                // we can replace it with the new analysis' cache.
                newCacheIndex            = danglingCaches[danglingCacheCount - 1];
                newCaches[newCacheIndex] = cache;
                danglingCaches.RemoveAt(danglingCacheCount - 1);
                danglingCacheCount--;

                // If we have more than one dangling cache, then we'll have to
                // delete all but one of them (one gets overwritten) and rewrite
                // all indices into the cache list.
                //
                // That's pretty expensive, but it should also be very rare.
                if (danglingCacheCount > 0)
                {
                    // Efficiently delete all dangling caches from the list
                    // of caches and also construct a mapping of old indices
                    // to new indices.
                    var indexRemapping   = new int[newCaches.Count];
                    var newCacheList     = new List <FlowGraphAnalysisCache>();
                    var danglingCacheSet = new HashSet <int>(danglingCaches);
                    int newIndex         = 0;
                    for (int i = 0; i < newCaches.Count; i++)
                    {
                        indexRemapping[i] = newIndex;
                        if (!danglingCacheSet.Contains(i))
                        {
                            newIndex++;
                            newCacheList.Add(newCaches[i]);
                        }
                    }
                    newCaches     = newCacheList;
                    newCacheIndex = indexRemapping [newCacheIndex];

                    // Rewrite indices into the cache list.
                    foreach (var pair in cacheIndices)
                    {
                        cacheIndicesBuilder[pair.Key] = indexRemapping[pair.Value];
                    }

                    // Rewrite reference counts.
                    var newRefCountsBuilder = ImmutableDictionary.CreateBuilder <int, int>();
                    foreach (var pair in cacheRefCountsBuilder)
                    {
                        if (!danglingCacheSet.Contains(pair.Key))
                        {
                            newRefCountsBuilder[indexRemapping[pair.Key]] = pair.Value;
                        }
                    }
                    cacheRefCountsBuilder = newRefCountsBuilder;
                }
            }
            else
            {
                // Otherwise, just add the new cache to the list.
                newCacheIndex = newCaches.Count;
                newCaches.Add(cache);
            }

            // Update the type-to-cache-index dictionary and increment
            // the new cache's reference count.
            int newRefCount = 0;

            foreach (var type in resultTypes)
            {
                if (overwrite || !cacheIndicesBuilder.ContainsKey(type))
                {
                    cacheIndicesBuilder[type] = newCacheIndex;
                    newRefCount++;
                }
            }
            cacheRefCountsBuilder[newCacheIndex] = newRefCount;

            return(new MacroAnalysisCache(
                       newCaches,
                       cacheIndicesBuilder.ToImmutable(),
                       cacheRefCountsBuilder.ToImmutable()));
        }