public static unsafe IntPtr GetGenericMethodFunctionPointer(IntPtr canonFunctionPointer, IntPtr instantiationArgument) { if (instantiationArgument == IntPtr.Zero) { return(canonFunctionPointer); } lock (s_genericFunctionPointerDictionary) { GenericMethodDescriptorInfo key; key.MethodFunctionPointer = canonFunctionPointer; key.InstantiationArgument = instantiationArgument; uint index = 0; if (!s_genericFunctionPointerDictionary.TryGetValue(key, out index)) { // Capture new index value index = s_genericFunctionPointerNextIndex; int newChunkIndex = (int)(index / c_genericDictionaryChunkSize); uint newSubChunkIndex = index % c_genericDictionaryChunkSize; // Generate new chunk if existing chunks are insufficient if (s_genericFunctionPointerCollection.Count <= newChunkIndex) { System.Diagnostics.Debug.Assert(newSubChunkIndex == 0); // New generic descriptors are allocated on the native heap and not tracked in the GC. UIntPtr allocationSize = new UIntPtr((uint)(c_genericDictionaryChunkSize * sizeof(RuntimeGeneratedGenericMethodDescriptor))); IntPtr pNewMem = Interop.MemAlloc(allocationSize); s_genericFunctionPointerCollection.Add(pNewMem); } RuntimeGeneratedGenericMethodDescriptor *newDescriptor = &((RuntimeGeneratedGenericMethodDescriptor *)s_genericFunctionPointerCollection[newChunkIndex])[newSubChunkIndex]; newDescriptor->Set(canonFunctionPointer, instantiationArgument); s_genericFunctionPointerDictionary.LookupOrAdd(key, index); // Now that we can no longer have failed, update the next index. s_genericFunctionPointerNextIndex++; } // Lookup within list int chunkIndex = (int)(index / c_genericDictionaryChunkSize); uint subChunkIndex = index % c_genericDictionaryChunkSize; RuntimeGeneratedGenericMethodDescriptor *genericRuntimeFunctionPointer = &((RuntimeGeneratedGenericMethodDescriptor *)s_genericFunctionPointerCollection[chunkIndex])[subChunkIndex]; GenericMethodDescriptor *genericFunctionPointer = &genericRuntimeFunctionPointer->Descriptor; System.Diagnostics.Debug.Assert(canonFunctionPointer == genericFunctionPointer->MethodFunctionPointer); System.Diagnostics.Debug.Assert(instantiationArgument == genericFunctionPointer->InstantiationArgument); return((IntPtr)((byte *)genericFunctionPointer + FatFunctionPointerOffset)); } }