1
0
Fork 0
mirror of https://github.com/beefytech/Beef.git synced 2025-06-08 03:28:20 +02:00

Beefy::String changes, lambda hotswap fixes

Changed some string internals related to StringViewsma
Added an "incompatible capture" error for lambdas when the captures change
This commit is contained in:
Brian Fiete 2019-09-03 11:17:13 -07:00
parent 767a3fafd9
commit 2f01cc14dd
25 changed files with 544 additions and 180 deletions

View file

@ -390,7 +390,7 @@ String DbgSubprogram::ToString()
{
if (mLinkName[0] == '<')
return mLinkName;
str = BfDemangler::Demangle(mLinkName, language);
str = BfDemangler::Demangle(StringImpl::MakeRef(mLinkName), language);
// Strip off the params since we need to generate those ourselves
int parenPos = (int)str.IndexOf('(');
if (parenPos != -1)
@ -776,6 +776,13 @@ bool DbgSubprogram::ThisIsSplat()
return strncmp(mBlock.mVariables.mHead->mName, "$this$", 6) == 0;
}
bool DbgSubprogram::IsLambda()
{
if (mName == NULL)
return false;
return StringView(mName).Contains('$');
}
//////////////////////////////////////////////////////////////////////////
DbgSubprogram::~DbgSubprogram()
@ -863,7 +870,7 @@ void DbgSrcFile::RehupLineData()
for (int idx = 0; idx < (int)mLineDataRefs.size(); idx++)
{
auto dbgSubprogram = mLineDataRefs[idx];
if (dbgSubprogram->mWasModuleHotReplaced)
if (dbgSubprogram->mHotReplaceKind != DbgSubprogram::HotReplaceKind_None)
{
mLineDataRefs.RemoveAtFast(idx);
idx--;
@ -1548,6 +1555,7 @@ String DbgType::ToString(DbgLanguage language, bool allowDirectBfObject)
else
return mParent->ToString(language) + "::" + nameP;
}
switch (mTypeCode)
{
@ -1999,6 +2007,39 @@ DbgModule::~DbgModule()
delete data;
}
DbgSubprogram* DbgModule::FindSubprogram(DbgType* dbgType, const char * methodName)
{
dbgType = dbgType->GetPrimaryType();
dbgType->PopulateType();
if (dbgType->mNeedsGlobalsPopulated)
PopulateTypeGlobals(dbgType);
for (auto methodNameEntry : dbgType->mMethodNameList)
{
if ((methodNameEntry->mCompileUnitId != -1) && (strcmp(methodNameEntry->mName, methodName) == 0))
{
// If we hot-replaced this type then we replaced and parsed all the methods too
if (!dbgType->mCompileUnit->mDbgModule->mIsHotObjectFile)
dbgType->mCompileUnit->mDbgModule->MapCompileUnitMethods(methodNameEntry->mCompileUnitId);
methodNameEntry->mCompileUnitId = -1;
}
}
DbgSubprogram* result = NULL;
for (auto method : dbgType->mMethodList)
{
if (strcmp(method->mName, methodName) == 0)
{
method->PopulateSubprogram();
if ((result == NULL) || (method->mBlock.mLowPC != 0))
result = method;
}
}
return result;
}
void DbgModule::Fail(const StringImpl& error)
{
if (mFailMsgPtr != NULL)
@ -4960,7 +5001,8 @@ void DbgModule::HotReplaceType(DbgType* newType)
HashSet<DbgSrcFile*> checkedFiles;
for (auto method : primaryType->mMethodList)
{
method->mWasModuleHotReplaced = true;
//method->mWasModuleHotReplaced = true;
method->mHotReplaceKind = DbgSubprogram::HotReplaceKind_Orphaned; // May be temporarily orphaned
if (method->mLineInfo == NULL)
continue;
@ -5014,35 +5056,154 @@ void DbgModule::HotReplaceType(DbgType* newType)
primaryType->mHotReplacedMethodList.PushFront(method);
mHotPrimaryTypes.Add(primaryType);
}
Dictionary<StringView, DbgSubprogram*> oldProgramMap;
for (auto oldMethod : primaryType->mHotReplacedMethodList)
{
oldMethod->PopulateSubprogram();
if (oldMethod->mBlock.IsEmpty())
continue;
auto symInfo = mDebugTarget->mSymbolMap.Get(oldMethod->mBlock.mLowPC);
if (symInfo != NULL)
{
oldProgramMap.TryAdd(symInfo->mName, oldMethod);
}
}
bool setHotJumpFailed = false;
while (!newType->mMethodList.IsEmpty())
{
DbgSubprogram* newMethod = newType->mMethodList.PopFront();
if (!newMethod->mBlock.IsEmpty())
{
newMethod->PopulateSubprogram();
newMethod->PopulateSubprogram();
bool found = false;
for (auto oldMethod : primaryType->mHotReplacedMethodList)
auto symInfo = mDebugTarget->mSymbolMap.Get(newMethod->mBlock.mLowPC);
if (symInfo != NULL)
{
if (oldMethod->mBlock.IsEmpty())
continue;
if (oldMethod->Equals(newMethod))
DbgSubprogram* oldMethod = NULL;
if (oldProgramMap.TryGetValue(symInfo->mName, &oldMethod))
{
if (!setHotJumpFailed)
bool doHotJump = false;
if (oldMethod->Equals(newMethod))
{
if (!mDebugger->SetHotJump(oldMethod, newMethod))
setHotJumpFailed = true;
oldMethod->mWasHotReplaced = true;
}
doHotJump = true;
}
else
{
// When mangles match but the actual signatures don't match, that can mean that the call signature was changed
// and thus it's actually a different method and shouldn't hot jump OR it could be lambda whose captures changed.
// When the lambda captures change, the user didn't actually enter a different signature so we want to do a hard
// fail if the old code gets called to avoid confusion of "why aren't my changes working?"
// If we removed captures then we can still do the hot jump. Otherwise we have to fail...
doHotJump = false;
if ((oldMethod->IsLambda()) && (oldMethod->GetParamCount() == 0) && (newMethod->GetParamCount() == 0) &&
(oldMethod->mHasThis) && (newMethod->mHasThis))
{
auto oldParam = oldMethod->mParams.front();
auto newParam = newMethod->mParams.front();
if ((oldParam->mType->IsPointer()) && (newParam->mType->IsPointer()))
{
auto oldType = oldParam->mType->mTypeParam->GetPrimaryType();
auto newType = newParam->mType->mTypeParam->GetPrimaryType();
if ((oldType->IsStruct()) && (newType->IsStruct()))
{
bool wasMatch = true;
auto oldMember = oldType->mMemberList.front();
auto newMember = newType->mMemberList.front();
while (newMember != NULL)
{
if (oldMember == NULL)
{
wasMatch = false;
break;
}
if ((oldMember->mName == NULL) || (newMember->mName == NULL))
{
wasMatch = false;
break;
}
if (strcmp(oldMember->mName, newMember->mName) != 0)
{
wasMatch = false;
break;
}
if (!oldMember->mType->Equals(newMember->mType))
{
wasMatch = false;
break;
}
oldMember = oldMember->mNext;
newMember = newMember->mNext;
}
if (wasMatch)
doHotJump = true;
}
}
if (!doHotJump)
{
mDebugTarget->mDebugger->PhysSetBreakpoint(oldMethod->mBlock.mLowPC);
oldMethod->mHotReplaceKind = DbgSubprogram::HotReplaceKind_Invalid;
}
}
}
if (doHotJump)
{
if (!setHotJumpFailed)
{
if (!mDebugger->SetHotJump(oldMethod, newMethod->mBlock.mLowPC, (int)(newMethod->mBlock.mHighPC - newMethod->mBlock.mLowPC)))
setHotJumpFailed = true;
}
oldMethod->mHotReplaceKind = DbgSubprogram::HotReplaceKind_Replaced;
}
}
}
}
}
newMethod->mParentType = primaryType;
primaryType->mMethodList.PushBack(newMethod);
}
//mDebugTarget->mSymbolMap.Get()
// bool setHotJumpFailed = false;
// while (!newType->mMethodList.IsEmpty())
// {
// DbgSubprogram* newMethod = newType->mMethodList.PopFront();
// if (!newMethod->mBlock.IsEmpty())
// {
// newMethod->PopulateSubprogram();
//
// bool found = false;
// for (auto oldMethod : primaryType->mHotReplacedMethodList)
// {
// if (oldMethod->mBlock.IsEmpty())
// continue;
// if (oldMethod->Equals(newMethod))
// {
// if (!setHotJumpFailed)
// {
// if (!mDebugger->SetHotJump(oldMethod, newMethod))
// setHotJumpFailed = true;
// oldMethod->mWasHotReplaced = true;
// }
// }
// }
// }
// newMethod->mParentType = primaryType;
// primaryType->mMethodList.PushBack(newMethod);
// }
primaryType->mCompileUnit->mWasHotReplaced = true;
primaryType->mNeedsGlobalsPopulated = newType->mNeedsGlobalsPopulated;