Esempio n. 1
0
        public static unsafe void ActivatorCreateInstanceAny(ref object ptrToData, IntPtr pEETypePtr)
        {
            EETypePtr pEEType = new EETypePtr(pEETypePtr);

            if (pEEType.IsValueType)
            {
                // Nothing else to do for value types.
                return;
            }

            // For reference types, we need to:
            //  1- Allocate the new object
            //  2- Call its default ctor
            //  3- Update ptrToData to point to that newly allocated object
            ptrToData = RuntimeImports.RhNewObject(pEEType);

            Entry entry = LookupInCache(s_cache, pEETypePtr, pEETypePtr);

            if (entry == null)
            {
                entry = CacheMiss(pEETypePtr, pEETypePtr,
                                  (IntPtr context, IntPtr signature, object contextObject, ref IntPtr auxResult) =>
                {
                    IntPtr result = RuntimeAugments.TypeLoaderCallbacks.TryGetDefaultConstructorForType(new RuntimeTypeHandle(new EETypePtr(context)));
                    if (result == IntPtr.Zero)
                    {
                        result = RuntimeAugments.GetFallbackDefaultConstructor();
                    }
                    return(result);
                });
            }
            RawCalliHelper.Call(entry.Result, ptrToData);
        }
Esempio n. 2
0
        private static unsafe Entry CacheMiss(IntPtr context, IntPtr signature, SignatureKind signatureKind = SignatureKind.GenericDictionary, object contextObject = null)
        {
            IntPtr result = IntPtr.Zero, auxResult = IntPtr.Zero;
            bool   previouslyCached = false;

            //
            // Try to find the entry in the previous version of the cache that is kept alive by weak reference
            //
            if (s_previousCache.IsAllocated)
            {
                Entry[] previousCache = (Entry[])s_previousCache.Target;
                if (previousCache != null)
                {
                    Entry previousEntry = LookupInCache(previousCache, context, signature);
                    if (previousEntry != null)
                    {
                        result           = previousEntry.Result;
                        auxResult        = previousEntry.AuxResult;
                        previouslyCached = true;
                    }
                }
            }

            //
            // Call into the type loader to compute the target
            //
            if (!previouslyCached)
            {
                switch (signatureKind)
                {
                case SignatureKind.GenericDictionary:
                    result = RuntimeAugments.TypeLoaderCallbacks.GenericLookupFromContextAndSignature(context, signature, out auxResult);
                    break;

                case SignatureKind.GenericVirtualMethod:
                    result = Internal.Runtime.CompilerServices.GenericVirtualMethodSupport.GVMLookupForSlot(new RuntimeTypeHandle(new EETypePtr(context)), *(RuntimeMethodHandle *)&signature);
                    break;

                case SignatureKind.OpenInstanceResolver:
                    result = Internal.Runtime.CompilerServices.OpenMethodResolver.ResolveMethodWorker(signature, contextObject);
                    break;

                case SignatureKind.DefaultConstructor:
                {
                    result = RuntimeAugments.TypeLoaderCallbacks.TryGetDefaultConstructorForType(new RuntimeTypeHandle(new EETypePtr(context)));
                    if (result == IntPtr.Zero)
                    {
                        result = RuntimeAugments.GetFallbackDefaultConstructor();
                    }
                }
                break;

                case SignatureKind.GenericDelegateThunk:
                    result = RuntimeAugments.TypeLoaderCallbacks.GetDelegateThunk((Delegate)contextObject, (int)signature);
                    break;

                default:
                    result = RawCalliHelper.Call <IntPtr>(s_resolutionFunctionPointers[(int)signatureKind], context, signature, contextObject, out auxResult);
                    break;
                }
            }

            //
            // Update the cache under the lock
            //
            if (s_lock == null)
            {
                Interlocked.CompareExchange(ref s_lock, new Lock(), null);
            }

            s_lock.Acquire();
            try
            {
                // Avoid duplicate entries
                Entry existingEntry = LookupInCache(s_cache, context, signature);
                if (existingEntry != null)
                {
                    return(existingEntry);
                }

                // Resize cache as necessary
                Entry[] cache = ResizeCacheForNewEntryAsNecessary();

                int key = ((context.GetHashCode() >> 4) ^ signature.GetHashCode()) & (cache.Length - 1);

                Entry newEntry = new Entry()
                {
                    Context = context, Signature = signature, Result = result, AuxResult = auxResult, Next = cache[key]
                };
                cache[key] = newEntry;
                return(newEntry);
            }
            finally
            {
                s_lock.Release();
            }
        }