@@ -16,9 +16,12 @@ public class SnapshotFile : LowLevelSnapshotFile
1616
1717 public readonly Dictionary < int , int > TypeIndexIndices = new ( ) ; // TypeIndex -> Index in the TypeIndex array. What.
1818
19+ public readonly Dictionary < int , int > StaticFieldsToOwningTypes = new ( ) ;
20+
1921 public readonly WellKnownTypeHelper WellKnownTypes ;
2022
2123 private readonly Dictionary < int , BasicFieldInfoCache [ ] > _nonStaticFieldIndicesByTypeIndex = new ( ) ;
24+ private readonly Dictionary < int , BasicFieldInfoCache [ ] > _staticFieldIndicesByTypeIndex = new ( ) ;
2225
2326 private readonly Dictionary < int , BasicTypeInfoCache > _typeInfoCacheByTypeIndex = new ( ) ;
2427
@@ -45,6 +48,74 @@ public SnapshotFile(string path) : base(path)
4548 TypeIndexIndices . Add ( indices [ i ] , i ) ;
4649 }
4750
51+ public void LoadManagedObjectsFromGcRoots ( )
52+ {
53+ var gcRoots = GcHandles ;
54+ var start = DateTime . Now ;
55+
56+ Console . WriteLine ( $ "Processing { gcRoots . Length } GC roots...") ;
57+ foreach ( var gcHandle in gcRoots )
58+ GetOrCreateManagedClassInstance ( gcHandle ) ;
59+
60+ Console . WriteLine ( $ "Found { _managedClassInstanceCache . Count } managed objects in { ( DateTime . Now - start ) . TotalMilliseconds } ms") ;
61+ }
62+
63+ public void LoadManagedObjectsFromStaticFields ( )
64+ {
65+ var allStaticFields = ReadValueTypeArrayChapter < byte > ( EntryType . TypeDescriptions_StaticFieldBytes , 0 , - 1 ) ;
66+
67+ var start = DateTime . Now ;
68+ var initialCount = _managedClassInstanceCache . Count ;
69+
70+ Console . WriteLine ( $ "Processing static field info for { allStaticFields . Length } types...") ;
71+ for ( var typeIndex = 0 ; typeIndex < allStaticFields . Length ; typeIndex ++ )
72+ {
73+ var typeFieldBytes = allStaticFields [ typeIndex ] . AsSpan ( ) ;
74+ if ( typeFieldBytes . Length == 0 )
75+ continue ;
76+
77+ var typeInfo = GetTypeInfo ( typeIndex ) ;
78+ var staticFields = GetStaticFieldInfoForTypeIndex ( typeIndex ) ;
79+
80+ foreach ( var field in staticFields )
81+ {
82+ StaticFieldsToOwningTypes [ field . FieldIndex ] = typeIndex ;
83+ if ( field . IsValueType )
84+ continue ; //TODO
85+
86+ if ( field . IsArray )
87+ continue ;
88+
89+ var fieldOffset = field . FieldOffset ;
90+
91+ if ( fieldOffset < 0 )
92+ continue ; //Generics, mainly
93+
94+ var fieldPointer = MemoryMarshal . Read < ulong > ( typeFieldBytes [ fieldOffset ..] ) ;
95+ if ( fieldPointer == 0 )
96+ continue ;
97+
98+ GetOrCreateManagedClassInstance ( fieldPointer , reason : LoadedReason . StaticField , fieldOrArrayIdx : field . FieldIndex ) ;
99+ }
100+ }
101+
102+ Console . WriteLine ( $ "Found { _managedClassInstanceCache . Count - initialCount } additional managed objects from static fields in { ( DateTime . Now - start ) . TotalMilliseconds } ms") ;
103+ }
104+
105+ public ManagedClassInstance ? GetOrCreateManagedClassInstance ( ulong address , ManagedClassInstance ? parent = null , int depth = 0 , LoadedReason reason = LoadedReason . GcRoot , int fieldOrArrayIdx = int . MinValue )
106+ {
107+ if ( _managedClassInstanceCache . TryGetValue ( address , out var ret ) )
108+ return ret ;
109+
110+ var info = ParseManagedObjectInfo ( address ) ;
111+ if ( ! info . IsKnownType )
112+ return null ;
113+
114+ var instance = new ManagedClassInstance ( this , info , parent , depth , reason , fieldOrArrayIdx ) ;
115+ _managedClassInstanceCache [ address ] = instance ;
116+ return instance ;
117+ }
118+
48119 public RawManagedObjectInfo ParseManagedObjectInfo ( ulong address )
49120 {
50121 if ( _managedObjectInfoCache . TryGetValue ( address , out var ret ) )
@@ -78,20 +149,6 @@ public RawManagedObjectInfo ParseManagedObjectInfo(ulong address)
78149
79150 return info ;
80151 }
81-
82- public ManagedClassInstance ? GetManagedClassInstance ( ulong address , ManagedClassInstance ? parent = null , int depth = 0 , LoadedReason reason = LoadedReason . GcRoot , int fieldOrArrayIdx = int . MinValue )
83- {
84- if ( _managedClassInstanceCache . TryGetValue ( address , out var ret ) )
85- return ret ;
86-
87- var info = ParseManagedObjectInfo ( address ) ;
88- if ( ! info . IsKnownType )
89- return null ;
90-
91- var instance = new ManagedClassInstance ( this , info , parent , depth , reason , fieldOrArrayIdx ) ;
92- _managedClassInstanceCache [ address ] = instance ;
93- return instance ;
94- }
95152
96153 public int SizeOfObjectInBytes ( RawManagedObjectInfo info , Span < byte > heap )
97154 {
@@ -247,30 +304,43 @@ public BasicTypeInfoCache GetTypeInfo(int typeIndex)
247304 return info ;
248305 }
249306
250- public BasicFieldInfoCache [ ] GetFieldInfoForTypeIndex ( int typeIndex )
307+ public BasicFieldInfoCache [ ] GetInstanceFieldInfoForTypeIndex ( int typeIndex )
251308 {
252309 if ( _nonStaticFieldIndicesByTypeIndex . TryGetValue ( typeIndex , out var indices ) )
253310 return indices ;
254311
255- _nonStaticFieldIndicesByTypeIndex [ typeIndex ] = indices = WalkFieldInfoForTypeIndex ( typeIndex ) . ToArray ( ) ;
312+ _nonStaticFieldIndicesByTypeIndex [ typeIndex ] = indices = WalkFieldInfoForTypeIndex ( typeIndex , false ) . ToArray ( ) ;
313+
314+ return indices ;
315+ }
316+
317+ public BasicFieldInfoCache [ ] GetStaticFieldInfoForTypeIndex ( int typeIndex )
318+ {
319+ if ( _staticFieldIndicesByTypeIndex . TryGetValue ( typeIndex , out var indices ) )
320+ return indices ;
321+
322+ _staticFieldIndicesByTypeIndex [ typeIndex ] = indices = WalkFieldInfoForTypeIndex ( typeIndex , true ) . ToArray ( ) ;
256323
257324 return indices ;
258325 }
259326
260- public IEnumerable < BasicFieldInfoCache > WalkFieldInfoForTypeIndex ( int typeIndex )
327+ public IEnumerable < BasicFieldInfoCache > WalkFieldInfoForTypeIndex ( int typeIndex , bool wantStatic )
261328 {
262- var baseTypeIndex = ReadSingleValueType < int > ( EntryType . TypeDescriptions_BaseOrElementTypeIndex , typeIndex ) ;
263- if ( baseTypeIndex != - 1 )
329+ if ( ! wantStatic )
264330 {
265- foreach ( var i in GetFieldInfoForTypeIndex ( baseTypeIndex ) )
266- yield return i ;
331+ var baseTypeIndex = ReadSingleValueType < int > ( EntryType . TypeDescriptions_BaseOrElementTypeIndex , typeIndex ) ;
332+ if ( baseTypeIndex != - 1 )
333+ {
334+ foreach ( var i in GetInstanceFieldInfoForTypeIndex ( baseTypeIndex ) )
335+ yield return i ;
336+ }
267337 }
268338
269339 var fieldIndices = ReadSingleValueTypeArrayChapterElement < int > ( EntryType . TypeDescriptions_FieldIndices , typeIndex ) . ToArray ( ) ;
270340 foreach ( var fieldIndex in fieldIndices )
271341 {
272342 var isStatic = ReadSingleValueType < bool > ( EntryType . FieldDescriptions_IsStatic , fieldIndex ) ;
273- if ( isStatic )
343+ if ( isStatic != wantStatic )
274344 continue ;
275345
276346 var fieldOffset = ReadSingleValueType < int > ( EntryType . FieldDescriptions_Offset , fieldIndex ) ;
0 commit comments