CONFIG_DWORD_INFO_EX(INTERNAL_MD_PreSaveBreak, W("MD_PreSaveBreak"), 0, "ASSERT when calling CMiniMdRw::PreSave", CLRConfig::EEConfig_default)
CONFIG_DWORD_INFO_EX(INTERNAL_MD_RegMetaBreak, W("MD_RegMetaBreak"), 0, "ASSERT when creating RegMeta class", CLRConfig::EEConfig_default)
CONFIG_DWORD_INFO_EX(INTERNAL_MD_RegMetaDump, W("MD_RegMetaDump"), 0, "Dump MD in 4 functions (?)", CLRConfig::EEConfig_default)
+RETAIL_CONFIG_STRING_INFO_EX(EXTERNAL_DOTNET_MODIFIABLE_ASSEMBLIES, W("DOTNET_MODIFIABLE_ASSEMBLIES"), "Enables hot reload on debug built assemblies with the 'debug' keyword", CLRConfig::DontPrependCOMPlus_ | CLRConfig::TrimWhiteSpaceFromStringValue);
// Metadata - mscordbi only - this flag is only intended to mitigate potential issues in bug fix 458597.
RETAIL_CONFIG_DWORD_INFO_EX(EXTERNAL_MD_PreserveDebuggerMetadataMemory, W("MD_PreserveDebuggerMetadataMemory"), 0, "Save all versions of metadata memory in the debugger when debuggee metadata is updated", CLRConfig::EEConfig_default)
Module::CreateAssemblyRefByNameTable(pamTracker);
}
- // If the program has the "ForceEnc" env variable set we ensure every eligible
- // module has EnC turned on.
- if (g_pConfig->ForceEnc() && IsEditAndContinueCapable())
- EnableEditAndContinue();
-
#if defined(PROFILING_SUPPORTED) && !defined(DACCESS_COMPILE) && !defined(CROSSGEN_COMPILE)
m_pJitInlinerTrackingMap = NULL;
if (ReJitManager::IsReJITInlineTrackingEnabled())
m_dwTransientFlags |= (newBits << DEBUGGER_INFO_SHIFT_PRIV);
#ifdef DEBUGGING_SUPPORTED
- BOOL setEnC = ((newBits & DACF_ENC_ENABLED) != 0) && IsEditAndContinueCapable();
-
- // The only way can change Enc is through debugger override.
- if (setEnC)
+ if (IsEditAndContinueCapable())
{
- EnableEditAndContinue();
- }
- else
- {
- if (!g_pConfig->ForceEnc())
- DisableEditAndContinue();
+ BOOL setEnC = (newBits & DACF_ENC_ENABLED) != 0 || g_pConfig->ForceEnc() || (g_pConfig->DebugAssembliesModifiable() && CORDisableJITOptimizations(GetDebuggerInfoBits()));
+ if (setEnC)
+ {
+ EnableEditAndContinue();
+ }
}
#endif // DEBUGGING_SUPPORTED
return m_moduleRef;
}
-
BOOL IsResource() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return GetFile()->IsResource(); }
BOOL IsPEFile() const { WRAPPER_NO_CONTRACT; return !GetFile()->IsDynamic(); }
BOOL IsReflection() const { WRAPPER_NO_CONTRACT; SUPPORTS_DAC; return GetFile()->IsDynamic(); }
// Returns true iff the debugger can see this module.
BOOL IsVisibleToDebugger();
-
BOOL IsEditAndContinueEnabled()
{
LIMITED_METHOD_CONTRACT;
SUPPORTS_DAC;
- // We are seeing cases where this flag is set for a module that is not an EditAndContinueModule. This should
- // never happen unless the module is EditAndContinueCapable, in which case we would have created an EditAndContinueModule
- // not a Module.
- //_ASSERTE((m_dwTransientFlags & IS_EDIT_AND_CONTINUE) == 0 || IsEditAndContinueCapable());
- return (IsEditAndContinueCapable()) && ((m_dwTransientFlags & IS_EDIT_AND_CONTINUE) != 0);
+ _ASSERTE((m_dwTransientFlags & IS_EDIT_AND_CONTINUE) == 0 || IsEditAndContinueCapable());
+ return (m_dwTransientFlags & IS_EDIT_AND_CONTINUE) != 0;
}
- BOOL IsEditAndContinueCapable();
+ virtual BOOL IsEditAndContinueCapable() const { return FALSE; }
BOOL IsIStream() { LIMITED_METHOD_CONTRACT; return GetFile()->IsIStream(); }
{
LIMITED_METHOD_CONTRACT;
SUPPORTS_DAC;
- // _ASSERTE(IsEditAndContinueCapable());
+ _ASSERTE(IsEditAndContinueCapable());
LOG((LF_ENC, LL_INFO100, "EnableEditAndContinue: this:0x%x, %s\n", this, GetDebugName()));
m_dwTransientFlags |= IS_EDIT_AND_CONTINUE;
}
- void DisableEditAndContinue()
- {
- LIMITED_METHOD_CONTRACT;
- SUPPORTS_DAC;
- // don't _ASSERTE(IsEditAndContinueCapable());
- LOG((LF_ENC, LL_INFO100, "DisableEditAndContinue: this:0x%x, %s\n", this, GetDebugName()));
- m_dwTransientFlags = m_dwTransientFlags.Load() & (~IS_EDIT_AND_CONTINUE);
- }
-
BOOL IsTenured()
{
LIMITED_METHOD_CONTRACT;
#endif //DACCESS_COMPILE
-inline BOOL Module::IsEditAndContinueCapable()
-{
- WRAPPER_NO_CONTRACT;
- SUPPORTS_DAC;
-
- BOOL isEnCCapable = IsEditAndContinueCapable(m_pAssembly, m_file);
-
- // for now, Module::IsReflection is equivalent to m_file->IsDynamic,
- // which is checked by IsEditAndContinueCapable(m_pAssembly, m_file)
- _ASSERTE(!isEnCCapable || (!this->IsReflection()));
-
- return isEnCCapable;
-}
-
FORCEINLINE PTR_DomainLocalModule Module::GetDomainLocalModule()
{
WRAPPER_NO_CONTRACT;
fStressLog = GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_StressLog, fStressLog) != 0;
fForceEnc = GetConfigDWORD_DontUse_(CLRConfig::UNSUPPORTED_ForceEnc, fForceEnc) != 0;
+ {
+ NewArrayHolder<WCHAR> wszModifiableAssemblies;
+ IfFailRet(CLRConfig::GetConfigValue(CLRConfig::EXTERNAL_DOTNET_MODIFIABLE_ASSEMBLIES, &wszModifiableAssemblies));
+ if (wszModifiableAssemblies)
+ fDebugAssembliesModifiable = _wcsicmp(wszModifiableAssemblies, W("debug")) == 0;
+ }
+
iRequireZaps = RequireZapsType(GetConfigDWORD_DontUse_(CLRConfig::EXTERNAL_ZapRequire, iRequireZaps));
if (IsCompilationProcess() || iRequireZaps >= REQUIRE_ZAPS_COUNT)
iRequireZaps = REQUIRE_ZAPS_NONE;
bool StressLog() const { LIMITED_METHOD_CONTRACT; return fStressLog; }
bool ForceEnc() const { LIMITED_METHOD_CONTRACT; return fForceEnc; }
+ bool DebugAssembliesModifiable() const { LIMITED_METHOD_CONTRACT; return fDebugAssembliesModifiable; }
// Optimizations to improve working set
bool fStressLog;
bool fForceEnc;
+ bool fDebugAssembliesModifiable;
bool fProbeForStackOverflow;
// Stackwalk optimization flag
virtual void Destruct();
#endif
+ virtual BOOL IsEditAndContinueCapable() const { return TRUE; }
+
// Apply an EnC edit
HRESULT ApplyEditAndContinue(DWORD cbMetadata,
BYTE *pMetadata,