summaryrefslogtreecommitdiff
path: root/src/inc
diff options
context:
space:
mode:
Diffstat (limited to 'src/inc')
-rw-r--r--src/inc/clrconfigvalues.h7
-rw-r--r--src/inc/corerror.xml5
-rw-r--r--src/inc/corprof.idl83
-rw-r--r--src/inc/dacprivate.h55
-rw-r--r--src/inc/dacvars.h8
-rw-r--r--src/inc/profilepriv.inl15
-rw-r--r--src/inc/simplerhash.h47
-rw-r--r--src/inc/sospriv.idl12
-rw-r--r--src/inc/switches.h2
9 files changed, 228 insertions, 6 deletions
diff --git a/src/inc/clrconfigvalues.h b/src/inc/clrconfigvalues.h
index 8f33e40c27..062ffb6e01 100644
--- a/src/inc/clrconfigvalues.h
+++ b/src/inc/clrconfigvalues.h
@@ -319,9 +319,12 @@ RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_StatsUpdatePeriod, W("StatsUpdatePeriod"),
RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_SuspendTimeLog, W("SuspendTimeLog"), "Specifies the name of the log file for suspension statistics")
RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_GCMixLog, W("GCMixLog"), "Specifies the name of the log file for GC mix statistics")
CONFIG_DWORD_INFO_DIRECT_ACCESS(INTERNAL_GCLatencyMode, W("GCLatencyMode"), "Specifies the GC latency mode - batch, interactive or low latency (note that the same thing can be specified via API which is the supported way)")
+RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCConfigLogEnabled, W("GCConfigLogEnabled"), 0, "Specifies if you want to turn on config logging in GC")
RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCLogEnabled, W("GCLogEnabled"), 0, "Specifies if you want to turn on logging in GC")
RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_GCLogFile, W("GCLogFile"), "Specifies the name of the GC log file")
-RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCLogFileSize, W("GCLogFileSize"), 0, "Specifies the maximum GC log file size")
+RETAIL_CONFIG_STRING_INFO(UNSUPPORTED_GCConfigLogFile, W("GCConfigLogFile"), "Specifies the name of the GC config log file")
+RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCLogFileSize, W("GCLogFileSize"), 0, "Specifies the GC log file size")
+RETAIL_CONFIG_DWORD_INFO(UNSUPPORTED_GCCompactRatio, W("GCCompactRatio"), 0, "Specifies the ratio compacting GCs vs sweeping ")
RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(EXTERNAL_GCPollType, W("GCPollType"), "")
RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_NewGCCalc, W("NewGCCalc"), "", CLRConfig::REGUTIL_default)
RETAIL_CONFIG_DWORD_INFO_DIRECT_ACCESS(UNSUPPORTED_GCprnLvl, W("GCprnLvl"), "Specifies the maximum level of GC logging")
@@ -598,6 +601,8 @@ RETAIL_CONFIG_STRING_INFO(INTERNAL_WinMDPath, W("WinMDPath"), "Path for Windows
//
CONFIG_DWORD_INFO_EX(INTERNAL_LoaderHeapCallTracing, W("LoaderHeapCallTracing"), 0, "Loader heap troubleshooting", CLRConfig::REGUTIL_default)
RETAIL_CONFIG_DWORD_INFO(INTERNAL_CodeHeapReserveForJumpStubs, W("CodeHeapReserveForJumpStubs"), 2, "Percentage of code heap to reserve for jump stubs")
+RETAIL_CONFIG_DWORD_INFO(INTERNAL_NGenReserveForJumpStubs, W("NGenReserveForJumpStubs"), 0, "Percentage of ngen image size to reserve for jump stubs")
+RETAIL_CONFIG_DWORD_INFO(INTERNAL_BreakOnOutOfMemoryWithinRange, W("BreakOnOutOfMemoryWithinRange"), 0, "Break before out of memory within range exception is thrown")
//
// Log
diff --git a/src/inc/corerror.xml b/src/inc/corerror.xml
index e4ddd973b0..98d41ea845 100644
--- a/src/inc/corerror.xml
+++ b/src/inc/corerror.xml
@@ -3650,6 +3650,11 @@
<Comment> This call can't be completed safely because the runtime is not suspended </Comment>
</HRESULT>
-->
+
+<HRESULT NumericValue="0x80131382">
+ <SymbolicName>CORPROF_E_CALLBACK7_REQUIRED</SymbolicName>
+ <Comment> Profiler must implement ICorProfilerCallback7 interface for this call to be supported. </Comment>
+</HRESULT>
<HRESULT NumericValue="0x80131400">
<SymbolicName>SECURITY_E_XML_TO_ASN_ENCODING</SymbolicName>
diff --git a/src/inc/corprof.idl b/src/inc/corprof.idl
index 894a8850be..328fbe01e1 100644
--- a/src/inc/corprof.idl
+++ b/src/inc/corprof.idl
@@ -615,9 +615,11 @@ typedef enum
COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES = 0x00000001,
+ COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED = 0x00000002,
+
COR_PRF_HIGH_REQUIRE_PROFILE_IMAGE = 0,
- COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = 0,
+ COR_PRF_HIGH_ALLOWABLE_AFTER_ATTACH = COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED,
// MONITOR_IMMUTABLE represents all flags that may only be set during initialization.
// Trying to change any of these flags elsewhere will result in a
@@ -2349,6 +2351,29 @@ interface ICorProfilerCallback6 : ICorProfilerCallback5
};
+[
+ object,
+ uuid(F76A2DBA-1D52-4539-866C-2AA518F9EFC3),
+ pointer_default(unique),
+ local
+]
+interface ICorProfilerCallback7 : ICorProfilerCallback6
+{
+ // This event is triggered whenever the symbol stream associated with an
+ // in-memory module is updated. Even when symbols are provided up-front in
+ // a call to the managed API Assembly.Load(byte[], byte[], ...) the runtime
+ // may not actually associate the symbolic data with the module until after
+ // the ModuleLoadFinished callback has occured. This event provides a later
+ // opportunity to collect symbols for such modules.
+ //
+ // This event is controlled by the COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED
+ // event mask flag.
+ //
+ // Note: This event is not currently raised for symbols implicitly created or
+ // modified via Reflection.Emit APIs.
+ HRESULT ModuleInMemorySymbolsUpdated(ModuleID moduleId);
+}
+
/*
* COR_PRF_CODEGEN_FLAGS controls various flags and hooks for a specific
@@ -3699,6 +3724,62 @@ interface ICorProfilerInfo6 : ICorProfilerInfo5
[out] ICorProfilerMethodEnum** ppEnum);
};
+[
+ object,
+ uuid(9AEECC0D-63E0-4187-8C00-E312F503F663),
+ pointer_default(unique),
+ local
+]
+interface ICorProfilerInfo7 : ICorProfilerInfo6
+{
+ /*
+ * Applies the newly emitted Metadata.
+ *
+ * This method can be used to apply the newly defined metadata by IMetadataEmit::Define* methods
+ * to the module.
+ *
+ * If metadata changes are made after ModuleLoadFinished callback,
+ * it is required to call this method before using the new metadata
+ */
+ HRESULT ApplyMetaData(
+ [in] ModuleID moduleId);
+
+ /* Returns the length of an in-memory symbol stream
+ *
+ * If the module has in-memory symbols the length of the stream will
+ * be placed in pCountSymbolBytes. If the module doesn't have in-memory
+ * symbols, *pCountSymbolBytes = 0
+ *
+ * Returns S_OK if the length could be determined (even if it is 0)
+ *
+ * Note: The current implementation does not support reflection.emit.
+ * CORPROF_E_MODULE_IS_DYNAMIC will be returned in that case.
+ */
+ HRESULT GetInMemorySymbolsLength(
+ [in] ModuleID moduleId,
+ [out] DWORD* pCountSymbolBytes);
+
+ /* Reads bytes from an in-memory symbol stream
+ *
+ * This function attempts to read countSymbolBytes of data starting at offset
+ * symbolsReadOffset within the in-memory stream. The data will be copied into
+ * pSymbolBytes which is expected to have countSymbolBytes of space available.
+ * pCountSymbolsBytesRead contains the actual number of bytes read which
+ * may be less than countSymbolBytes if the end of the stream is reached.
+ *
+ * Returns S_OK if a non-zero number of bytes were read.
+ *
+ * Note: The current implementation does not support reflection.emit.
+ * CORPROF_E_MODULE_IS_DYNAMIC will be returned in that case.
+ */
+ HRESULT ReadInMemorySymbols(
+ [in] ModuleID moduleId,
+ [in] DWORD symbolsReadOffset,
+ [out] BYTE* pSymbolBytes,
+ [in] DWORD countSymbolBytes,
+ [out] DWORD* pCountSymbolBytesRead);
+
+};
/*
* This interface lets you iterate over methods in the runtime.
diff --git a/src/inc/dacprivate.h b/src/inc/dacprivate.h
index 087d89b2f1..5ec6e7fead 100644
--- a/src/inc/dacprivate.h
+++ b/src/inc/dacprivate.h
@@ -753,6 +753,61 @@ struct DacpOomData : ZeroInit<DacpOomData>
}
};
+// This is the value of max_idp_count in ndp\clr\src\vm\gcpriv.h
+#define NUM_GC_DATA_POINTS 9
+// These are from ndp\clr\src\vm\gcrecord.h
+#define MAX_COMPACT_REASONS_COUNT 11
+#define MAX_EXPAND_MECHANISMS_COUNT 6
+#define MAX_GC_MECHANISM_BITS_COUNT 2
+// This is from ndp\clr\src\vm\common.h
+#define MAX_GLOBAL_GC_MECHANISMS_COUNT 6
+struct DacpGCInterestingInfoData : ZeroInit<DacpGCInterestingInfoData>
+{
+ size_t interestingDataPoints[NUM_GC_DATA_POINTS];
+ size_t compactReasons[MAX_COMPACT_REASONS_COUNT];
+ size_t expandMechanisms[MAX_EXPAND_MECHANISMS_COUNT];
+ size_t bitMechanisms[MAX_GC_MECHANISM_BITS_COUNT];
+ size_t globalMechanisms[MAX_GLOBAL_GC_MECHANISMS_COUNT];
+
+ HRESULT RequestGlobal(ISOSDacInterface *sos)
+ {
+ HRESULT hr;
+ ISOSDacInterface3 *psos3 = NULL;
+ if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3)))
+ {
+ hr = psos3->GetGCGlobalMechanisms(globalMechanisms);
+ psos3->Release();
+ }
+ return hr;
+ }
+
+ HRESULT Request(ISOSDacInterface *sos)
+ {
+ HRESULT hr;
+ ISOSDacInterface3 *psos3 = NULL;
+ if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3)))
+ {
+ hr = psos3->GetGCInterestingInfoStaticData(this);
+ psos3->Release();
+ }
+ return hr;
+ }
+
+ // Use this for Server mode, as there are multiple heaps,
+ // and you need to pass a heap address in addr.
+ HRESULT Request(ISOSDacInterface *sos, CLRDATA_ADDRESS addr)
+ {
+ HRESULT hr;
+ ISOSDacInterface3 *psos3 = NULL;
+ if (SUCCEEDED(hr = sos->QueryInterface(__uuidof(ISOSDacInterface3), (void**) &psos3)))
+ {
+ hr = psos3->GetGCInterestingInfoData(addr, this);
+ psos3->Release();
+ }
+ return hr;
+ }
+};
+
struct DacpGcHeapAnalyzeData
: ZeroInit<DacpGcHeapAnalyzeData>
{
diff --git a/src/inc/dacvars.h b/src/inc/dacvars.h
index 560d63a795..4195b863aa 100644
--- a/src/inc/dacvars.h
+++ b/src/inc/dacvars.h
@@ -201,6 +201,14 @@ DEFINE_DACVAR(ULONG, PTR_BYTE, dac__g_highest_address, ::g_highest_address)
DEFINE_DACVAR(ULONG, GCHeap, dac__g_pGCHeap, ::g_pGCHeap)
+#ifdef GC_CONFIG_DRIVEN
+DEFINE_DACVAR_NO_DUMP(ULONG, SIZE_T, dac__interesting_data_per_heap, ::interesting_data_per_heap)
+DEFINE_DACVAR_NO_DUMP(ULONG, SIZE_T, dac__compact_reasons_per_heap, ::compact_reasons_per_heap)
+DEFINE_DACVAR_NO_DUMP(ULONG, SIZE_T, dac__expand_mechanisms_per_heap, ::expand_mechanisms_per_heap)
+DEFINE_DACVAR_NO_DUMP(ULONG, SIZE_T, dac__interesting_mechanism_bits_per_heap, ::interesting_mechanism_bits_per_heap)
+DEFINE_DACVAR_NO_DUMP(ULONG, SIZE_T, dac__gc_global_mechanisms, ::gc_global_mechanisms)
+#endif //GC_CONFIG_DRIVEN
+
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pThinLockThreadIdDispenser, ::g_pThinLockThreadIdDispenser)
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pModuleIndexDispenser, ::g_pModuleIndexDispenser)
DEFINE_DACVAR(ULONG, UNKNOWN_POINTER_TYPE, dac__g_pObjectClass, ::g_pObjectClass)
diff --git a/src/inc/profilepriv.inl b/src/inc/profilepriv.inl
index 8e0e4ffa21..d8997fd8b6 100644
--- a/src/inc/profilepriv.inl
+++ b/src/inc/profilepriv.inl
@@ -722,6 +722,21 @@ inline BOOL CORProfilerAddsAssemblyReferences()
((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_ADD_ASSEMBLY_REFERENCES));
}
+inline BOOL CORProfilerInMemorySymbolsUpdatesEnabled()
+{
+ CONTRACTL
+ {
+ NOTHROW;
+ GC_NOTRIGGER;
+ CANNOT_TAKE_LOCK;
+ SO_NOT_MAINLINE;
+ }
+ CONTRACTL_END;
+
+ return (CORProfilerPresent() &&
+ ((&g_profControlBlock)->dwEventMaskHigh & COR_PRF_HIGH_IN_MEMORY_SYMBOLS_UPDATED));
+}
+
#if defined(PROFILING_SUPPORTED) && !defined(CROSSGEN_COMPILE)
#if defined(FEATURE_PROFAPI_ATTACH_DETACH)
diff --git a/src/inc/simplerhash.h b/src/inc/simplerhash.h
index 37b0b8fb0b..538eacf059 100644
--- a/src/inc/simplerhash.h
+++ b/src/inc/simplerhash.h
@@ -467,10 +467,49 @@ struct LargePrimitiveKeyFuncs: public KeyFuncsDefEquals<T>
{
static unsigned GetHashCode(const T val)
{
- UINT64 asUINT64 = static_cast<UINT64>(val);
- unsigned res = asUINT64 >> 32;
- res = res ^ static_cast<unsigned>(asUINT64 & ((((UINT64)1) << 32) - 1));
- return res;
+ // A static cast when T is a float or a double converts the value (i.e. 0.25 converts to 0)
+ //
+ // Instead we want to use all of the bits of a float to create the hash value
+ // So we cast the address of val to a pointer to an equivalent sized unsigned int
+ // This allows us to read the actual bit representation of a float type
+ //
+ // We can't read beyond the end of val, so we use sizeof(T) to determine
+ // exactly how many bytes to read
+ //
+ if (sizeof(T) == 8)
+ {
+ // cast &val to (UINT64 *) then deref to get the bits
+ UINT64 asUINT64 = *(reinterpret_cast<const UINT64 *>(&val));
+
+ // Get the upper and lower 32-bit values from the 64-bit value
+ UINT32 upper32 = static_cast<UINT32> (asUINT64 >> 32);
+ UINT32 lower32 = static_cast<UINT32> (asUINT64 & 0xFFFFFFFF);
+
+ // Exclusive-Or the upper32 and the lower32 values
+ return static_cast<unsigned>(upper32 ^ lower32);
+
+ }
+ else if (sizeof(T) == 4)
+ {
+ // cast &val to (UINT32 *) then deref to get the bits
+ UINT32 asUINT32 = *(reinterpret_cast<const UINT32 *>(&val));
+
+ // Just return the 32-bit value
+ return static_cast<unsigned>(asUINT32);
+ }
+ else if ((sizeof(T) == 2) || (sizeof(T) == 1))
+ {
+ // For small sizes we must have an integer type
+ // so we can just use the static_cast.
+ //
+ return static_cast<unsigned>(val);
+ }
+ else
+ {
+ // Only support Hashing for types that are 8,4,2 or 1 bytes in size
+ assert(!"Unsupported size");
+ return static_cast<unsigned>(val); // compile-time error here when we have a illegal size
+ }
}
};
diff --git a/src/inc/sospriv.idl b/src/inc/sospriv.idl
index 9ef6cc2ffa..48c76cbf87 100644
--- a/src/inc/sospriv.idl
+++ b/src/inc/sospriv.idl
@@ -336,3 +336,15 @@ interface ISOSDacInterface2 : IUnknown
HRESULT GetObjectExceptionData(CLRDATA_ADDRESS objAddr, struct DacpExceptionObjectData *data);
HRESULT IsRCWDCOMProxy(CLRDATA_ADDRESS rcwAddr, BOOL* isDCOMProxy);
};
+
+[
+ object,
+ local,
+ uuid(B08C5CDC-FD8A-49C5-AB38-5FEEF35235B4)
+]
+interface ISOSDacInterface3 : IUnknown
+{
+ HRESULT GetGCInterestingInfoData(CLRDATA_ADDRESS interestingInfoAddr, struct DacpGCInterestingInfoData *data);
+ HRESULT GetGCInterestingInfoStaticData(struct DacpGCInterestingInfoData *data);
+ HRESULT GetGCGlobalMechanisms(size_t* globalMechanisms);
+}; \ No newline at end of file
diff --git a/src/inc/switches.h b/src/inc/switches.h
index b298b5563b..dd4da272c0 100644
--- a/src/inc/switches.h
+++ b/src/inc/switches.h
@@ -20,6 +20,8 @@
#define VERIFY_HEAP
#endif
+#define GC_CONFIG_DRIVEN
+
// define this to test data safety for the DAC. See code:DataTest::TestDataSafety.
#define TEST_DATA_CONSISTENCY