PeerInfo GetLastOrCreatePeerInfo(Match m, JniHandleInfo newHandle) { var h = GetHandle(m, "handle"); var i = alive.FindLastIndex(p => p.Handles.Contains(h)); if (i >= 0) { return(alive [i]); } var pid = m.Groups ["pid"].Value; var peer = new PeerInfo(pid) { CreatedOnThread = m.Groups ["thread"].Value, Handles = { newHandle, }, // Not *technically* removed, but `h` can't appear in Handles either, because of possible handle "reuse" RemovedHandles = { h, }, }; allocated.Add(peer); alive.Add(peer); return(peer); }
PeerInfo GetPeerInfo(Match m) { var h = GetHandle(m, "handle"); var i = allocated.FindLastIndex(p => p.Handles.Contains(h)); if (i >= 0) { return(allocated [i]); } var pid = m.Groups ["pid"].Value; var peer = new PeerInfo(pid) { CreatedOnThread = m.Groups ["thread"].Value, Handles = { h, }, }; allocated.Add(peer); return(peer); }
Dictionary <Regex, Action <Match, int> > CreateHandlers(int?pid) { string pidv = pid.HasValue ? pid.ToString() : @"\d+"; string addGm = string.Format(AddGrefFormat, pidv); string addWm = string.Format(AddWgrefFormat, pidv); string atm = string.Format(AtFormat, pidv); string dm = string.Format(DisposingFormat, pidv); string fm = string.Format(FinalizingFormat, pidv); string hm = string.Format(HandleFormat, pidv); string remGm = string.Format(RemoveGrefFormat, pidv); string remWm = string.Format(RemoveWgrefFormat, pidv); PeerInfo curPeer = null; JniHandleInfo curHandle = default(JniHandleInfo); return(new Dictionary <Regex, Action <Match, int> > { { new Regex(addGm), (m, l) => { var h = GetHandle(m, "ghandle"); var p = GetPeerInfo(m); p.AppendStackTraceForHandle(h, m.Groups ["stack"].Value); GlobalRefs.Add(h); CheckCounts(m, l); curPeer = p; curHandle = h; } }, { new Regex(addWm), (m, l) => { var h = GetHandle(m, "whandle"); var p = GetPeerInfo(m); p.AppendStackTraceForHandle(h, m.Groups ["stack"].Value); WeakRefs.Add(h); CheckCounts(m, l); curPeer = p; curHandle = h; } }, { new Regex(dm), (m, l) => { var p = GetPeerInfo(m); p.Disposed = true; } }, { new Regex(fm), (m, l) => { var p = GetPeerInfo(m); p.Finalized = true; } }, { new Regex(hm), (m, l) => { var p = GetPeerInfo(m); p.KeyHandle = m.Groups ["key_handle"].Value; p.JniType = m.Groups ["jtype"].Value; p.McwType = m.Groups ["mtype"].Value; } }, { new Regex(remGm), (m, l) => { var h = GetHandle(m, "handle"); var p = GetPeerInfo(m); GlobalRefs.Remove(h); if (!WeakRefs.Any(w => p.Handles.Contains(w))) { p.Collected = true; p.DestroyedOnThread = m.Groups ["thread"].Value; } CheckCounts(m, l); curPeer = null; curHandle = default(JniHandleInfo); } }, { new Regex(remWm), (m, l) => { var h = GetHandle(m, "handle"); var p = GetPeerInfo(m); WeakRefs.Remove(h); if (!GlobalRefs.Any(g => p.Handles.Contains(g))) { p.Collected = true; p.DestroyedOnThread = m.Groups ["thread"].Value; } CheckCounts(m, l); curPeer = null; curHandle = default(JniHandleInfo); } }, { new Regex(atm), (m, l) => { if (curPeer == null || curHandle == null) { return; } curPeer.AppendStackTraceForHandle(curHandle, m.Groups ["stack"].Value); } }, }); }
Dictionary <Regex, Action <Match, int> > CreateHandlers(int?pid) { string pidv = pid.HasValue ? pid.ToString() : @"\d+"; string addGm = string.Format(AddGrefFormat, pidv); string addWm = string.Format(AddWgrefFormat, pidv); string atm = string.Format(AtFormat, pidv); string dm = string.Format(DisposingFormat, pidv); string fm = string.Format(FinalizingFormat, pidv); string hm = string.Format(HandleFormat, pidv); string remGm = string.Format(RemoveGrefFormat, pidv); string remWm = string.Format(RemoveWgrefFormat, pidv); PeerInfo curPeer = null; JniHandleInfo curHandle = default(JniHandleInfo); return(new Dictionary <Regex, Action <Match, int> > { { new Regex(addGm), (m, l) => { var h = GetHandle(m, "ghandle"); var p = GetLastOrCreatePeerInfo(m, h); p.AppendStackTraceForHandle(h, m.Groups ["stack"].Value); GlobalRefs.Add(h); CheckCounts(m, l); curPeer = p; curHandle = h; } }, { new Regex(addWm), (m, l) => { var h = GetHandle(m, "whandle"); var p = GetLastOrCreatePeerInfo(m, h); p.AppendStackTraceForHandle(h, m.Groups ["stack"].Value); WeakRefs.Add(h); CheckCounts(m, l); curPeer = p; curHandle = h; } }, { new Regex(dm), (m, l) => { var p = GetAlivePeerInfo(m); if (p == null) { LogWarning(GrefParseOptions.CheckAlivePeers, $"at line {l}: could not find PeerInfo for disposed handle {GetHandle (m, "handle")}"); return; } p.Disposed = true; } }, { new Regex(fm), (m, l) => { var p = GetAlivePeerInfo(m); if (p == null) { LogWarning(GrefParseOptions.CheckAlivePeers, $"at line {l}: could not find PeerInfo for finalized handle {GetHandle (m, "handle")}"); return; } p.Finalized = true; } }, { new Regex(hm), (m, l) => { var p = GetAlivePeerInfo(m); if (p == null) { LogWarning(GrefParseOptions.CheckAlivePeers, $"at line {l}: could not find PeerInfo for handle {GetHandle (m, "handle")}"); return; } if (!string.IsNullOrEmpty(p.KeyHandle)) { LogWarning(GrefParseOptions.CheckAlivePeers, $"at line {l}: Attempting to re-set p.KeyHandle {p.KeyHandle} for `{p.JniType}` to {m.Groups ["key_handle"].Value} for {m.Groups ["jtype"].Value}"); return; } p.KeyHandle = m.Groups ["key_handle"].Value; p.JniType = m.Groups ["jtype"].Value; p.McwType = m.Groups ["mtype"].Value; } }, { new Regex(remGm), (m, l) => { var h = GetHandle(m, "handle"); var p = GetAlivePeerInfo(m); if (p == null) { LogWarning(GrefParseOptions.CheckAlivePeers, $"at line {l}: could not find PeerInfo to remove gref for handle {h}"); } GlobalRefs.Remove(h); if (p != null) { p.Handles.Remove(h); p.RemovedHandles.Add(h); } if (p != null && !WeakRefs.Any(w => p.Handles.Contains(w))) { p.Collected = true; p.DestroyedOnThread = m.Groups ["thread"].Value; alive.Remove(p); } CheckCounts(m, l); curPeer = null; curHandle = default(JniHandleInfo); } }, { new Regex(remWm), (m, l) => { var h = GetHandle(m, "handle"); var p = GetAlivePeerInfo(m); WeakRefs.Remove(h); if (p == null) { // Means that the instance has been collected; this is fine. } else { p.Handles.Remove(h); p.RemovedHandles.Add(h); if (!GlobalRefs.Any(g => p.Handles.Contains(g))) { p.Collected = true; p.DestroyedOnThread = m.Groups ["thread"].Value; alive.Remove(p); } } CheckCounts(m, l); curPeer = null; curHandle = default(JniHandleInfo); } }, { new Regex(atm), (m, l) => { if (curPeer == null || curHandle == null) { return; } curPeer.AppendStackTraceForHandle(curHandle, m.Groups ["stack"].Value); } }, }); }