}
//---------------------------------------------------------
-// ComCallWrapperTemplate::IIDToInterfaceTemplateCache
-//---------------------------------------------------------
-
-// Perf critical cache lookup code, in particular we want InlineIsEqualGUID to be inlined.
-#include <optsmallperfcritical.h>
-
-// Looks up an interface template in the cache.
-bool ComCallWrapperTemplate::IIDToInterfaceTemplateCache::LookupInterfaceTemplate(REFIID riid, ComCallWrapperTemplate **ppTemplate)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- SpinLock::Holder lock(&m_lock);
-
- for (SIZE_T i = 0; i < CACHE_SIZE; i++)
- {
- // is the item in use?
- if (!m_items[i].IsFree())
- {
- // does the IID match?
- if (InlineIsEqualGUID(m_items[i].m_iid, riid))
- {
- // mark the item as hot to help avoid eviction
- m_items[i].MarkHot();
- *ppTemplate = m_items[i].GetTemplate();
- return true;
- }
- }
- }
-
- *ppTemplate = NULL;
- return false;
-}
-
-#include <optdefault.h>
-
-// Inserts an interface template in the cache. If the cache is full and an item needs to be evicted,
-// it tries to find one that hasn't been recently used.
-void ComCallWrapperTemplate::IIDToInterfaceTemplateCache::InsertInterfaceTemplate(REFIID riid, ComCallWrapperTemplate *pTemplate)
-{
- CONTRACTL
- {
- NOTHROW;
- GC_NOTRIGGER;
- MODE_ANY;
- }
- CONTRACTL_END;
-
- SpinLock::Holder lock(&m_lock);
-
- for (SIZE_T i = 0; i < CACHE_SIZE; i++)
- {
- // is the item free?
- if (m_items[i].IsFree())
- {
- m_items[i].m_iid = riid;
- m_items[i].SetTemplate(pTemplate);
- return;
- }
- }
-
- // the cache is full - find an item to evict and reset all items to "cold"
- SIZE_T index_to_evict = 0;
- for (SIZE_T i = 0; i < CACHE_SIZE; i++)
- {
- // is the item cold?
- if (!m_items[i].IsHot())
- {
- index_to_evict = i;
- }
- m_items[i].MarkCold();
- }
-
- m_items[index_to_evict].m_iid = riid;
- m_items[index_to_evict].SetTemplate(pTemplate);
-}
-
-//---------------------------------------------------------
// ComCallWrapperTemplate::CCWInterfaceMapIterator
//---------------------------------------------------------
ComCallWrapperTemplate::CCWInterfaceMapIterator::CCWInterfaceMapIterator(TypeHandle thClass)
if (m_pBasicComMT)
m_pBasicComMT->Release();
- if (m_pIIDToInterfaceTemplateCache)
- delete m_pIIDToInterfaceTemplateCache;
-
delete[] (BYTE*)this;
}
pTemplate->m_pBasicComMT = NULL;
pTemplate->m_pDefaultItf = NULL;
pTemplate->m_pICustomQueryInterfaceGetInterfaceMD = NULL;
- pTemplate->m_pIIDToInterfaceTemplateCache = NULL;
pTemplate->m_flags = 0;
// Determine the COM visibility of classes in our hierarchy.
pTemplate->m_pBasicComMT = NULL;
pTemplate->m_pDefaultItf = pItfMT;
pTemplate->m_pICustomQueryInterfaceGetInterfaceMD = NULL;
- pTemplate->m_pIIDToInterfaceTemplateCache = NULL;
pTemplate->m_flags = enum_RepresentsVariantInterface;
// Initialize the one ComMethodTable
RETURN m_pICustomQueryInterfaceGetInterfaceMD;
}
-ComCallWrapperTemplate::IIDToInterfaceTemplateCache *ComCallWrapperTemplate::GetOrCreateIIDToInterfaceTemplateCache()
-{
- CONTRACT (IIDToInterfaceTemplateCache *)
- {
- THROWS;
- GC_NOTRIGGER;
- MODE_ANY;
- POSTCONDITION(CheckPointer(RETVAL));
- }
- CONTRACT_END;
-
- IIDToInterfaceTemplateCache *pCache = m_pIIDToInterfaceTemplateCache.Load();
- if (pCache == NULL)
- {
- pCache = new IIDToInterfaceTemplateCache();
-
- IIDToInterfaceTemplateCache *pOldCache = InterlockedCompareExchangeT(&m_pIIDToInterfaceTemplateCache, pCache, NULL);
- if (pOldCache != NULL)
- {
- delete pCache;
- RETURN pOldCache;
- }
- }
- RETURN pCache;
-}
-
-
//--------------------------------------------------------------------------
// Module* ComCallMethodDesc::GetModule()
// Get Module
#include "stdinterfaces.h"
#include "threads.h"
#include "comutilnative.h"
-#include "spinlock.h"
#include "comtoclrcall.h"
#include "dispatchinfo.h"
#include "wrappers.h"
class MethodTable;
class ComCallWrapper;
struct SimpleComCallWrapper;
-class RCWHolder;
struct ComMethodTable;
typedef DPTR(struct SimpleComCallWrapper) PTR_SimpleComCallWrapper;
friend class ClrDataAccess;
public:
- // Small "L1" cache to speed up QI's on CCWs with variance. It caches both positive and negative
- // results (i.e. also keeps track of IIDs that the QI doesn't respond to).
- class IIDToInterfaceTemplateCache
- {
- enum
- {
- // There is also some number of IIDs QI'ed for by external code that we won't
- // recognize - this number is potentially unbounded so even if this was a different data
- // structure, we would want to limit its size. Simple sequentially searched array seems to
- // work the best both in terms of memory footprint and lookup performance.
- CACHE_SIZE = 16,
- };
-
- struct CacheItem
- {
- IID m_iid;
-
- // The lowest bit indicates whether this item is being used (since NULL is a legal value).
- // The second lowest bit indicates whether the item has been accessed since the last eviction.
- // The rest of the bits contain ComCallWrapperTemplate pointer.
- SIZE_T m_pTemplate;
-
- bool IsFree()
- {
- LIMITED_METHOD_CONTRACT;
- return (m_pTemplate == 0);
- }
-
- bool IsHot()
- {
- LIMITED_METHOD_CONTRACT;
- return ((m_pTemplate & 0x2) == 0x2);
- }
-
- ComCallWrapperTemplate *GetTemplate()
- {
- LIMITED_METHOD_CONTRACT;
- return (ComCallWrapperTemplate *)(m_pTemplate & ~0x3);
- }
-
- void SetTemplate(ComCallWrapperTemplate *pTemplate)
- {
- LIMITED_METHOD_CONTRACT;
- m_pTemplate = ((SIZE_T)pTemplate | 0x1);
- }
-
- void MarkHot()
- {
- LIMITED_METHOD_CONTRACT;
- m_pTemplate |= 0x2;
- }
-
- void MarkCold()
- {
- LIMITED_METHOD_CONTRACT;
- m_pTemplate &= ~0x2;
- }
- };
-
- // array of cache items
- CacheItem m_items[CACHE_SIZE];
-
- // spin lock to protect concurrent access to m_items
- SpinLock m_lock;
-
- public:
- IIDToInterfaceTemplateCache()
- {
- CONTRACTL
- {
- THROWS;
- GC_NOTRIGGER;
- }
- CONTRACTL_END;
-
- ZeroMemory(this, sizeof(IIDToInterfaceTemplateCache));
- m_lock.Init(LOCK_TYPE_DEFAULT);
- }
-
- bool LookupInterfaceTemplate(REFIID riid, ComCallWrapperTemplate **ppTemplate);
- void InsertInterfaceTemplate(REFIID riid, ComCallWrapperTemplate *pTemplate);
- };
-
// Iterates COM-exposed interfaces of a class.
class CCWInterfaceMapIterator
{
MethodDesc * GetICustomQueryInterfaceGetInterfaceMD();
- IIDToInterfaceTemplateCache *GetOrCreateIIDToInterfaceTemplateCache();
-
BOOL HasInvisibleParent()
{
LIMITED_METHOD_CONTRACT;
};
DWORD m_flags;
MethodDesc* m_pICustomQueryInterfaceGetInterfaceMD;
- Volatile<IIDToInterfaceTemplateCache *> m_pIIDToInterfaceTemplateCache;
ULONG m_cbInterfaces;
SLOT* m_rgpIPtr[1];
};