public static bool Exists(EETypePairList *pList, EEType *pEEType1, EEType *pEEType2) { while (pList != null) { if (pList->_eetype1 == pEEType1 && pList->_eetype2 == pEEType2) { return(true); } if (pList->_eetype1 == pEEType2 && pList->_eetype2 == pEEType1) { return(true); } pList = pList->_next; } return(false); }
private static unsafe bool CacheMiss(ref Key key, EETypePairList *pVisited) { // // First, check if we previously visited the input types pair, to avoid infinite recursions // if (EETypePairList.Exists(pVisited, key.SourceType, key.TargetType)) { return(false); } bool result = false; // 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) { // Unchecked cast to avoid recursive dependency on array casting Entry[] previousCache = Unsafe.As <Entry[]>(s_previousCache.Target); if (previousCache != null) { Entry previousEntry = LookupInCache(previousCache, ref key); if (previousEntry != null) { result = previousEntry.Result; // previouslyCached = true; } } } // // Call into the type cast code to calculate the result // Debugger.Break(); /* * if (!previouslyCached) * { * EETypePairList newList = new EETypePairList(key.SourceType, key.TargetType, pVisited); * result = TypeCast.AreTypesAssignableInternal(key.SourceType, key.TargetType, key.Variation, &newList); * } * * // * // Update the cache under the lock * // * InternalCalls.RhpAcquireCastCacheLock(); */ try { try { // Avoid duplicate entries Entry existingEntry = LookupInCache(s_cache, ref key); if (existingEntry != null) { return(existingEntry.Result); } // Resize cache as necessary Entry[] cache = ResizeCacheForNewEntryAsNecessary(); int entryIndex = key.CalculateHashCode() & (cache.Length - 1); Entry newEntry = new Entry() { Key = key, Result = result, Next = cache[entryIndex] }; // BEWARE: Array store check can lead to infinite recursion. We avoid this by making certain // that the cache trivially answers the case of equivalent types without triggering the cache // miss path. (See CastCache.AreTypesAssignableInternal) cache[entryIndex] = newEntry; return(newEntry.Result); } catch (OutOfMemoryException) { // Entry allocation failed -- but we can still return the correct cast result. return(result); } } finally { InternalCalls.RhpReleaseCastCacheLock(); } }
public static unsafe bool AreTypesAssignableInternal_SourceNotTarget_BoxedSource(EEType *pSourceType, EEType *pTargetType, EETypePairList *pVisited) { Debug.Assert(pSourceType != pTargetType, "target is source"); Key key = new Key(pSourceType, pTargetType, AssignmentVariation.BoxedSource); Entry entry = LookupInCache(s_cache, ref key); if (entry == null) { return(CacheMiss(ref key, pVisited)); } return(entry.Result); }
public static unsafe bool AreTypesAssignableInternal(EEType *pSourceType, EEType *pTargetType, AssignmentVariation variation, EETypePairList *pVisited) { // Important special case -- it breaks infinite recursion in CastCache itself! if (pSourceType == pTargetType) { return(true); } Key key = new Key(pSourceType, pTargetType, variation); Entry entry = LookupInCache(s_cache, ref key); if (entry == null) { return(CacheMiss(ref key, pVisited)); } return(entry.Result); }
public EETypePairList(EEType *pEEType1, EEType *pEEType2, EETypePairList *pNext) { _eetype1 = pEEType1; _eetype2 = pEEType2; _next = pNext; }