Skip to content

Commit 8512b2a

Browse files
TypeMap API (Dynamic implementation) (#113954)
Definition of TypeMaps APIs in BCL CoreCLR implementation of TypeMap APIs
1 parent 3dbeb51 commit 8512b2a

34 files changed

+1563
-119
lines changed

src/coreclr/System.Private.CoreLib/System.Private.CoreLib.csproj

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,10 @@
107107

108108
<!-- Sources -->
109109
<ItemGroup>
110+
<Compile Include="$(BclSourcesRoot)\Internal\VersionResilientHashCode.CoreCLR.cs" />
111+
<Compile Include="$(CommonPath)Internal\VersionResilientHashCode.cs">
112+
<Link>Common\Internal\VersionResilientHashCode.cs</Link>
113+
</Compile>
110114
<Compile Include="$(BclSourcesRoot)\Internal\Runtime\CompilerHelpers\ThrowHelpers.cs" />
111115
<Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\ComActivationContextInternal.cs" />
112116
<Compile Include="$(BclSourcesRoot)\Internal\Runtime\InteropServices\ComponentActivator.CoreCLR.cs" />
Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,78 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Reflection.Metadata;
6+
using System.Runtime.CompilerServices;
7+
using System.Runtime.InteropServices;
8+
9+
namespace Internal
10+
{
11+
/// <summary>
12+
/// Managed implementation of the version-resilient hash code algorithm.
13+
/// </summary>
14+
internal static partial class VersionResilientHashCode
15+
{
16+
[LibraryImport(RuntimeHelpers.QCall, EntryPoint = "VersionResilientHashCode_TypeHashCode")]
17+
private static partial int TypeHashCode(QCallTypeHandle typeHandle);
18+
19+
public static int TypeHashCode(RuntimeType type)
20+
=> TypeHashCode(new QCallTypeHandle(ref type));
21+
22+
/// <summary>
23+
/// CoreCLR 1-parameter <a href="https://github.com/dotnet/runtime/blob/17154bd7b8f21d6d8d6fca71b89d7dcb705ec32b/src/coreclr/vm/versionresilienthashcode.cpp#L109">GetVersionResilientTypeHashCode</a>
24+
/// </summary>
25+
/// <param name="type">TypeName to hash</param>
26+
public static int TypeHashCode(TypeName type)
27+
{
28+
if (type.IsSimple || type.IsConstructedGenericType)
29+
{
30+
int hashcode = NameHashCode(type.IsNested ? string.Empty : type.Namespace, type.Name);
31+
if (type.IsNested)
32+
{
33+
hashcode = NestedTypeHashCode(TypeHashCode(type.DeclaringType), hashcode);
34+
}
35+
if (type.IsConstructedGenericType)
36+
{
37+
return GenericInstanceHashCode(hashcode, type.GetGenericArguments());
38+
}
39+
else
40+
{
41+
return hashcode;
42+
}
43+
}
44+
45+
if (type.IsArray)
46+
{
47+
return ArrayTypeHashCode(TypeHashCode(type.GetElementType()), type.GetArrayRank());
48+
}
49+
50+
if (type.IsPointer)
51+
{
52+
return PointerTypeHashCode(TypeHashCode(type.GetElementType()));
53+
}
54+
55+
if (type.IsByRef)
56+
{
57+
return ByrefTypeHashCode(TypeHashCode(type.GetElementType()));
58+
}
59+
60+
throw new NotImplementedException();
61+
}
62+
63+
/// <summary>
64+
/// CoreCLR <a href="https://github.com/dotnet/runtime/blob/17154bd7b8f21d6d8d6fca71b89d7dcb705ec32b/src/coreclr/vm/typehashingalgorithms.h#L87">ComputeGenericInstanceHashCode</a>
65+
/// </summary>
66+
/// <param name="hashcode">Base hash code</param>
67+
/// <param name="instantiation">Instantiation to include in the hash</param>
68+
private static int GenericInstanceHashCode(int hashcode, ReadOnlySpan<TypeName> instantiation)
69+
{
70+
for (int i = 0; i < instantiation.Length; i++)
71+
{
72+
int argumentHashCode = TypeHashCode(instantiation[i]);
73+
hashcode = unchecked(hashcode + RotateLeft(hashcode, 13)) ^ argumentHashCode;
74+
}
75+
return unchecked(hashcode + RotateLeft(hashcode, 15));
76+
}
77+
}
78+
}

src/coreclr/System.Private.CoreLib/src/System/Reflection/TypeNameResolver.CoreCLR.cs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,12 @@ internal static RuntimeType GetTypeReferencedByCustomAttribute(string typeName,
131131
bool throwOnError, bool requireAssemblyQualifiedName)
132132
{
133133
ReadOnlySpan<char> typeName = MemoryMarshal.CreateReadOnlySpanFromNullTerminated(pTypeName);
134+
return GetTypeHelper(typeName, requestingAssembly, throwOnError, requireAssemblyQualifiedName);
135+
}
134136

137+
internal static unsafe RuntimeType? GetTypeHelper(ReadOnlySpan<char> typeName, RuntimeAssembly? requestingAssembly,
138+
bool throwOnError, bool requireAssemblyQualifiedName)
139+
{
135140
// Compat: Empty name throws TypeLoadException instead of
136141
// the natural ArgumentException
137142
if (typeName.Length == 0)

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/AttributePresenceFilterNode.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Reflection.Metadata;
1010
using System.Reflection.Metadata.Ecma335;
1111

12+
using Internal;
1213
using Internal.Text;
1314
using Internal.TypeSystem.Ecma;
1415

@@ -334,8 +335,8 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
334335
{
335336
string name = customAttributeEntry.TypeNamespace + "." + customAttributeEntry.TypeName;
336337
// This hashing algorithm MUST match exactly the logic in NativeCuckooFilter
337-
int hashOfAttribute = ReadyToRunHashCode.NameHashCode(name);
338-
uint hash = unchecked((uint)ReadyToRunHashCode.CombineTwoValuesIntoHash((uint)hashOfAttribute, (uint)customAttributeEntry.Parent));
338+
int hashOfAttribute = VersionResilientHashCode.NameHashCode(name);
339+
uint hash = unchecked((uint)VersionResilientHashCode.CombineTwoValuesIntoHash((uint)hashOfAttribute, (uint)customAttributeEntry.Parent));
339340
ushort fingerprint = (ushort)(hash >> 16);
340341
if (fingerprint == 0)
341342
{

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InliningInfoNode.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
using System.IO;
88
using System.Reflection.Metadata.Ecma335;
99

10+
using Internal;
1011
using Internal.NativeFormat;
1112
using Internal.ReadyToRunConstants;
1213
using Internal.Text;
@@ -139,16 +140,16 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
139140
EcmaMethod inlinee = inlineeWithInliners.Key;
140141
int inlineeRid = MetadataTokens.GetRowNumber(inlinee.Handle);
141142
int hashCode;
142-
143+
143144
if (AllowCrossModuleInlines)
144145
{
145146
// CrossModuleInlineInfo format
146-
hashCode = ReadyToRunHashCode.MethodHashCode(inlinee);
147+
hashCode = VersionResilientHashCode.MethodHashCode(inlinee);
147148
}
148149
else
149150
{
150151
// InliningInfo2 format
151-
hashCode = ReadyToRunHashCode.ModuleNameHashCode(inlinee.Module);
152+
hashCode = VersionResilientHashCode.ModuleNameHashCode(inlinee.Module);
152153
hashCode ^= inlineeRid;
153154
}
154155

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstanceEntryPointTableNode.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Linq;
99
using System.Reflection.Metadata.Ecma335;
1010

11+
using Internal;
1112
using Internal.JitInterface;
1213
using Internal.NativeFormat;
1314
using Internal.Runtime;
@@ -123,7 +124,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
123124

124125
EntryPointVertex entryPointVertex = new EntryPointWithBlobVertex((uint)methodIndex, fixupBlob, signatureBlob);
125126
hashtableSection.Place(entryPointVertex);
126-
vertexHashtable.Append(unchecked((uint)ReadyToRunHashCode.MethodHashCode(method.Method)), entryPointVertex);
127+
vertexHashtable.Append(unchecked((uint)VersionResilientHashCode.MethodHashCode(method.Method)), entryPointVertex);
127128
}
128129

129130
MemoryStream hashtableContent = new MemoryStream();

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/InstrumentationDataTableNode.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using System.Linq;
1010
using System.Reflection.Metadata.Ecma335;
1111

12+
using Internal;
1213
using Internal.JitInterface;
1314
using Internal.NativeFormat;
1415
using Internal.Pgo;
@@ -284,7 +285,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
284285

285286
PgoInstrumentedDataWithSignatureBlobVertex pgoDataVertex = new PgoInstrumentedDataWithSignatureBlobVertex(signatureBlob, 0, instrumentationDataBlob);
286287
hashtableSection.Place(pgoDataVertex);
287-
vertexHashtable.Append(unchecked((uint)ReadyToRunHashCode.MethodHashCode(method)), pgoDataVertex);
288+
vertexHashtable.Append(unchecked((uint)VersionResilientHashCode.MethodHashCode(method)), pgoDataVertex);
288289
}
289290

290291
MemoryStream hashtableContent = new MemoryStream();

src/coreclr/tools/aot/ILCompiler.ReadyToRun/Compiler/DependencyAnalysis/ReadyToRun/TypesTableNode.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@
88
using System.Reflection.Metadata;
99
using System.Reflection.Metadata.Ecma335;
1010

11+
using Internal;
1112
using Internal.NativeFormat;
1213
using Internal.Text;
1314
using Internal.TypeSystem;
@@ -45,7 +46,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
4546
TypeDefinition defType = defTypeInfo.MetadataReader.GetTypeDefinition(defTypeHandle);
4647
string namespaceName = defTypeInfo.MetadataReader.GetString(defType.Namespace);
4748
string typeName = defTypeInfo.MetadataReader.GetString(defType.Name);
48-
hashCode ^= ReadyToRunHashCode.NameHashCode(namespaceName, typeName);
49+
hashCode ^= VersionResilientHashCode.NameHashCode(namespaceName, typeName);
4950
if (!defType.Attributes.IsNested())
5051
{
5152
break;
@@ -64,7 +65,7 @@ public override ObjectData GetData(NodeFactory factory, bool relocsOnly = false)
6465
ExportedType expType = expTypeInfo.MetadataReader.GetExportedType(expTypeHandle);
6566
string namespaceName = expTypeInfo.MetadataReader.GetString(expType.Namespace);
6667
string typeName = expTypeInfo.MetadataReader.GetString(expType.Name);
67-
hashCode ^= ReadyToRunHashCode.NameHashCode(namespaceName, typeName);
68+
hashCode ^= VersionResilientHashCode.NameHashCode(namespaceName, typeName);
6869
if (expType.Implementation.Kind != HandleKind.ExportedType)
6970
{
7071
// Not a nested class
Lines changed: 120 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,120 @@
1+
// Licensed to the .NET Foundation under one or more agreements.
2+
// The .NET Foundation licenses this file to you under the MIT license.
3+
4+
using System;
5+
using System.Diagnostics;
6+
using System.Numerics;
7+
using System.Text;
8+
9+
using Internal.TypeSystem;
10+
11+
namespace Internal
12+
{
13+
/// <summary>
14+
/// Managed implementation of the version-resilient hash code algorithm.
15+
/// </summary>
16+
internal static partial class VersionResilientHashCode
17+
{
18+
/// <summary>
19+
/// CoreCLR 3-parameter <a href="https://github.com/dotnet/runtime/blob/17154bd7b8f21d6d8d6fca71b89d7dcb705ec32b/src/coreclr/vm/versionresilienthashcode.cpp#L9">GetVersionResilientTypeHashCode</a>
20+
/// </summary>
21+
/// <param name="type">Type to hash</param>
22+
public static int TypeTableHashCode(DefType type)
23+
{
24+
int hashcode = 0;
25+
do
26+
{
27+
hashcode ^= NameHashCode(type.Namespace, type.Name);
28+
type = type.ContainingType;
29+
}
30+
while (type != null);
31+
return hashcode;
32+
}
33+
34+
/// <summary>
35+
/// CoreCLR 1-parameter <a href="https://github.com/dotnet/runtime/blob/17154bd7b8f21d6d8d6fca71b89d7dcb705ec32b/src/coreclr/vm/versionresilienthashcode.cpp#L109">GetVersionResilientTypeHashCode</a>
36+
/// </summary>
37+
/// <param name="type">Type to hash</param>
38+
public static int TypeHashCode(TypeDesc type)
39+
{
40+
if (type.GetTypeDefinition() is DefType defType)
41+
{
42+
int hashcode = NameHashCode(defType.Namespace, defType.Name);
43+
DefType containingType = defType.ContainingType;
44+
if (containingType != null)
45+
{
46+
hashcode = NestedTypeHashCode(TypeHashCode(containingType), hashcode);
47+
}
48+
if (type.HasInstantiation && !type.IsGenericDefinition)
49+
{
50+
return GenericInstanceHashCode(hashcode, type.Instantiation);
51+
}
52+
else
53+
{
54+
return hashcode;
55+
}
56+
}
57+
58+
if (type is ArrayType arrayType)
59+
{
60+
return ArrayTypeHashCode(TypeHashCode(arrayType.ElementType), arrayType.Rank);
61+
}
62+
63+
if (type is PointerType pointerType)
64+
{
65+
return PointerTypeHashCode(TypeHashCode(pointerType.ParameterType));
66+
}
67+
68+
if (type is ByRefType byRefType)
69+
{
70+
return ByrefTypeHashCode(TypeHashCode(byRefType.ParameterType));
71+
}
72+
73+
throw new NotImplementedException();
74+
}
75+
76+
/// <summary>
77+
/// CoreCLR <a href="https://github.com/dotnet/runtime/blob/17154bd7b8f21d6d8d6fca71b89d7dcb705ec32b/src/coreclr/vm/typehashingalgorithms.h#L87">ComputeGenericInstanceHashCode</a>
78+
/// </summary>
79+
/// <param name="hashcode">Base hash code</param>
80+
/// <param name="instantiation">Instantiation to include in the hash</param>
81+
private static int GenericInstanceHashCode(int hashcode, Instantiation instantiation)
82+
{
83+
for (int i = 0; i < instantiation.Length; i++)
84+
{
85+
int argumentHashCode = TypeHashCode(instantiation[i]);
86+
hashcode = unchecked(hashcode + RotateLeft(hashcode, 13)) ^ argumentHashCode;
87+
}
88+
return unchecked(hashcode + RotateLeft(hashcode, 15));
89+
}
90+
91+
/// <summary>
92+
/// CoreCLR <a href="https://github.com/dotnet/runtime/blob/17154bd7b8f21d6d8d6fca71b89d7dcb705ec32b/src/coreclr/vm/versionresilienthashcode.cpp#L161">GetVersionResilientMethodHashCode</a>
93+
/// </summary>
94+
/// <param name="method">Method to hash</param>
95+
public static int MethodHashCode(MethodDesc method)
96+
{
97+
int hashCode = TypeHashCode(method.OwningType);
98+
int methodNameHashCode = NameHashCode(method.Name);
99+
100+
// Todo: Add signature to hash.
101+
if (method.HasInstantiation && !method.IsGenericMethodDefinition)
102+
{
103+
hashCode ^= GenericInstanceHashCode(methodNameHashCode, method.Instantiation);
104+
}
105+
else
106+
{
107+
hashCode ^= methodNameHashCode;
108+
}
109+
110+
return hashCode;
111+
}
112+
113+
public static int ModuleNameHashCode(ModuleDesc module)
114+
{
115+
IAssemblyDesc assembly = module.Assembly;
116+
Debug.Assert(assembly == module);
117+
return NameHashCode(assembly.GetName().Name);
118+
}
119+
}
120+
}

src/coreclr/tools/aot/ILCompiler.ReadyToRun/ILCompiler.ReadyToRun.csproj

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -256,7 +256,8 @@
256256
<Compile Include="IBC\ReaderExtensions.cs" />
257257
<Compile Include="Compiler\ProfileData.cs" />
258258
<Compile Include="Compiler\ProfileDataManager.cs" />
259-
<Compile Include="Compiler\ReadyToRunHashCode.cs" />
259+
<Compile Include="Compiler\VersionResilientHashCode.ReadyToRun.cs" />
260+
<Compile Include="$(LibrariesProjectRoot)\Common\src\Internal\VersionResilientHashCode.cs" />
260261
<Compile Include="Compiler\ReadyToRunLibraryRootProvider.cs" />
261262
<Compile Include="Compiler\ReadyToRunCompilerContext.cs" />
262263
<Compile Include="Compiler\ReadyToRunCodegenCompilation.cs" />

0 commit comments

Comments
 (0)