Example #1
0
        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));
            }
        }