示例#1
0
        public bool CreateForwardReferences(ClrHeap heap, out string error)
        {
            const string progressHeader = Constants.HeavyAsteriskHeader + "[FwdRefs] ";

            error = null;
            int          nullCount = 0;
            BinaryWriter bwFwdRefs = null, bwFwdOffs = null;

            _reflagSet = new BitSet(_instances.Length);
            //_reflagSet = new HashSet<int>();
            try
            {
                _stopWatch = new Stopwatch();
                _stopWatch.Start();
                _progress?.Report(progressHeader + "Creating forward references data...");
                _reversedRefsCounts = new int[_instances.Length];
                _forwardRefsCounts  = new int[_instances.Length];
                int lastInstanceNdx = _instances.Length - 1; // for binary search
                bwFwdRefs = GetWriter(RefFile.FwdRefs, FileMode.Create);
                bwFwdOffs = GetWriter(RefFile.FwdOffsets, FileMode.Create);
                long offset = 0L;

                var fieldAddrOffsetList = new List <ulong>(64);
                for (int i = 0, icnt = _instances.Length; i < icnt; ++i)
                {
                    var addr    = Utils.RealAddress(_instances[i]);
                    var clrType = heap.GetObjectType(addr);
                    //Debug.Assert(clrType != null); // TODO JRD restore this
                    bwFwdOffs.Write(offset);

                    if (clrType == null)
                    {
                        ++nullCount; continue;
                    }
                    if (TypeExtractor.IsExludedType(clrType.Name))
                    {
                        continue;
                    }

                    fieldAddrOffsetList.Clear();
                    clrType.EnumerateRefsOfObjectCarefully(addr, (address, off) =>
                    {
                        fieldAddrOffsetList.Add(address);
                    });
                    if (fieldAddrOffsetList.Count < 1)
                    {
                        continue;
                    }

                    int acount = PreprocessParentRefs(addr, fieldAddrOffsetList);
                    if (acount == 0)
                    {
                        continue;
                    }

                    offset += acount * sizeof(int);
                    _forwardRefsCounts[i] += acount;

                    int parentNdx = Utils.AddressSearch(_instances, addr);
                    Debug.Assert(parentNdx >= 0);
                    for (int j = 0; j < acount; ++j)
                    {
                        ulong childAddr = fieldAddrOffsetList[j];
                        int   childNdx  = Utils.AddressSearch(_instances, childAddr);
                        Debug.Assert(childNdx >= 0);
                        if (copy_addr_flags_check(_instances, parentNdx, childNdx))
                        {
                            _reflagSet.Set(childNdx);
                            //_reflagSet.Add(childNdx);
                        }
                        _reversedRefsCounts[childNdx] += 1; // update reversed references count
                        ++_totalReversedRefs;
                        bwFwdRefs.Write(childNdx);
                    }
                }
                bwFwdOffs.Write(offset);
                _progress?.Report(progressHeader + "Creating forward references data done. " + Utils.StopAndGetDurationStringAndRestart(_stopWatch));
                _progress?.Report(progressHeader + "UNEXPECTED NULLS, count: " + nullCount);
                return(true);
            }
            catch (Exception ex)
            {
                error = Utils.GetExceptionErrorString(ex);
                _progress?.Report(progressHeader + "EXCEPTION: " + ex.Message);
                return(false);
            }
            finally
            {
                bwFwdRefs?.Close();
                bwFwdOffs?.Close();
            }
        }