@@ -16,9 +16,12 @@ public class SnapshotFile : LowLevelSnapshotFile
16
16
17
17
public readonly Dictionary < int , int > TypeIndexIndices = new ( ) ; // TypeIndex -> Index in the TypeIndex array. What.
18
18
19
+ public readonly Dictionary < int , int > StaticFieldsToOwningTypes = new ( ) ;
20
+
19
21
public readonly WellKnownTypeHelper WellKnownTypes ;
20
22
21
23
private readonly Dictionary < int , BasicFieldInfoCache [ ] > _nonStaticFieldIndicesByTypeIndex = new ( ) ;
24
+ private readonly Dictionary < int , BasicFieldInfoCache [ ] > _staticFieldIndicesByTypeIndex = new ( ) ;
22
25
23
26
private readonly Dictionary < int , BasicTypeInfoCache > _typeInfoCacheByTypeIndex = new ( ) ;
24
27
@@ -45,6 +48,74 @@ public SnapshotFile(string path) : base(path)
45
48
TypeIndexIndices . Add ( indices [ i ] , i ) ;
46
49
}
47
50
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
+
48
119
public RawManagedObjectInfo ParseManagedObjectInfo ( ulong address )
49
120
{
50
121
if ( _managedObjectInfoCache . TryGetValue ( address , out var ret ) )
@@ -78,20 +149,6 @@ public RawManagedObjectInfo ParseManagedObjectInfo(ulong address)
78
149
79
150
return info ;
80
151
}
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
- }
95
152
96
153
public int SizeOfObjectInBytes ( RawManagedObjectInfo info , Span < byte > heap )
97
154
{
@@ -247,30 +304,43 @@ public BasicTypeInfoCache GetTypeInfo(int typeIndex)
247
304
return info ;
248
305
}
249
306
250
- public BasicFieldInfoCache [ ] GetFieldInfoForTypeIndex ( int typeIndex )
307
+ public BasicFieldInfoCache [ ] GetInstanceFieldInfoForTypeIndex ( int typeIndex )
251
308
{
252
309
if ( _nonStaticFieldIndicesByTypeIndex . TryGetValue ( typeIndex , out var indices ) )
253
310
return indices ;
254
311
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 ( ) ;
256
323
257
324
return indices ;
258
325
}
259
326
260
- public IEnumerable < BasicFieldInfoCache > WalkFieldInfoForTypeIndex ( int typeIndex )
327
+ public IEnumerable < BasicFieldInfoCache > WalkFieldInfoForTypeIndex ( int typeIndex , bool wantStatic )
261
328
{
262
- var baseTypeIndex = ReadSingleValueType < int > ( EntryType . TypeDescriptions_BaseOrElementTypeIndex , typeIndex ) ;
263
- if ( baseTypeIndex != - 1 )
329
+ if ( ! wantStatic )
264
330
{
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
+ }
267
337
}
268
338
269
339
var fieldIndices = ReadSingleValueTypeArrayChapterElement < int > ( EntryType . TypeDescriptions_FieldIndices , typeIndex ) . ToArray ( ) ;
270
340
foreach ( var fieldIndex in fieldIndices )
271
341
{
272
342
var isStatic = ReadSingleValueType < bool > ( EntryType . FieldDescriptions_IsStatic , fieldIndex ) ;
273
- if ( isStatic )
343
+ if ( isStatic != wantStatic )
274
344
continue ;
275
345
276
346
var fieldOffset = ReadSingleValueType < int > ( EntryType . FieldDescriptions_Offset , fieldIndex ) ;
0 commit comments