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

Extensive runtime refactor to reduce generated executable sizes

This commit is contained in:
Brian Fiete 2024-03-16 07:23:29 -04:00
parent 4e750a7e1a
commit ddd9b1b218
74 changed files with 2514 additions and 717 deletions

View file

@ -26,7 +26,7 @@ enum BfObjectFlags : uint8
BfObjectFlag_StackAlloc = 0x08,
BfObjectFlag_AppendAlloc = 0x10,
BfObjectFlag_AllocInfo = 0x20,
BfObjectFlag_AllocInfo_Short= 0x40,
BfObjectFlag_AllocInfo_Short= 0x40,
BfObjectFlag_Deleted = 0x80
};
@ -36,7 +36,7 @@ enum BfRtFlags
BfRtFlags_LeakCheck = 2,
BfRtFlags_SilentCrash = 4,
BfRtFlags_DebugAlloc = 8,
BfRtFlags_NoThreadExitWait = 0x10,
BfRtFlags_NoThreadExitWait = 0x10,
};
namespace bf
@ -90,7 +90,7 @@ namespace bf
bf::System::Object* (*Object_DynamicCastToTypeId)(bf::System::Object* obj, int typeId);
void(*Type_GetFullName)(System::Type* type, bf::System::String* str);
bf::System::String* (*String_Alloc)();
const char* (*String_ToCStr)(bf::System::String* str);
Beefy::StringView (*String_ToStringView)(bf::System::String* str);
bf::System::Threading::Thread* (*Thread_Alloc)();
bf::System::Threading::Thread* (*Thread_GetMainThread)();
void(*Thread_ThreadProc)(bf::System::Threading::Thread* thread);
@ -98,24 +98,26 @@ namespace bf
void(*Thread_SetInternalThread)(bf::System::Threading::Thread* thread, BfInternalThread* internalThread);
bool(*Thread_IsAutoDelete)(bf::System::Threading::Thread* thread);
void(*Thread_AutoDelete)(bf::System::Threading::Thread* thread);
int32(*Thread_GetMaxStackSize)(bf::System::Threading::Thread* thread);
int32(*Thread_GetMaxStackSize)(bf::System::Threading::Thread* thread);
void(*Thread_Exiting)();
void(*GC_MarkAllStaticMembers)();
bool(*GC_CallRootCallbacks)();
void(*GC_Shutdown)();
void(*SetErrorString)(const char* str);
void(*DebugMessageData_SetupError)(const char* str, int32 stackWindbackCount);
void(*DebugMessageData_SetupProfilerCmd)(const char* str);
void(*DebugMessageData_SetupProfilerCmd)(const char* str);
void(*DebugMessageData_Fatal)();
void(*DebugMessageData_Clear)();
int(*CheckErrorHandler)(const char* kind, const char* arg1, const char* arg2, intptr arg3);
int(*CheckErrorHandler)(const char* kind, const char* arg1, const char* arg2, intptr arg3);
};
public:
BFRT_EXPORT static void SetCrashReportKind(RtCrashReportKind crashReportKind);
BFRT_EXPORT static void SetCrashReportKind(RtCrashReportKind crashReportKind);
private:
BFRT_EXPORT static void Init(int version, int flags, BfRtCallbacks* callbacks);
BFRT_EXPORT static void Init(int version, int flags, BfRtCallbacks* callbacks);
BFRT_EXPORT static void InitCrashCatcher(int flags);
BFRT_EXPORT static void ShutdownCrashCatcher();
BFRT_EXPORT static void AddCrashInfoFunc(void* func);
BFRT_EXPORT static void SetErrorString(char* errorStr);
BFRT_EXPORT static void Dbg_Init(int version, int flags, BfRtCallbacks* callbacks);
@ -150,7 +152,7 @@ namespace bf
public:
union
{
intptr mClassVData;
intptr mClassVData;
struct
{
BfObjectFlags mObjectFlags;
@ -193,7 +195,7 @@ namespace bf
TypeId mTypeId;
TypeId mBoxedId;
uint16 mTypeFlags;
int32 mMemberDataOffset;
int32 mMemberDataOffset;
uint8 mTypeCode;
uint8 mAlign;
@ -225,7 +227,7 @@ namespace bf
String* mName;
String* mNamespace;
int32 mInstSize;
int32 mInstAlign;
int32 mInstAlign;
};
}
@ -252,9 +254,9 @@ namespace bf
uint mAllocSizeAndFlags;
char* mPtr;
const char* CStr()
Beefy::StringView ToStringView()
{
return BFRTCALLBACKS.String_ToCStr(this);
return BFRTCALLBACKS.String_ToStringView(this);
}
};
}

