Exemplo n.º 1
0
        // cache must be a size which is a power of two.
        internal static unsafe object CastableTargetLookup(CastableObjectCacheEntry[] cache, EEType* interfaceType)
        {
            uint cacheMask = (uint)cache.Length - 1;
            uint bucket = interfaceType->HashCode & cacheMask;
            uint curbucket = bucket;

            // hash algorithm is open addressing with linear probing

            while (curbucket < cache.Length)
            {
                if (cache[curbucket].Type == interfaceType)
                    return cache[curbucket].InstanceObjectForType;
                if (cache[curbucket].Type == null)
                    return null;
                curbucket++;
            }

            // Handle wrap-around case
            curbucket = 0;
            while (curbucket < bucket)
            {
                if (cache[curbucket].Type == interfaceType)
                    return cache[curbucket].InstanceObjectForType;
                if (cache[curbucket].Type == null)
                    return null;
                curbucket++;
            }

            return null;
        }
Exemplo n.º 2
0
        internal unsafe static int GetCachePopulation(CastableObjectCacheEntry[] cache)
        {
            int population = 0;
            for (int i = 0; i < cache.Length; i++)
            {
                if (cache[i].Type != null)
                    population++;
            }

            return population;
        }
Exemplo n.º 3
0
        /// <summary>
        /// Add the results of a CastableObject call to the cache if possible. (OOM errors may cause caching failure. An OOM is specified not
        /// to introduce new failure points though.)
        /// </summary>
        internal static unsafe void AddToCastableCache(ICastableObject castableObject, EEType *interfaceType, object objectForType)
        {
            CastableObjectCacheEntry <object>[] cache = Unsafe.As <CastableObject>(castableObject).Cache;
            bool setNewCache = false;

            // If there is no cache, allocate one
            if (cache == null)
            {
                try
                {
                    cache = new CastableObjectCacheEntry <object> [8];
                }
                catch (OutOfMemoryException)
                {
                    // Failed to allocate a cache.  That is fine, simply return.
                    return;
                }

                setNewCache = true;
            }

            // Expand old cache if it isn't big enough.
            if (GetCachePopulation(cache) > (cache.Length / 2))
            {
                setNewCache = true;
                CastableObjectCacheEntry <object>[] oldCache = cache;
                try
                {
                    cache = new CastableObjectCacheEntry <object> [oldCache.Length * 2];
                }
                catch (OutOfMemoryException)
                {
                    // Failed to allocate a bigger cache.  That is fine, keep the old one.
                }

                for (int i = 0; i < oldCache.Length; i++)
                {
                    if (oldCache[i].Key != default(IntPtr))
                    {
                        AddToExistingCache(cache, oldCache[i].Key, oldCache[i].Value);
                    }
                }
            }

            AddToExistingCache(cache, new IntPtr(interfaceType), objectForType);

            if (setNewCache)
            {
                Unsafe.As <CastableObject>(castableObject).Cache = cache;
            }

            return;
        }
Exemplo n.º 4
0
        internal unsafe static void AddToExistingCache(CastableObjectCacheEntry[] cache, EEType* interfaceType, object objectForType)
        {
            uint cacheMask = (uint)cache.Length - 1;
            uint bucket = interfaceType->HashCode & cacheMask;
            uint curbucket = bucket;

            // hash algorithm is open addressing with linear probing

            while (curbucket < cache.Length)
            {
                if (cache[curbucket].Type == null)
                {
                    cache[curbucket].Type = interfaceType;
                    cache[curbucket].InstanceObjectForType = objectForType;
                    return;
                }
                curbucket++;
            }

            // Handle wrap-around case
            curbucket = 0;
            while (curbucket < bucket)
            {
                if (cache[curbucket].Type == null)
                {
                    cache[curbucket].Type = interfaceType;
                    cache[curbucket].InstanceObjectForType = objectForType;
                    return;
                }
                curbucket++;
            }

            EH.FallbackFailFast(RhFailFastReason.InternalError, null);
            return;
        }
Exemplo n.º 5
0
        /// <summary>
        /// Add the results of a CastableObject call to the cache if possible. (OOM errors may cause caching failure. An OOM is specified not
        /// to introduce new failure points though.)
        /// </summary>
        internal unsafe static void AddToCastableCache(ICastableObject castableObject, EEType* interfaceType, object objectForType)
        {
            CastableObjectCacheEntry[] cache = Unsafe.As<CastableObject>(castableObject).Cache;
            bool setNewCache = false;

            // If there is no cache, allocate one
            if (cache == null)
            {
                try
                {
                    cache = new CastableObjectCacheEntry[8];
                }
                catch (OutOfMemoryException)
                {
                    // Failed to allocate a cache.  That is fine, simply return.
                    return;
                }

                setNewCache = true;
            }

            // Expand old cache if it isn't big enough.
            if (GetCachePopulation(cache) > (cache.Length / 2))
            {
                setNewCache = true;
                CastableObjectCacheEntry[] oldCache = cache;
                try
                {
                    cache = new CastableObjectCacheEntry[oldCache.Length * 2];
                }
                catch (OutOfMemoryException)
                {
                    // Failed to allocate a bigger cache.  That is fine, keep the old one.
                }

                for (int i = 0; i < oldCache.Length; i++)
                {
                    if (oldCache[i].Type != null)
                    {
                        AddToExistingCache(cache, oldCache[i].Type, oldCache[i].InstanceObjectForType);
                    }
                }
            }

            AddToExistingCache(cache, interfaceType, objectForType);

            if (setNewCache)
            {
                Unsafe.As<CastableObject>(castableObject).Cache = cache;
            }

            return;
        }