COR_PRF_HIGH_REQUIRE_PROFILE_IMAGE = 0,
+ // Enables the large object allocation monitoring according to the LOH threshold.
+ COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED = 0x00000040,
+
COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED |
COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS |
COR_PRF_HIGH_BASIC_GC |
- COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS,
+ COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS |
+ COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED,
// MONITOR_IMMUTABLE represents all flags that may only be set during initialization.
// Trying to change any of these flags elsewhere will result in a
// Given an ObjectID, determines whether it is in a read only segment.
HRESULT IsFrozenObject(ObjectID objectId, BOOL *pbFrozen);
+
+ // Gets the value of the configured LOH Threshold.
+ HRESULT GetLOHObjectSizeThreshold(DWORD *pThreshold);
}
/*
((&g_profControlBlock)->dwEventMask & COR_PRF_MONITOR_OBJECT_ALLOCATED));
}
+inline BOOL CORProfilerTrackLargeAllocations()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ CANNOT_TAKE_LOCK;
+ }
+ CONTRACTL_END;
+
+ return
+ (CORProfilerPresent() &&
+ ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED));
+}
+
inline BOOL CORProfilerEnableRejit()
{
CONTRACTL
COR_PRF_HIGH_BASIC_GC = 0x10,
COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS = 0x20,
COR_PRF_HIGH_REQUIRE_PROFILE_IMAGE = 0,
- COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = ( ( ( COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS ) | COR_PRF_HIGH_BASIC_GC ) | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS ) ,
+ COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED = 0x40,
+ COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = ( ( ( ( COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED | COR_PRF_HIGH_MONITOR_DYNAMIC_FUNCTION_UNLOADS ) | COR_PRF_HIGH_BASIC_GC ) | COR_PRF_HIGH_MONITOR_GC_MOVED_OBJECTS ) | COR_PRF_HIGH_MONITOR_LARGEOBJECT_ALLOCATED ) ,
COR_PRF_HIGH_MONITOR_IMMUTABLE = COR_PRF_HIGH_DISABLE_TIERED_COMPILATION
} COR_PRF_HIGH_MONITOR;
ObjectID objectId,
BOOL *pbFrozen) = 0;
+ virtual HRESULT STDMETHODCALLTYPE GetLOHObjectSizeThreshold(
+ DWORD *pThreshold) = 0;
+
};
ObjectID objectId,
BOOL *pbFrozen);
+ HRESULT ( STDMETHODCALLTYPE *GetLOHObjectSizeThreshold )(
+ ICorProfilerInfo10 * This,
+ DWORD *pThreshold);
+
END_INTERFACE
} ICorProfilerInfo10Vtbl;
#define ICorProfilerInfo10_IsFrozenObject(This,objectId,pbFrozen) \
( (This)->lpVtbl -> IsFrozenObject(This,objectId,pbFrozen) )
+#define ICorProfilerInfo10_GetLOHObjectSizeThreshold(This,pThreshold) \
+ ( (This)->lpVtbl -> GetLOHObjectSizeThreshold(This,pThreshold) )
+
#endif /* COBJMACROS */
#endif // PROFILING_SUPPORTED
}
+FORCEINLINE BOOL TrackLargeAllocations()
+{
+#ifdef PROFILING_SUPPORTED
+ return CORProfilerTrackLargeAllocations();
+#else
+ return FALSE;
+#endif // PROFILING_SUPPORTED
+}
+
#endif
// Initialize Object
orArray->m_NumComponents = cElements;
+ bool bProfilerNotifyLargeAllocation = false;
+
if (bAllocateInLargeHeap ||
(totalSize >= g_pConfig->GetGCLOHThreshold()))
{
GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orArray);
+ bProfilerNotifyLargeAllocation = TrackLargeAllocations();
}
#ifdef _LOGALLOC
// Notify the profiler of the allocation
// do this after initializing bounds so callback has size information
- if (TrackAllocations())
+ if (TrackAllocations() || bProfilerNotifyLargeAllocation)
{
ProfileTrackArrayAlloc(orArray);
}
// Initialize Object
orArray->m_NumComponents = cElements;
+ bool bProfilerNotifyLargeAllocation = false;
+
if (bAllocateInLargeHeap ||
(totalSize >= g_pConfig->GetGCLOHThreshold()))
{
GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orArray);
+ bProfilerNotifyLargeAllocation = TrackLargeAllocations();
}
#ifdef _LOGALLOC
// Notify the profiler of the allocation
// do this after initializing bounds so callback has size information
- if (TrackAllocations())
+ if (TrackAllocations() || bProfilerNotifyLargeAllocation)
{
ProfileTrackArrayAlloc(orArray);
}
orObject->SetMethodTable( g_pStringClass );
orObject->SetStringLength( cchStringLength );
+ bool bProfilerNotifyLargeAllocation = false;
if (ObjectSize >= g_pConfig->GetGCLOHThreshold())
{
+ bProfilerNotifyLargeAllocation = TrackLargeAllocations();
GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject);
}
// Notify the profiler of the allocation
- if (TrackAllocations())
+ if (TrackAllocations() || bProfilerNotifyLargeAllocation)
{
OBJECTREF objref = ObjectToOBJECTREF((Object*)orObject);
GCPROTECT_BEGIN(objref);
orObject->SetMethodTable(g_pUtf8StringClass);
orObject->SetLength(cchStringLength);
- if (ObjectSize >= LARGE_OBJECT_SIZE)
+ bool bProfilerNotifyLargeAllocation = false;
+
+ if (ObjectSize >= g_pConfig->GetGCLOHThreshold())
{
GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject);
+ bProfilerNotifyLargeAllocation = TrackLargeAllocations();
}
// Notify the profiler of the allocation
- if (TrackAllocations())
+ if (TrackAllocations() || bProfilerNotifyLargeAllocation)
{
OBJECTREF objref = ObjectToOBJECTREF((Object*)orObject);
GCPROTECT_BEGIN(objref);
// verify zero'd memory (at least for sync block)
_ASSERTE( orObject->HasEmptySyncBlockInfo() );
+ bool bProfilerNotifyLargeAllocation = false;
if ((baseSize >= g_pConfig->GetGCLOHThreshold()))
{
orObject->SetMethodTableForLargeObject(pMT);
+ bProfilerNotifyLargeAllocation = TrackLargeAllocations();
GCHeapUtilities::GetGCHeap()->PublishObject((BYTE*)orObject);
}
else
}
// Notify the profiler of the allocation
- if (TrackAllocations())
+ if (TrackAllocations() || bProfilerNotifyLargeAllocation)
{
OBJECTREF objref = ObjectToOBJECTREF((Object*)orObject);
GCPROTECT_BEGIN(objref);
// Notify the profiler of the allocation
{
- BEGIN_PIN_PROFILER(CORProfilerTrackAllocations());
+ BEGIN_PIN_PROFILER(CORProfilerTrackAllocations() || CORProfilerTrackLargeAllocations());
// Note that for generic code we always return uninstantiated ClassIDs and FunctionIDs.
// Thus we strip any instantiations of the ClassID (which is really a type handle) here.
g_profControlBlock.pProfInterface->ObjectAllocated(
}
/*
+ * GetLOHObjectSizeThreshold
+ *
+ * Gets the value of the configured LOH Threshold.
+ *
+ * Parameters:
+ * pThreshold - value of the threshold in bytes
+ *
+ * Returns:
+ * S_OK if successful
+ *
+ */
+HRESULT ProfToEEInterfaceImpl::GetLOHObjectSizeThreshold(DWORD *pThreshold)
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ MODE_ANY;
+ EE_THREAD_NOT_REQUIRED;
+ CANNOT_TAKE_LOCK;
+ }
+ CONTRACTL_END;
+
+ PROFILER_TO_CLR_ENTRYPOINT_SYNC_EX(
+ kP2EEAllowableAfterAttach,
+ (LF_CORPROF,
+ LL_INFO1000,
+ "**PROF: GetLOHObjectSizeThreshold\n"));
+
+ if (pThreshold == nullptr)
+ {
+ return E_INVALIDARG;
+ }
+
+ *pThreshold = g_pConfig->GetGCLOHThreshold();
+
+ return S_OK;
+}
+
+/*
* GetStringLayout
*
* This function describes to a profiler the internal layout of a string.
COM_METHOD IsFrozenObject(ObjectID objectId, BOOL *pbFrozen);
+ COM_METHOD GetLOHObjectSizeThreshold(DWORD *pThreshold);
+
// end ICorProfilerInfo10
protected: