@@ -48,7 +48,8 @@ internal sealed class ModuleData
48
48
{
49
49
public Guid Mvid ;
50
50
public AssemblyDefinition Assembly ;
51
- public List < TypeMapEntry > Types ;
51
+ public SortedDictionary < string , TypeMapEntry > Types ;
52
+ public Dictionary < uint , TypeMapEntry > DuplicateTypes ;
52
53
public string AssemblyName ;
53
54
public string AssemblyNameLabel ;
54
55
public string OutputFilePath ;
@@ -124,7 +125,8 @@ public bool Generate (DirectoryAssemblyResolver resolver, IEnumerable<string> as
124
125
Mvid = td . Module . Mvid ,
125
126
Assembly = td . Module . Assembly ,
126
127
AssemblyName = td . Module . Assembly . Name . Name ,
127
- Types = new List < TypeMapEntry > ( ) ,
128
+ Types = new SortedDictionary < string , TypeMapEntry > ( StringComparer . Ordinal ) ,
129
+ DuplicateTypes = new Dictionary < uint , TypeMapEntry > ( ) ,
128
130
} ;
129
131
modules . Add ( moduleUUID , moduleData ) ;
130
132
@@ -151,14 +153,18 @@ public bool Generate (DirectoryAssemblyResolver resolver, IEnumerable<string> as
151
153
maxJavaNameLength = javaName . Length ;
152
154
}
153
155
154
- moduleData . Types . Add (
155
- new TypeMapEntry {
156
- JavaName = javaName ,
157
- ManagedTypeName = td . FullName ,
158
- Token = td . MetadataToken . ToUInt32 ( ) ,
159
- AssemblyNameIndex = knownAssemblies [ assemblyName ]
160
- }
161
- ) ;
156
+ var entry = new TypeMapEntry {
157
+ JavaName = javaName ,
158
+ ManagedTypeName = td . FullName ,
159
+ Token = td . MetadataToken . ToUInt32 ( ) ,
160
+ AssemblyNameIndex = knownAssemblies [ assemblyName ]
161
+ } ;
162
+
163
+ if ( moduleData . Types . ContainsKey ( entry . JavaName ) ) {
164
+ logger ( $ "Warning: duplicate Java type name '{ entry . JavaName } ' (new token: { entry . Token } ).") ;
165
+ moduleData . DuplicateTypes . Add ( entry . Token , entry ) ;
166
+ } else
167
+ moduleData . Types . Add ( entry . JavaName , entry ) ;
162
168
}
163
169
164
170
NativeTypeMappingData data ;
@@ -269,15 +275,17 @@ void OutputModule (string outputDirectory, byte[] moduleUUID, ModuleData moduleD
269
275
270
276
// Binary file format, all data is little-endian:
271
277
//
272
- // [Magic string] # XATM
273
- // [Format version] # 32-bit integer, 4 bytes
274
- // [Module UUID] # 16 bytes
275
- // [Entry count] # 32-bit integer, 4 bytes
276
- // [Java type name width] # 32-bit integer, 4 bytes
277
- // [Assembly name size] # 32-bit integer, 4 bytes
278
- // [Assembly name] # Non-null terminated assembly name
279
- // [Java-to-managed map] # Format described below, [Entry count] entries
280
- // [Managed-to-java map] # Format described below, [Entry count] entries
278
+ // [Magic string] # XATM
279
+ // [Format version] # 32-bit integer, 4 bytes
280
+ // [Module UUID] # 16 bytes
281
+ // [Entry count] # 32-bit integer, 4 bytes
282
+ // [Duplicate count] # 32-bit integer, 4 bytes (might be 0)
283
+ // [Java type name width] # 32-bit integer, 4 bytes
284
+ // [Assembly name size] # 32-bit integer, 4 bytes
285
+ // [Assembly name] # Non-null terminated assembly name
286
+ // [Java-to-managed map] # Format described below, [Entry count] entries
287
+ // [Managed-to-java map] # Format described below, [Entry count] entries
288
+ // [Managed-to-java duplicates map] # Map of unique managed IDs which point to the same Java type name (might be empty)
281
289
//
282
290
// Java-to-managed map format:
283
291
//
@@ -297,27 +305,22 @@ void OutputModule (string outputDirectory, byte[] moduleUUID, ModuleData moduleD
297
305
// Both fields are 32-bit integers, to a total of 8 bytes per entry. Index points into the
298
306
// [Java-to-managed map] table above.
299
307
//
308
+ // Managed-to-java duplicates map format:
309
+ //
310
+ // Format is identical to [Managed-to-java] above.
311
+ //
300
312
void OutputModule ( BinaryWriter bw , byte [ ] moduleUUID , ModuleData moduleData )
301
313
{
302
314
bw . Write ( moduleMagicString ) ;
303
315
bw . Write ( TypeMapFormatVersion ) ;
304
316
bw . Write ( moduleUUID ) ;
305
317
306
318
var javaNames = new SortedDictionary < string , uint > ( StringComparer . Ordinal ) ;
307
- var duplicateJavaNames = new Dictionary < string , bool > ( StringComparer . Ordinal ) ;
308
319
var managedTypes = new SortedDictionary < uint , uint > ( ) ;
309
-
310
- // TODO: put duplicate types in a separate list (typeid:index) at the end of the typemap file/assembly code
311
- // and mark such entries somehow in the typeid->java table (e.g. set the high bit of the index, it's unlikely
312
- // we'd have 4 billion entries)
313
320
int maxJavaNameLength = 0 ;
314
- foreach ( TypeMapEntry entry in moduleData . Types ) {
315
- if ( javaNames . ContainsKey ( entry . JavaName ) ) {
316
- logger ( $ "Warning: duplicate Java type name '{ entry . JavaName } ' (old token: { javaNames [ entry . JavaName ] } ; new token: { entry . Token } ). Ignoring the new type.") ;
317
- if ( ! duplicateJavaNames . ContainsKey ( entry . JavaName ) )
318
- duplicateJavaNames . Add ( entry . JavaName , false ) ;
319
- continue ;
320
- }
321
+
322
+ foreach ( var kvp in moduleData . Types ) {
323
+ TypeMapEntry entry = kvp . Value ;
321
324
322
325
javaNames . Add ( entry . JavaName , entry . Token ) ;
323
326
if ( entry . JavaName . Length > maxJavaNameLength )
@@ -327,17 +330,14 @@ void OutputModule (BinaryWriter bw, byte[] moduleUUID, ModuleData moduleData)
327
330
}
328
331
329
332
var javaNameList = javaNames . Keys . ToList ( ) ;
330
- foreach ( TypeMapEntry entry in moduleData . Types ) {
331
- if ( duplicateJavaNames . TryGetValue ( entry . JavaName , out bool skip ) ) {
332
- if ( skip )
333
- continue ;
334
- duplicateJavaNames [ entry . JavaName ] = true ;
335
- }
336
-
337
- managedTypes [ entry . Token ] = ( uint ) javaNameList . IndexOf ( entry . JavaName ) ;
333
+ foreach ( var kvp in moduleData . Types ) {
334
+ TypeMapEntry entry = kvp . Value ;
335
+ var javaIndex = ( uint ) javaNameList . IndexOf ( entry . JavaName ) ;
336
+ managedTypes . Add ( entry . Token , javaIndex ) ;
338
337
}
339
338
340
339
bw . Write ( javaNames . Count ) ;
340
+ bw . Write ( moduleData . DuplicateTypes . Count ) ;
341
341
bw . Write ( maxJavaNameLength + 1 ) ;
342
342
343
343
string assemblyName = moduleData . Assembly . Name . Name ;
@@ -353,12 +353,29 @@ void OutputModule (BinaryWriter bw, byte[] moduleUUID, ModuleData moduleData)
353
353
bw . Write ( token ) ;
354
354
}
355
355
356
- foreach ( var kvp in managedTypes ) {
357
- uint token = kvp . Key ;
358
- uint javaIndex = kvp . Value ;
356
+ WriteManagedTypes ( managedTypes ) ;
357
+ if ( moduleData . DuplicateTypes . Count == 0 )
358
+ return ;
359
359
360
- bw . Write ( token ) ;
361
- bw . Write ( javaIndex ) ;
360
+ var managedDuplicates = new SortedDictionary < uint , uint > ( ) ;
361
+ foreach ( var kvp in moduleData . DuplicateTypes ) {
362
+ uint javaIndex = kvp . Key ;
363
+ uint typeId = kvp . Value . Token ;
364
+
365
+ managedDuplicates . Add ( javaIndex , typeId ) ;
366
+ }
367
+
368
+ WriteManagedTypes ( managedDuplicates ) ;
369
+
370
+ void WriteManagedTypes ( IDictionary < uint , uint > types )
371
+ {
372
+ foreach ( var kvp in types ) {
373
+ uint token = kvp . Key ;
374
+ uint javaIndex = kvp . Value ;
375
+
376
+ bw . Write ( token ) ;
377
+ bw . Write ( javaIndex ) ;
378
+ }
362
379
}
363
380
}
364
381
0 commit comments