View file

@ -52,6 +52,7 @@
USING_NS_BF;
static Beefy::StringT<0> gCmdLineString;
bool gCmdLineStringHandled;
bf::System::Runtime::BfRtCallbacks gBfRtCallbacks;
BfRtFlags gBfRtFlags = (BfRtFlags)0;
@ -65,7 +66,10 @@ static int gTestMethodIdx = -1;
static uint32 gTestStartTick = 0;
static bool gTestBreakOnFailure = false;
typedef void(*ClientPipeErrorFunc)(const Beefy::StringView& error, int stackOffset);
static BfpFile* gClientPipe = NULL;
static ClientPipeErrorFunc gClientPipeErrorFunc;
static Beefy::String gTestInBuffer;
namespace bf
@ -85,7 +89,7 @@ namespace bf
BFRT_EXPORT static void BfStaticCtor();
BFRT_EXPORT static void BfStaticDtor();
BFRT_EXPORT static void Shutdown();
BFRT_EXPORT static void Shutdown_Internal();
public:
BFRT_EXPORT static Object* UnsafeCastToObject(void* inPtr);
BFRT_EXPORT static void* UnsafeCastToPtr(Object* obj);
@ -224,18 +228,8 @@ static void Internal_FatalError(const char* error)
if (gBfRtCallbacks.CheckErrorHandler != NULL)
gBfRtCallbacks.CheckErrorHandler("FatalError", error, NULL, 0);
if ((gClientPipe != NULL) && (!gTestBreakOnFailure))
{
Beefy::String str = ":TestFatal\t";
str += error;
str.Replace('\n', '\r');
str += "\n";
TestString(str);
Beefy::String result;
TestReadCmd(result);
exit(1);
}
if (gClientPipeErrorFunc != NULL)
gClientPipeErrorFunc(error, 0);
else
BfpSystem_FatalError(error, "BEEF FATAL ERROR");
}
@ -304,57 +298,22 @@ void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
if ((flags & 4) != 0)
sysInitFlags = (BfpSystemInitFlags)(sysInitFlags | BfpSystemInitFlag_SilentCrash);
BfpSystem_Init(BFP_VERSION, sysInitFlags);
BfpSystem_AddCrashInfoFunc(GetCrashInfo);
if (gBfRtCallbacks.Alloc != NULL)
{
Internal_FatalError(StrFormat("BeefRT already initialized. Multiple executable modules in the same process cannot dynamically link to the Beef runtime.").c_str());
Internal_FatalError("BeefRT already initialized. Multiple executable modules in the same process cannot dynamically link to the Beef runtime.");
}
if (version != BFRT_VERSION)
{
BfpSystem_FatalError(StrFormat("BeefRT build version '%d' does not match requested version '%d'", BFRT_VERSION, version).c_str(), "BEEF FATAL ERROR");
char error[256];
sprintf(error, "BeefRT build version '%d' does not match requested version '%d'", BFRT_VERSION, version);
BfpSystem_FatalError(error, "BEEF FATAL ERROR");
}
gBfRtCallbacks = *callbacks;
gBfRtFlags = (BfRtFlags)flags;
Beefy::String cmdLine;
BfpSystemResult result;
BFP_GETSTR_HELPER(cmdLine, result, BfpSystem_GetCommandLine(__STR, __STRLEN, &result));
char* cmdLineStr = (char*)cmdLine.c_str();
//::MessageBoxA(NULL, cmdLineStr, "BFRT", 0);
char* useCmdLineStr = cmdLineStr;
if (cmdLineStr[0] != 0)
{
bool nameQuoted = cmdLineStr[0] == '\"';
Beefy::String passedName;
int i;
for (i = (nameQuoted ? 1 : 0); cmdLineStr[i] != 0; i++)
{
wchar_t c = cmdLineStr[i];
if (((nameQuoted) && (c == '"')) ||
((!nameQuoted) && (c == ' ')))
{
i++;
break;
}
passedName += cmdLineStr[i];
}
useCmdLineStr += i;
while (*useCmdLineStr == L' ')
useCmdLineStr++;
}
gCmdLineString = useCmdLineStr;
#ifdef BF_PLATFORM_WINDOWS
gBfTLSKey = FlsAlloc(TlsFreeFunc);
#else
@ -362,6 +321,20 @@ void bf::System::Runtime::Init(int version, int flags, BfRtCallbacks* callbacks)
#endif
}
void bf::System::Runtime::InitCrashCatcher(int flags)
{
BfpSystemInitFlags sysInitFlags = BfpSystemInitFlag_InstallCrashCatcher;
if ((flags & 4) != 0)
sysInitFlags = (BfpSystemInitFlags)(sysInitFlags | BfpSystemInitFlag_SilentCrash);
BfpSystem_InitCrashCatcher(sysInitFlags);
BfpSystem_AddCrashInfoFunc(GetCrashInfo);
}
void bf::System::Runtime::ShutdownCrashCatcher()
{
BfpSystem_ShutdownCrashCatcher();
}
void bf::System::Runtime::SetErrorString(char* errorStr)
{
::SetErrorString(errorStr);
@ -379,7 +352,7 @@ void bf::System::Runtime::SetCrashReportKind(bf::System::Runtime::RtCrashReportK
//////////////////////////////////////////////////////////////////////////
void Internal::Shutdown()
void Internal::Shutdown_Internal()
{
BfInternalThread::WaitForAllDone();
if (gBfRtCallbacks.GC_Shutdown != NULL)
@ -419,20 +392,9 @@ void* Internal::UnsafeCastToPtr(Object* obj)
void Internal::ThrowIndexOutOfRange(intptr stackOffset)
{
if (gClientPipe != NULL)
{
if (gTestBreakOnFailure)
{
SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
BF_DEBUG_BREAK();
}
Beefy::String str = ":TestFail\tIndex out of range\n";
TestString(str);
exit(1);
}
if ((stackOffset != -1) && (::IsDebuggerPresent()))
if (gClientPipeErrorFunc != NULL)
gClientPipeErrorFunc("Index out of range", 0);
else if ((stackOffset != -1) && (::IsDebuggerPresent()))
{
SETUP_ERROR("Index out of range", (int)(2 + stackOffset));
BF_DEBUG_BREAK();
@ -443,20 +405,9 @@ void Internal::ThrowIndexOutOfRange(intptr stackOffset)
void Internal::ThrowObjectNotInitialized(intptr stackOffset)
{
if (gClientPipe != NULL)
{
if (gTestBreakOnFailure)
{
SETUP_ERROR("Object not initialized", (int)(2 + stackOffset));
BF_DEBUG_BREAK();
}
Beefy::String str = ":TestFail\tObject not initialized\n";
TestString(str);
exit(1);
}
if ((stackOffset != -1) && (::IsDebuggerPresent()))
if (gClientPipeErrorFunc != NULL)
gClientPipeErrorFunc("Object not initialized", 0);
else if ((stackOffset != -1) && (::IsDebuggerPresent()))
{
SETUP_ERROR("Object not initialized", (int)(2 + stackOffset));
BF_DEBUG_BREAK();
@ -467,29 +418,17 @@ void Internal::ThrowObjectNotInitialized(intptr stackOffset)
void Internal::FatalError(bf::System::String* error, intptr stackOffset)
{
if (gClientPipe != NULL)
{
if (gTestBreakOnFailure)
{
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
BF_DEBUG_BREAK();
}
Beefy::String str = ":TestFail\t";
str += error->CStr();
str.Replace('\n', '\r');
str += "\n";
TestString(str);
exit(1);
}
Beefy::StringView errorStringView = error->ToStringView();
Beefy::StringSimple errorString = errorStringView;
if (gClientPipeErrorFunc != NULL)
gClientPipeErrorFunc(errorStringView, 0);
if ((stackOffset != -1) && (::IsDebuggerPresent()))
{
SETUP_ERROR(error->CStr(), (int)(2 + stackOffset));
SETUP_ERROR(errorString.c_str(), (int)(2 + stackOffset));
BF_DEBUG_BREAK();
}
Internal_FatalError(error->CStr());
Internal_FatalError(errorString.c_str());
}
void Internal::MemCpy(void* dest, void* src, intptr length)
@ -630,6 +569,46 @@ void Internal::GetSharedProcAddressInto(void* libHandle, char* procName, void**
char* Internal::GetCommandLineArgs()
{
if (!gCmdLineStringHandled)
{
Beefy::String cmdLine;
BfpSystemResult result;
BFP_GETSTR_HELPER(cmdLine, result, BfpSystem_GetCommandLine(__STR, __STRLEN, &result));
char* cmdLineStr = (char*)cmdLine.c_str();
//::MessageBoxA(NULL, cmdLineStr, "BFRT", 0);
char* useCmdLineStr = cmdLineStr;
if (cmdLineStr[0] != 0)
{
bool nameQuoted = cmdLineStr[0] == '\"';
Beefy::String passedName;
int i;
for (i = (nameQuoted ? 1 : 0); cmdLineStr[i] != 0; i++)
{
wchar_t c = cmdLineStr[i];
if (((nameQuoted) && (c == '"')) ||
((!nameQuoted) && (c == ' ')))
{
i++;
break;
}
passedName += cmdLineStr[i];
}
useCmdLineStr += i;
while (*useCmdLineStr == L' ')
useCmdLineStr++;
}
gCmdLineString = useCmdLineStr;
gCmdLineStringHandled = true;
}
return (char*)gCmdLineString.c_str();
}
@ -697,6 +676,27 @@ static void TestReadCmd(Beefy::String& str)
}
}
void TestFailed(const Beefy::StringView& error, int stackOffset)
{
if (gClientPipe != NULL)
{
Beefy::String errorString = error;
if (gTestBreakOnFailure)
{
SETUP_ERROR(errorString.c_str(), (int)(2 + stackOffset));
BF_DEBUG_BREAK();
}
Beefy::String str = ":TestFail\t";
str += errorString.c_str();
str.Replace('\n', '\r');
str += "\n";
TestString(str);
exit(1);
}
}
void Internal::Test_Init(char* testData)
{
BfpSystem_SetCrashReportKind(BfpCrashReportKind_None);
@ -708,6 +708,8 @@ void Internal::Test_Init(char* testData)
if (fileResult != BfpFileResult_Ok)
BF_FATAL("Test_Init failed to create pipe to test manager");
gClientPipeErrorFunc = TestFailed;
Beefy::String outStr;
outStr += ":TestInit\n";
outStr += testData;
@ -853,7 +855,6 @@ void Internal::ObjectDynCheck(bf::System::Object* object, int typeId, bool allow
if (result == NULL)
{
Beefy::String errorStr = "Attempting invalid cast on object";
//errorStr += StrFormat("\x1LEAK\t0x%@\n (%s)0x%@\n", object, object->GetTypeName().c_str(), object);
errorStr += StrFormat("\x1LEAK\t0x%@\n (%s)0x%@\n", object, "System.Object", object);
SETUP_ERROR(errorStr.c_str(), 2);
BF_DEBUG_BREAK();

View file

@ -7,7 +7,7 @@ Beefy::String bf::System::Object::GetTypeName()
String* strObj = BFRTCALLBACKS.String_Alloc();
Type* type = _GetType();
BFRTCALLBACKS.Type_GetFullName(type, strObj);
Beefy::String str = strObj->CStr();
Beefy::String str = strObj->ToStringView();
BFRTCALLBACKS.Object_Delete(strObj);
return str;
}
@ -16,7 +16,7 @@ Beefy::String bf::System::Type::GetFullName()
{
String* strObj = BFRTCALLBACKS.String_Alloc();
BFRTCALLBACKS.Type_GetFullName(this, strObj);
Beefy::String str = strObj->CStr();
Beefy::String str = strObj->ToStringView();
BFRTCALLBACKS.Object_Delete(strObj);
return str;
}

View file

@ -1,4 +1,4 @@
#include "BeefySysLib/Common.h"
#include "BeefySysLib/Common.h"
#include "BfObjects.h"
#include "Thread.h"
//#include "ThreadLocalStorage.h"
@ -32,24 +32,24 @@ bf::System::Threading::Thread* BfGetCurrentThread()
#else
Thread* internalThread = (Thread*)BfpTLS_GetValue(BfTLSManager::sInternalThreadKey);
return internalThread;
#endif
#endif
}
void Thread::Suspend()
{
BfpThread_Suspend(GetInternalThread()->mThreadHandle, NULL);
BfpThread_Suspend(GetInternalThread()->mThreadHandle, NULL);
}
void Thread::Resume()
{
BfpThread_Resume(GetInternalThread()->mThreadHandle, NULL);
BfpThread_Resume(GetInternalThread()->mThreadHandle, NULL);
}
void Thread::SetJoinOnDelete(bool joinOnDelete)
{
auto internalThread = GetInternalThread();
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
internalThread->mJoinOnDelete = joinOnDelete;
auto internalThread = GetInternalThread();
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
internalThread->mJoinOnDelete = joinOnDelete;
}
int Thread::GetPriorityNative()
@ -59,7 +59,7 @@ int Thread::GetPriorityNative()
void Thread::SetPriorityNative(int priority)
{
return BfpThread_SetPriority(GetInternalThread()->mThreadHandle, (BfpThreadPriority)(priority - 2), NULL);
return BfpThread_SetPriority(GetInternalThread()->mThreadHandle, (BfpThreadPriority)(priority - 2), NULL);
}
bool Thread::GetIsAlive()
@ -80,7 +80,7 @@ bool Thread::JoinInternal(int millisecondsTimeout)
auto internalThread = GetInternalThread();
if (internalThread == NULL)
return true;
bool success = BfpThread_WaitFor(internalThread->mThreadHandle, millisecondsTimeout);
bool success = BfpThread_WaitFor(internalThread->mThreadHandle, millisecondsTimeout);
return success;
}
@ -121,7 +121,7 @@ static void BF_CALLTYPE CStartProc(void* threadParam)
#endif
auto internalThread = thread->GetInternalThread();
// Hold lock until we get ThreadStarted callback
internalThread->mCritSect.Lock();
@ -130,16 +130,16 @@ static void BF_CALLTYPE CStartProc(void* threadParam)
internalThread->mStackStart = (intptr)&thread;
internalThread->ThreadStarted();
bool isAutoDelete = gBfRtCallbacks.Thread_IsAutoDelete(thread);
bool isAutoDelete = gBfRtCallbacks.Thread_IsAutoDelete(thread);
gBfRtCallbacks.Thread_ThreadProc(thread);
bool isLastThread = BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, -1) == 1;
//printf("Stopping thread\n");
bool wantsDelete = false;
//
{
internalThread->ThreadStopped();
{
internalThread->ThreadStopped();
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
if (isAutoDelete)
@ -149,8 +149,8 @@ static void BF_CALLTYPE CStartProc(void* threadParam)
if (internalThread->mThread == NULL)
{
// If the thread was already deleted then we need to delete ourselves now
wantsDelete = true;
// If the thread was already deleted then we need to delete ourselves now
wantsDelete = true;
}
}
@ -164,53 +164,53 @@ static void BF_CALLTYPE CStartProc(void* threadParam)
}
void BfInternalThread::WaitForAllDone()
{
{
if ((gBfRtFlags & BfRtFlags_NoThreadExitWait) != 0)
return;
while (gLiveThreadCount != 0)
{
// Clear out any old done events
gThreadsDoneEvent.WaitFor();
gThreadsDoneEvent.WaitFor();
}
}
BfInternalThread* Thread::SetupInternalThread()
{
BfInternalThread* internalThread;
BfInternalThread* internalThread;
internalThread = new BfInternalThread();
SetInternalThread(internalThread);
SetInternalThread(internalThread);
return internalThread;
}
void Thread::ManualThreadInit()
{
{
#ifdef BF_THREAD_TLS
sCurrentThread = this;
#else
BfpTLS_SetValue(BfTLSManager::sInternalThreadKey, this);
#endif
BfInternalThread* internalThread = SetupInternalThread();
internalThread->ManualThreadInit(this);
}
void Thread::StartInternal()
{
{
BfpSystem_InterlockedExchangeAdd32((uint32*)&gLiveThreadCount, 1);
BfInternalThread* internalThread = SetupInternalThread();
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
internalThread->mStarted = true;
internalThread->mThread = this;
#ifdef _WIN32
internalThread->mThreadHandle = BfpThread_Create(CStartProc, (void*)this, GetMaxStackSize(), (BfpThreadCreateFlags)(BfpThreadCreateFlag_StackSizeReserve | BfpThreadCreateFlag_Suspended), &internalThread->mThreadId);
SetInternalThread(internalThread);
SetInternalThread(internalThread);
BfpThread_Resume(internalThread->mThreadHandle, NULL);
#else
internalThread->mThreadHandle = BfpThread_Create(CStartProc, (void*)this, GetMaxStackSize(), (BfpThreadCreateFlags)(BfpThreadCreateFlag_StackSizeReserve), &internalThread->mThreadId);
SetInternalThread(internalThread);
SetInternalThread(internalThread);
#endif
}
@ -220,9 +220,9 @@ void Thread::RequestExitNotify()
if (BfGetCurrentThread() != NULL)
return;
#ifdef BF_PLATFORM_WINDOWS
#ifdef BF_PLATFORM_WINDOWS
FlsSetValue(gBfTLSKey, (void*)&gBfRtCallbacks);
#else
#else
pthread_setspecific(gBfTLSKey, (void*)&gBfRtCallbacks);
#endif
}
@ -249,7 +249,7 @@ void Thread::InternalFinalize()
auto internalThread = GetInternalThread();
if (internalThread == NULL)
return;
bool wantsJoin = false;
bool started = false;
@ -264,12 +264,12 @@ void Thread::InternalFinalize()
//
{
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
if ((!internalThread->mDone) && (internalThread->mJoinOnDelete))
{
if (this != BfGetCurrentThread())
{
wantsJoin = true;
wantsJoin = true;
}
}
}
@ -278,19 +278,19 @@ void Thread::InternalFinalize()
JoinInternal(0);
bool wantsDelete = false;
//
//
{
Beefy::AutoCrit autoCrit(internalThread->mCritSect);
if (!internalThread->mDone)
{
// We need to let the internal thread delete itself when it's done...
internalThread->mThread = NULL;
}
else
{
wantsDelete = true;
}
{
wantsDelete = true;
}
SetInternalThread(NULL);
}
@ -298,7 +298,7 @@ void Thread::InternalFinalize()
wantsDelete = true;
if (wantsDelete)
delete internalThread;
delete internalThread;
}
bool Thread::IsBackgroundNative()
@ -317,8 +317,11 @@ int Thread::GetThreadStateNative()
}
void Thread::InformThreadNameChange(String* name)
{
BfpThread_SetName(GetInternalThread()->mThreadHandle, (name != NULL) ? name->CStr() : "", NULL);
{
Beefy::String nameStr;
if (name != NULL)
nameStr = name->ToStringView();
BfpThread_SetName(GetInternalThread()->mThreadHandle, nameStr.c_str(), NULL);
}
void Thread::MemoryBarrier()