Esempio n. 1
0
        /// <summary>
        /// Fetches the information we know about a particular object given its address in memory.  Note that our
        /// understanding of what generation an object is in may not be completely in sync with the GCs.
        /// </summary>
        public GCHeapSimulatorObject GetObjectInfo(Address objectAddress, out int gen)
        {
            GCHeapSimulatorObject ret = null;

            // Start in Gen 2 since you most objects will be there.
            for (int i = 2; 0 <= i; --i)
            {
                if (m_ObjsInGen[i].TryGetValue(objectAddress, out ret))
                {
                    gen = i;
                    return(ret);
                }
            }
            gen = 0;
            return(ret);
        }
Esempio n. 2
0
        /// <summary>
        /// Takes the set of objects (a plug) in the region from 'fromPtr' to fromEnd, and relocates the objects to new address 'toPtr'.
        /// It also places the objects into whatever generation it is current in to m_condemedGenerationNum+1.
        /// Note that while our understanding of where what generation an object is might differ from the GC's idea, (we ALWAYS promote
        /// to a m_condemedGenerationNum+1 where the GC might not), this does not affect the movement/liveness calculation.
        /// </summary>
        private void CopyPlugToNextGen(Address fromPtr, Address fromEnd, Address toPtr)
        {
            Address origFromPtr = fromPtr;      // Only used for asserts.

            Debug.Assert(m_condemedGenerationNum <= 2);
            var toGen = m_ObjsInGen[m_condemedGenerationNum + 1];     // We always put the survived objects in the generation after the one condemned.

            // For every object in the plug
            int fromGenNum = m_condemedGenerationNum;               // This is the starting point where we search for an objects generation.

            Debug.WriteLine(string.Format("Plug {0:x} - {1:x} going to {2:x}", fromPtr, fromEnd, toPtr));
            int pointerSizeMask = m_pointerSize - 1;

            while (fromPtr < fromEnd)
            {
                // Find the generation in the condemned region where the object lives, start the search where we
                // looked last time because it tends to find it quicker
                int genStartSearch = fromGenNum;
                // TODO: in the sampling case, when you miss we only increment by the pointer size, which is pretty inefficient.
                // if we has a sorted table, we could do much better.
                uint sizeToNextObj = (uint)m_pointerSize;
                bool foundGen      = false;         // once we have found the generation for a plug, we don't have to search.
                for (; ;)
                {
                    var fromGen = m_ObjsInGen[fromGenNum];
                    GCHeapSimulatorObject objInfo = null;
                    if (fromGen.TryGetValue(fromPtr, out objInfo))
                    {
                        foundGen      = true;
                        sizeToNextObj = (uint)((objInfo.Size + pointerSizeMask) & ~pointerSizeMask);
                        if (sizeToNextObj < (uint)m_pointerSize)
                        {
                            sizeToNextObj = (uint)m_pointerSize;
                        }

                        if (fromGenNum > m_condemedGenerationNum)
                        {
                            Debug.WriteLine(string.Format("Found in old generation, already alive."));
                        }

                        // Note even if we find this in in an non-condemned generation we do the logic to move it because we basically were incorrect
                        // to have put it in the older generation (the GC obviously had demoted the plug).
                        fromGen.Remove(fromPtr);              // Remove it from the current generation
                        toGen[toPtr] = objInfo;               // Copy survived data into next generation
                        Debug.WriteLine(string.Format("Object Survived {0:x} -> {1:x}", fromPtr, toPtr));
                        break;
                    }

                    // Once we have found a plug's generation everything in the plug will have the same gen, so we don't
                    // need to search more than once before we fail in that case.
                    if (foundGen)
                    {
                        break;
                    }

                    --fromGenNum;               // decrement with wrap around.
                    if (fromGenNum < 0)
                    {
                        fromGenNum = 2;         // We search all generations not just condemned because things may be demoted and we want to walk the plug efficiently.
                    }

                    if (genStartSearch != fromGenNum)
                    {
                        // Debug.Assert(false, "Error, could not find first object in plug, skipping and continuing.");
                        break;
                    }
                }

                if (sizeToNextObj == m_pointerSize)
                {
                    Debug.WriteLine(string.Format("Synching {0:x}", fromPtr));
                }

                fromPtr += sizeToNextObj;
                toPtr   += sizeToNextObj;
            }
        }