1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-09 03:52:19 +02:00

Improved hot compilation handling of DLLs

This commit is contained in:
Brian Fiete 2023-02-20 16:21:56 -05:00
parent 990b509111
commit c7ae0988dc
9 changed files with 84 additions and 9 deletions

View file

@ -16,6 +16,7 @@ namespace IDE
case DebugAfter; case DebugAfter;
case DebugComptime; case DebugComptime;
case Test; case Test;
case WhileRunning;
public bool WantsRunAfter public bool WantsRunAfter
{ {

View file

@ -25,7 +25,8 @@ namespace IDE.Debugger
Terminating, Terminating,
Terminated, Terminated,
SearchingSymSrv, SearchingSymSrv,
HotResolve HotResolve,
TargetUnloaded
} }
public enum IntDisplayType public enum IntDisplayType
@ -172,6 +173,9 @@ namespace IDE.Debugger
[CallingConvention(.Stdcall),CLink] [CallingConvention(.Stdcall),CLink]
static extern RunState Debugger_GetRunState(); static extern RunState Debugger_GetRunState();
[CallingConvention(.Stdcall),CLink]
static extern bool Debugger_HasLoadedTargetBinary();
[CallingConvention(.Stdcall),CLink] [CallingConvention(.Stdcall),CLink]
static extern char8* Debugger_GetCurrentException(); static extern char8* Debugger_GetCurrentException();
@ -534,6 +538,11 @@ namespace IDE.Debugger
return Debugger_GetRunState(); return Debugger_GetRunState();
} }
public bool HasLoadedTargetBinary()
{
return Debugger_HasLoadedTargetBinary();
}
public bool HasPendingDebugLoads() public bool HasPendingDebugLoads()
{ {
return Debugger_HasPendingDebugLoads(); return Debugger_HasPendingDebugLoads();
@ -561,8 +570,8 @@ namespace IDE.Debugger
public bool IsPaused(bool allowDebugEvalDone = false) public bool IsPaused(bool allowDebugEvalDone = false)
{ {
RunState runState = GetRunState(); RunState runState = GetRunState();
return (runState == RunState.Paused) || (runState == RunState.Breakpoint) || (runState == RunState.Exception) || return (runState == .Paused) || (runState == .Breakpoint) || (runState == .Exception) ||
((runState == RunState.DebugEval_Done) && (allowDebugEvalDone)); ((runState == .DebugEval_Done) && (allowDebugEvalDone));
} }
public void GetCurrentException(String exStr) public void GetCurrentException(String exStr)

View file

@ -4501,6 +4501,10 @@ namespace IDE
Compile(compileKind, null); Compile(compileKind, null);
} }
} }
else if ((mDebugger.mIsRunning) && (!mDebugger.HasLoadedTargetBinary()))
{
Compile(.WhileRunning, null);
}
else else
{ {
mOutputPanel.Clear(); mOutputPanel.Clear();
@ -11588,7 +11592,7 @@ namespace IDE
if (mExecutionQueue.Count > 0) if (mExecutionQueue.Count > 0)
return false; return false;
if ((mDebugger != null) && (mDebugger.mIsRunning) && (hotProject == null)) if ((mDebugger != null) && (mDebugger.mIsRunning) && (hotProject == null) && (compileKind != .WhileRunning))
{ {
Debug.Assert(!mDebugger.mIsRunningCompiled); Debug.Assert(!mDebugger.mIsRunningCompiled);
Debug.Assert((compileKind == .Normal) || (compileKind == .DebugComptime)); Debug.Assert((compileKind == .Normal) || (compileKind == .DebugComptime));
@ -13416,8 +13420,9 @@ namespace IDE
mBreakpointPanel.MarkStatsDirty(); mBreakpointPanel.MarkStatsDirty();
mTargetHadFirstBreak = true; mTargetHadFirstBreak = true;
if (mDebugger.GetRunState() == DebugManager.RunState.Exception) switch (mDebugger.GetRunState())
{ {
case .Exception:
String exceptionLine = scope String(); String exceptionLine = scope String();
mDebugger.GetCurrentException(exceptionLine); mDebugger.GetCurrentException(exceptionLine);
var exceptionData = String.StackSplit!(exceptionLine, '\n'); var exceptionData = String.StackSplit!(exceptionLine, '\n');
@ -13431,11 +13436,26 @@ namespace IDE
OutputLine(exString); OutputLine(exString);
if (!IsCrashDump) if (!IsCrashDump)
Fail(exString); Fail(exString);
default:
} }
} }
} }
break; break;
} }
else if ((mDebugger != null) && (mDebugger.GetRunState() == .TargetUnloaded))
{
if (mWorkspace.mHadHotCompileSinceLastFullCompile)
{
// Had hot compiles - we need to recompile!
Compile(.WhileRunning);
}
else
{
mDebugger.Continue();
}
mWorkspace.StoppedRunning();
break;
}
else if (mDebuggerPerformingTask) else if (mDebuggerPerformingTask)
{ {
break; break;

View file

@ -1108,6 +1108,14 @@ BF_EXPORT int BF_CALLTYPE Debugger_GetRunState()
return gDebugger->mRunState; return gDebugger->mRunState;
} }
BF_EXPORT bool Debugger_HasLoadedTargetBinary()
{
AutoCrit autoCrit(gDebugManager->mCritSect);
if (gDebugger == NULL)
return false;
return gDebugger->HasLoadedTargetBinary();
}
BF_EXPORT bool BF_CALLTYPE Debugger_HasPendingDebugLoads() BF_EXPORT bool BF_CALLTYPE Debugger_HasPendingDebugLoads()
{ {
if (gDebugger == NULL) if (gDebugger == NULL)

View file

@ -30,6 +30,8 @@ DebugTarget::DebugTarget(WinDebugger* debugger)
mCapturedNamesPtr = NULL; mCapturedNamesPtr = NULL;
mCapturedTypesPtr = NULL; mCapturedTypesPtr = NULL;
mHotHeap = NULL; mHotHeap = NULL;
mHotHeapAddr = 0;
mHotHeapReserveSize = 0;
mLastHotHeapCleanIdx = 0; mLastHotHeapCleanIdx = 0;
mIsEmpty = false; mIsEmpty = false;
mWasLocallyBuilt = false; mWasLocallyBuilt = false;
@ -107,12 +109,18 @@ void DebugTarget::SetupTargetBinary()
{ {
reservedPtr = (addr_target)VirtualAllocEx(mDebugger->mProcessInfo.hProcess, (void*)(intptr)checkHotReserveAddr, reserveSize, MEM_RESERVE, PAGE_EXECUTE_READWRITE); reservedPtr = (addr_target)VirtualAllocEx(mDebugger->mProcessInfo.hProcess, (void*)(intptr)checkHotReserveAddr, reserveSize, MEM_RESERVE, PAGE_EXECUTE_READWRITE);
if (reservedPtr != NULL) if (reservedPtr != NULL)
{
mHotHeapAddr = reservedPtr;
mHotHeapReserveSize = reserveSize;
BfLogDbg("VirtualAllocEx %p %d. ImageBase: %p\n", mHotHeapAddr, mHotHeapReserveSize, mTargetBinary->mImageBase);
break; break;
}
checkHotReserveAddr += 4 * mb; checkHotReserveAddr += 4 * mb;
} }
if (reservedPtr == 0) if (reservedPtr == 0)
{ {
BfLogDbg("VirtualAllocEx failed. ImageBase: %p\n", mTargetBinary->mImageBase);
mDebugger->Fail("Failed to reserve memory for hot swapping"); mDebugger->Fail("Failed to reserve memory for hot swapping");
} }
else else
@ -207,7 +215,7 @@ DbgModule* DebugTarget::SetupDyn(const StringImpl& filePath, DataStream* stream,
{ {
BP_ZONE("DebugTarget::SetupDyn"); BP_ZONE("DebugTarget::SetupDyn");
AutoDbgTime dbgTime("DebugTarget::SetupDyn " + filePath); //AutoDbgTime dbgTime("DebugTarget::SetupDyn " + filePath);
DbgModule* dwarf = new COFF(this); DbgModule* dwarf = new COFF(this);
dwarf->mFilePath = filePath; dwarf->mFilePath = filePath;
@ -239,7 +247,7 @@ String DebugTarget::UnloadDyn(addr_target imageBase)
{ {
String filePath; String filePath;
AutoDbgTime dbgTime("DebugTarget::UnloadDyn"); //AutoDbgTime dbgTime("DebugTarget::UnloadDyn");
for (int i = 0; i < (int)mDbgModules.size(); i++) for (int i = 0; i < (int)mDbgModules.size(); i++)
{ {
@ -252,7 +260,18 @@ String DebugTarget::UnloadDyn(addr_target imageBase)
filePath = dwarf->mFilePath; filePath = dwarf->mFilePath;
if (mTargetBinary == dwarf) if (mTargetBinary == dwarf)
{
mTargetBinary = NULL; mTargetBinary = NULL;
delete mHotHeap;
mHotHeap = NULL;
if (mHotHeapAddr != 0)
{
BfLogDbg("VirtualFreeEx %p %d\n", mHotHeapAddr, mHotHeapReserveSize);
::VirtualFreeEx(mDebugger->mProcessInfo.hProcess, (void*)(intptr)mHotHeapAddr, 0, MEM_RELEASE);
mHotHeapAddr = 0;
}
}
mDbgModules.RemoveAt(i); mDbgModules.RemoveAt(i);
bool success = mDbgModuleMap.Remove(dwarf->mId); bool success = mDbgModuleMap.Remove(dwarf->mId);

View file

@ -34,6 +34,8 @@ public:
Array<DbgType*>* mCapturedTypesPtr; Array<DbgType*>* mCapturedTypesPtr;
HotHeap* mHotHeap; HotHeap* mHotHeap;
addr_target mHotHeapAddr;
int64 mHotHeapReserveSize;
int mLastHotHeapCleanIdx; int mLastHotHeapCleanIdx;
String mTargetPath; String mTargetPath;
DbgModule* mLaunchBinary; DbgModule* mLaunchBinary;

View file

@ -159,7 +159,8 @@ enum RunState
RunState_Terminating, RunState_Terminating,
RunState_Terminated, RunState_Terminated,
RunState_SearchingSymSrv, RunState_SearchingSymSrv,
RunState_HotResolve RunState_HotResolve,
RunState_TargetUnloaded
}; };
enum DebuggerResult enum DebuggerResult
@ -268,6 +269,7 @@ public:
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled) = 0; virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled) = 0;
virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) = 0; virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) = 0;
virtual void Run() = 0; virtual void Run() = 0;
virtual bool HasLoadedTargetBinary() { return true; }
virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) = 0; virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) = 0;
virtual void InitiateHotResolve(DbgHotResolveFlags flags) = 0; virtual void InitiateHotResolve(DbgHotResolveFlags flags) = 0;
virtual intptr GetDbgAllocHeapSize() = 0; virtual intptr GetDbgAllocHeapSize() = 0;

View file

@ -1067,6 +1067,13 @@ void WinDebugger::Run()
CloseHandle(hThread); CloseHandle(hThread);
} }
bool WinDebugger::HasLoadedTargetBinary()
{
if (mDebugTarget == NULL)
return false;
return mDebugTarget->mTargetBinary != NULL;
}
void WinDebugger::HotLoad(const Array<String>& objectFiles, int hotIdx) void WinDebugger::HotLoad(const Array<String>& objectFiles, int hotIdx)
{ {
AutoCrit autoCrit(mDebugManager->mCritSect); AutoCrit autoCrit(mDebugManager->mCritSect);
@ -1891,10 +1898,16 @@ bool WinDebugger::DoUpdate()
} }
} }
bool hadTarget = mDebugTarget->mTargetBinary != NULL;
mDebugTarget->UnloadDyn(dbgModule->mImageBase); mDebugTarget->UnloadDyn(dbgModule->mImageBase);
if (needsBreakpointRehup) if (needsBreakpointRehup)
RehupBreakpoints(true); RehupBreakpoints(true);
if ((mDebugTarget->mTargetBinary == NULL) && (hadTarget))
{
mRunState = RunState_TargetUnloaded;
}
mPendingDebugInfoLoad.Remove(dbgModule); mPendingDebugInfoLoad.Remove(dbgModule);
mPendingDebugInfoRequests.Remove(dbgModule); mPendingDebugInfoRequests.Remove(dbgModule);
mDebugManager->mOutMessages.push_back("modulesChanged"); mDebugManager->mOutMessages.push_back("modulesChanged");
@ -2880,7 +2893,7 @@ void WinDebugger::ContinueDebugEvent()
} }
} }
if ((mRunState == RunState_Breakpoint) || (mRunState == RunState_Paused)) if ((mRunState == RunState_Breakpoint) || (mRunState == RunState_Paused) || (mRunState == RunState_TargetUnloaded))
{ {
ClearCallStack(); ClearCallStack();
mRunState = RunState_Running; mRunState = RunState_Running;

View file

@ -584,6 +584,7 @@ public:
virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled) override; virtual void OpenFile(const StringImpl& launchPath, const StringImpl& targetPath, const StringImpl& args, const StringImpl& workingDir, const Array<uint8>& envBlock, bool hotSwapEnabled) override;
virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) override; virtual bool Attach(int processId, BfDbgAttachFlags attachFlags) override;
virtual void Run() override; virtual void Run() override;
virtual bool HasLoadedTargetBinary() override;
virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) override; virtual void HotLoad(const Array<String>& objectFiles, int hotIdx) override;
virtual void InitiateHotResolve(DbgHotResolveFlags flags) override; virtual void InitiateHotResolve(DbgHotResolveFlags flags) override;
virtual intptr GetDbgAllocHeapSize() override; virtual intptr GetDbgAllocHeapSize() override;