From 7877868f8b44c206697845a85f60b2d6e3f5f6ca Mon Sep 17 00:00:00 2001 From: mitrokosta Date: Fri, 14 May 2021 23:58:14 +0300 Subject: [PATCH] Rewrite FuncTable --- src/apps/ENGINE/compiler.cpp | 99 ++++---- src/apps/ENGINE/compiler.h | 5 +- src/apps/ENGINE/expression.cpp | 14 +- src/apps/ENGINE/s_debug.cpp | 4 +- src/apps/ENGINE/s_functab.cpp | 433 +++++++++++---------------------- src/apps/ENGINE/s_functab.h | 116 +++++---- 6 files changed, 252 insertions(+), 419 deletions(-) diff --git a/src/apps/ENGINE/compiler.cpp b/src/apps/ENGINE/compiler.cpp index e2dc22828..ef5a8facd 100644 --- a/src/apps/ENGINE/compiler.cpp +++ b/src/apps/ENGINE/compiler.cpp @@ -581,7 +581,7 @@ void COMPILER::FindErrorSource() void COMPILER::SetEventHandler(const char *event_name, const char *func_name, long flag, bool bStatic) { - FUNCINFO fi; + FuncInfo fi; if (event_name == nullptr) { @@ -696,7 +696,7 @@ VDATA *COMPILER::ProcessEvent(const char *event_name) BC_Execute(ei.pFuncInfo[n].func_code, pResult); RDTSC_E(nTicks); - FUNCINFO fi; + FuncInfo fi; // if(FuncTab.GetFuncX(fi,ei.pFuncInfo[n].func_code)) if (FuncTab.GetFuncX(fi, func_code)) { @@ -964,7 +964,7 @@ bool COMPILER::ProcessDebugExpression0(const char *pExpression, DATA &Result) if (pRun_fi) { - CurrentFuncCode = pRun_fi->code; + CurrentFuncCode = FuncTab.FindFunc(pRun_fi->name); } try @@ -988,7 +988,7 @@ bool COMPILER::ProcessDebugExpression0(const char *pExpression, DATA &Result) // save current pointers values const uint32_t mem_InstructionPointer = InstructionPointer; // mem_ip = ip; - FUNCINFO *mem_pfi = pRun_fi; + FuncInfo *mem_pfi = pRun_fi; const char *mem_codebase = pRunCodeBase; // mem_CurrentFuncCode = CurrentFuncCode; @@ -1176,7 +1176,7 @@ void COMPILER::CompileToken(SEGMENT_DESC &Segment, S_TOKEN_TYPE Token_type, uint bool COMPILER::InitInternalFunctions() { - FUNCINFO fi; + FuncInfo fi; // register internal functions ------------ @@ -1198,7 +1198,7 @@ bool COMPILER::InitInternalFunctions() func_code = FuncTab.FindFunc(fi.name); FuncTab.GetFunc(fi, func_code); // SetError("Duplicate function name: %s",fi.name); - SetError("Function [%s] already declared in: %s line %d", fi.name, fi.decl_file_name, fi.decl_line); + SetError("Function [%s] already declared in: %s line %d", fi.name.c_str(), fi.decl_file_name.c_str(), fi.decl_line); return false; } } @@ -1214,9 +1214,9 @@ bool COMPILER::Compile(SEGMENT_DESC &Segment, char *pInternalCode, uint32_t pInt char *pProgram; char *pApend_file; char *pSegmentSource; - FUNCINFO fi; + FuncInfo fi; VarInfo vi; - LVARINFO lvi; + LocalVarInfo lvi; CLASSINFO ci; CLASSINFO cci; uint32_t SegmentSize; @@ -1526,7 +1526,7 @@ bool COMPILER::Compile(SEGMENT_DESC &Segment, char *pInternalCode, uint32_t pInt fi.arguments = 0; fi.decl_file_name = DebugSourceFileName; fi.decl_line = DebugSourceLine; - fi.pImportedFunc = nullptr; + fi.imported_func = nullptr; func_code = FuncTab.AddFunc(fi); if (func_code == INVALID_FUNC_CODE) @@ -1534,7 +1534,7 @@ bool COMPILER::Compile(SEGMENT_DESC &Segment, char *pInternalCode, uint32_t pInt func_code = FuncTab.FindFunc(fi.name); FuncTab.GetFunc(fi, func_code); // SetError("Duplicate function name: %s",fi.name); - SetError("Function [%s] already declared in: %s line %d", fi.name, fi.decl_file_name, + SetError("Function [%s] already declared in: %s line %d", fi.name.c_str(), fi.decl_file_name.c_str(), fi.decl_line); return false; @@ -1785,7 +1785,6 @@ bool COMPILER::Compile(SEGMENT_DESC &Segment, char *pInternalCode, uint32_t pInt strcpy_s(var_name, Token.GetData()); lvi.name = var_name; lvi.elements = 1; - lvi.bArray = false; Token.Get(); if (Token.GetType() == SQUARE_OPEN_BRACKET) { @@ -1802,26 +1801,25 @@ bool COMPILER::Compile(SEGMENT_DESC &Segment, char *pInternalCode, uint32_t pInt } else { - SetError("Invalid array (%s) size", lvi.name); + SetError("Invalid array (%s) size", lvi.name.c_str()); return false; } } else { - SetError("Invalid array (%s) size", lvi.name); + SetError("Invalid array (%s) size", lvi.name.c_str()); return false; } } else lvalue = static_cast(atoll(Token.GetData())); lvi.elements = lvalue; - lvi.bArray = true; Token.Get(); // SQUARE_CLOSE_BRACKET Token.Get(); } if (!FuncTab.AddFuncVar(func_code, lvi)) { - SetError("Duplicate variable name: %s", lvi.name); + SetError("Duplicate variable name: %s", lvi.name.c_str()); return false; } } while (Token.GetType() == COMMA); @@ -2205,7 +2203,7 @@ bool COMPILER::CompileBlock(SEGMENT_DESC &Segment, bool &bFunctionBlock, uint32_ uint32_t dwRCode; VarInfo vi; - LVARINFO lvi; + LocalVarInfo lvi; jump_offset = 0xffbadbad; @@ -2945,7 +2943,7 @@ bool COMPILER::CompileBlock(SEGMENT_DESC &Segment, bool &bFunctionBlock, uint32_ case UNKNOWN: { uint32_t func_code; uint32_t func_args; - FUNCINFO fi; + FuncInfo fi; if (DetectUnknown(func_code) == CALL_FUNCTION) { @@ -2993,7 +2991,7 @@ bool COMPILER::CompileBlock(SEGMENT_DESC &Segment, bool &bFunctionBlock, uint32_ if (fi.offset == INVALID_FUNC_OFFSET) { // external function declared but not compiled yet - fi.arguments = fi.ext_args; + fi.arguments = fi.extern_arguments; } // off for debug needs @@ -3005,7 +3003,7 @@ bool COMPILER::CompileBlock(SEGMENT_DESC &Segment, bool &bFunctionBlock, uint32_ case INTERNAL_SEGMENT_ID: if (!IsIntFuncVarArgsNum(func_code)) { - SetError("function '%s(args:%d)' doesnt accept %d arguments", fi.name, fi.arguments, + SetError("function '%s(args:%d)' doesnt accept %d arguments", fi.name.c_str(), fi.arguments, func_args); return false; } @@ -3014,7 +3012,7 @@ bool COMPILER::CompileBlock(SEGMENT_DESC &Segment, bool &bFunctionBlock, uint32_ // skip imported funcs checking for now break; default: - SetError("function %s(args:%d) doesnt accept %d arguments", fi.name, fi.arguments, func_args); + SetError("function %s(args:%d) doesnt accept %d arguments", fi.name.c_str(), fi.arguments, func_args); return false; } @@ -3690,10 +3688,10 @@ S_TOKEN_TYPE COMPILER::NextTokenType() bool COMPILER::BC_CallFunction(uint32_t func_code, uint32_t &ip, DATA *&pVResult) { - FUNCINFO call_fi; + FuncInfo call_fi; uint32_t mem_ip; uint32_t mem_InstructionPointer; - FUNCINFO *mem_pfi; + FuncInfo *mem_pfi; // DATA * pV; const char *mem_codebase; uint32_t arguments; @@ -3781,7 +3779,7 @@ bool COMPILER::BC_CallFunction(uint32_t func_code, uint32_t &ip, DATA *&pVResult { pVResult = nullptr; RDTSC_B(nTicks); - const uint32_t nResult = call_fi.pImportedFunc(&SStack); + const uint32_t nResult = call_fi.imported_func(&SStack); if (nResult == IFUNCRESULT_OK) { if (call_fi.return_type != TVOID) @@ -3811,7 +3809,7 @@ bool COMPILER::BC_CallFunction(uint32_t func_code, uint32_t &ip, DATA *&pVResult { if (check_sp != (SStack.GetDataNum() - 1)) { - SetError("function '%s' stack error", call_fi.name); + SetError("function '%s' stack error", call_fi.name.c_str()); pRun_fi = mem_pfi; InstructionPointer = mem_InstructionPointer; @@ -3827,7 +3825,7 @@ bool COMPILER::BC_CallFunction(uint32_t func_code, uint32_t &ip, DATA *&pVResult { if (check_sp != SStack.GetDataNum()) { - SetError("function '%s' stack error", call_fi.name); + SetError("function '%s' stack error", call_fi.name.c_str()); pRun_fi = mem_pfi; InstructionPointer = mem_InstructionPointer; ip = mem_ip; @@ -3864,7 +3862,7 @@ bool COMPILER::BC_Execute(uint32_t function_code, DATA *&pVReturnResult, const c uint32_t bLeftOperandType; long nLeftOperandIndex; S_TOKEN_TYPE Token_type; - FUNCINFO fi; + FuncInfo fi; VarInfo vi; DATA *pV; DATA *pVResult; @@ -3899,39 +3897,36 @@ bool COMPILER::BC_Execute(uint32_t function_code, DATA *&pVReturnResult, const c pVReturnResult = nullptr; pVResult = nullptr; - PZERO(&fi, sizeof(fi)); - if (pDbgExpSource == nullptr) { - // PZERO(&fi,sizeof(fi)); if (!FuncTab.GetFunc(fi, function_code)) { - SetError("Invalid function: %s", fi.name); + SetError("Invalid function: %s", fi.name.c_str()); return false; } if (fi.offset == INVALID_FUNC_OFFSET) { - SetError("Function (%s) isnt loaded", fi.name); + SetError("Function (%s) isnt loaded", fi.name.c_str()); return false; } if (fi.segment_id == INTERNAL_SEGMENT_ID) { - SetError("Function (%s) is internal", fi.name); + SetError("Function (%s) is internal", fi.name.c_str()); return false; } if (fi.segment_id == IMPORTED_SEGMENT_ID) { - SetError("Function (%s) is imported", fi.name); + SetError("Function (%s) is imported", fi.name.c_str()); return false; } segment_index = GetSegmentIndex(fi.segment_id); if (segment_index == INVALID_SEGMENT_INDEX) { - SetError("Function (%s) segment not loaded", fi.name); + SetError("Function (%s) segment not loaded", fi.name.c_str()); return false; } if (SegmentTable[segment_index].pCode == nullptr) @@ -3949,10 +3944,10 @@ bool COMPILER::BC_Execute(uint32_t function_code, DATA *&pVReturnResult, const c // check arguments types for (n = 0; n < fi.arguments; n++) { - if (fi.pLocal[n].type == VAR_REFERENCE) + if (fi.local_vars[n].type == VAR_REFERENCE) continue; pV = SStack.Read(fi.stack_offset, n); - if (pV->GetType() != fi.pLocal[n].type) + if (pV->GetType() != fi.local_vars[n].type) { pV = pV->GetVarPointer(); if (!pV) @@ -3961,22 +3956,22 @@ bool COMPILER::BC_Execute(uint32_t function_code, DATA *&pVReturnResult, const c return false; } - if (fi.pLocal[n].type == VAR_AREFERENCE && pV->GetType() == VAR_OBJECT) + if (fi.local_vars[n].type == VAR_AREFERENCE && pV->GetType() == VAR_OBJECT) continue; // TODO: remove and fix - if (false && pV->GetType() != fi.pLocal[n].type) + if (false && pV->GetType() != fi.local_vars[n].type) { - SetWarning("wrong type of argument %d %s(%s) <-- [%s]", n, fi.name, - Token.GetTypeName(fi.pLocal[n].type), Token.GetTypeName(pV->GetType())); + SetWarning("wrong type of argument %d %s(%s) <-- [%s]", n, fi.name.c_str(), + Token.GetTypeName(fi.local_vars[n].type), Token.GetTypeName(pV->GetType())); } } } - for (n = fi.arguments; n < fi.var_num; n++) + for (n = fi.arguments; n < fi.local_vars.size(); n++) { pV = SStack.Push(); - pV->SetType(fi.pLocal[n].type, fi.pLocal[n].elements); + pV->SetType(fi.local_vars[n].type, fi.local_vars[n].elements); } pRun_fi = &fi; // set pointer to 'this' function info @@ -4358,7 +4353,7 @@ bool COMPILER::BC_Execute(uint32_t function_code, DATA *&pVReturnResult, const c ShowWindow(CDebug.GetWindowHandle(), SW_NORMAL); CDebug.SetTraceLine(nDebugTraceLineCode); - CDebug.BreakOn(fi.decl_file_name, nDebugTraceLineCode); + CDebug.BreakOn(fi.decl_file_name.c_str(), nDebugTraceLineCode); CDebug.SetTraceMode(TMODE_WAIT); while (CDebug.GetTraceMode() == TMODE_WAIT) { @@ -4372,7 +4367,7 @@ bool COMPILER::BC_Execute(uint32_t function_code, DATA *&pVReturnResult, const c else if (CDebug.Breaks.CanBreak()) { // check for breakpoint - if (CDebug.Breaks.Find(fi.decl_file_name, nDebugTraceLineCode)) + if (CDebug.Breaks.Find(fi.decl_file_name.c_str(), nDebugTraceLineCode)) { if (!CDebug.IsDebug()) CDebug.OpenDebugWindow(core.GetAppInstance()); @@ -4380,7 +4375,7 @@ bool COMPILER::BC_Execute(uint32_t function_code, DATA *&pVReturnResult, const c ShowWindow(CDebug.GetWindowHandle(), SW_NORMAL); // CDebug.OpenDebugWindow(core.hInstance); CDebug.SetTraceMode(TMODE_WAIT); - CDebug.BreakOn(fi.decl_file_name, nDebugTraceLineCode); + CDebug.BreakOn(fi.decl_file_name.c_str(), nDebugTraceLineCode); while (CDebug.GetTraceMode() == TMODE_WAIT) { @@ -7040,7 +7035,7 @@ void COMPILER::AddRuntimeEvent() uint32_t COMPILER::SetScriptFunction(IFUNCINFO *pFuncInfo) { - FUNCINFO fi; + FuncInfo fi; if (pFuncInfo->pFuncName == nullptr) { @@ -7065,13 +7060,8 @@ uint32_t COMPILER::SetScriptFunction(IFUNCINFO *pFuncInfo) } fi.name = pFuncInfo->pFuncName; - fi.decl_file_name = pFuncInfo->pDeclFileName; - if (fi.decl_file_name == nullptr) - fi.decl_file_name = "unknown"; - fi.decl_line = pFuncInfo->nDeclLine; - fi.pImportedFunc = pFuncInfo->pFuncAddress; + fi.imported_func = pFuncInfo->pFuncAddress; fi.arguments = pFuncInfo->nArguments; - fi.var_num = 0; fi.segment_id = IMPORTED_SEGMENT_ID; fi.offset = INVALID_FUNC_OFFSET; fi.stack_offset = 0xffffffff; @@ -7104,11 +7094,6 @@ uint32_t COMPILER::SetScriptFunction(IFUNCINFO *pFuncInfo) return funch; } -void COMPILER::DeleteScriptFunction(uint32_t nFuncHandle) -{ - FuncTab.InvalidateFunction(nFuncHandle); -} - DATA *COMPILER::GetOperand(const char *pCodeBase, uint32_t &ip, S_TOKEN_TYPE *pTokenType) { uint32_t token_data_size; diff --git a/src/apps/ENGINE/compiler.h b/src/apps/ENGINE/compiler.h index df09a8c52..269c29838 100644 --- a/src/apps/ENGINE/compiler.h +++ b/src/apps/ENGINE/compiler.h @@ -126,8 +126,8 @@ class COMPILER : public VIRTUAL_COMPILER char *pDebExpBuffer; uint32_t nDebExpBufferSize; - FUNCINFO *pRun_fi; // running function info - S_FUNCTAB FuncTab; + FuncInfo *pRun_fi; // running function info + FuncTable FuncTab; VarTable VarTab; S_CLASSTAB ClassTab; S_DEFTAB DefTab; @@ -327,7 +327,6 @@ class COMPILER : public VIRTUAL_COMPILER void AddRuntimeEvent(); uint32_t SetScriptFunction(IFUNCINFO *pFuncInfo); - void DeleteScriptFunction(uint32_t nFuncHandle); bool CompileExpression(SEGMENT_DESC &Segment); bool CompileExpression_L0(SEGMENT_DESC &Segment); diff --git a/src/apps/ENGINE/expression.cpp b/src/apps/ENGINE/expression.cpp index 098a95cd6..3cf0486b3 100644 --- a/src/apps/ENGINE/expression.cpp +++ b/src/apps/ENGINE/expression.cpp @@ -861,7 +861,7 @@ bool COMPILER::CompileExpression(SEGMENT_DESC &Segment) { uint32_t dwVarCode; VarInfo vi; - LVARINFO lvi; + LocalVarInfo lvi; const S_TOKEN_TYPE Token_type = CompileAuxiliaryTokens(Segment); if (Token_type == SEPARATOR) @@ -914,11 +914,11 @@ bool COMPILER::CompileExpression(SEGMENT_DESC &Segment) { FuncTab.GetVar(lvi, CurrentFuncCode, dwVarCode); // check for possibilities of '[' operator - if (!lvi.bArray) + if (!lvi.IsArray()) { if (lvi.type != VAR_REFERENCE) { - SetError(" B Invalid '[' operator, %s - isnt array", lvi.name); + SetError(" B Invalid '[' operator, %s - isnt array", lvi.name.c_str()); return false; } } @@ -1233,8 +1233,8 @@ bool COMPILER::CompileExpression_L7(SEGMENT_DESC &Segment) uint32_t dwVarCode; uint32_t dwAWCode; VarInfo vi; - LVARINFO lvi; - FUNCINFO fi; + LocalVarInfo lvi; + FuncInfo fi; bool bDynamicCall = false; switch (Token.GetType()) @@ -1480,11 +1480,11 @@ bool COMPILER::CompileExpression_L7(SEGMENT_DESC &Segment) { FuncTab.GetVar(lvi, CurrentFuncCode, dwVarCode); // check for possibilities of '[' operator - if (!lvi.bArray) + if (!lvi.IsArray()) { if (lvi.type != VAR_REFERENCE) { - SetError(" D Invalid '[' operator, %s - isnt array", lvi.name); + SetError(" D Invalid '[' operator, %s - isnt array", lvi.name.c_str()); return false; } } diff --git a/src/apps/ENGINE/s_debug.cpp b/src/apps/ENGINE/s_debug.cpp index 1262831c7..a573ceff2 100644 --- a/src/apps/ENGINE/s_debug.cpp +++ b/src/apps/ENGINE/s_debug.cpp @@ -541,8 +541,8 @@ const char *S_DEBUG::ProcessExpression(const char *pExpression) uint32_t S_DEBUG::GetLineStatus(const char *_pFileName, uint32_t _linecode) { // nDebugTraceLineCode - if (core.Compiler->pRun_fi && core.Compiler->pRun_fi->decl_file_name) - if (_stricmp(core.Compiler->pRun_fi->decl_file_name, _pFileName) == 0) + if (core.Compiler->pRun_fi && !core.Compiler->pRun_fi->decl_file_name.empty()) + if (_stricmp(core.Compiler->pRun_fi->decl_file_name.c_str(), _pFileName) == 0) { if (_linecode == core.Compiler->nDebugTraceLineCode) return LST_CONTROL; diff --git a/src/apps/ENGINE/s_functab.cpp b/src/apps/ENGINE/s_functab.cpp index 6edc8ceed..8065160bd 100644 --- a/src/apps/ENGINE/s_functab.cpp +++ b/src/apps/ENGINE/s_functab.cpp @@ -1,387 +1,238 @@ #include "s_functab.h" -/*DWORD _testfunc(VS_STACK * ps) +FuncInfo::FuncInfo() : + name(), + local_vars(), + segment_id(INVALID_SEGMENT_ID), + offset(INVALID_FUNC_OFFSET), + stack_offset(), + arguments(), + return_type(TVOID), + decl_file_name(), + decl_line(), + usage_time(), + number_of_calls(), + imported_func(), + extern_arguments() { - return 7; -}*/ +} -#define MAKEHASHINDEX(x) (x & 0xff) +FuncTable::~FuncTable() +{ + Release(); +} -S_FUNCTAB::S_FUNCTAB() +size_t FuncTable::FindFunc(const std::string &func_name) const { - Buffer_size = 0; - Func_num = 0; - for (uint32_t n = 0; n < HASHT_SIZE; n++) + auto result = hash_table_.find(func_name); + + if (result == hash_table_.end()) { - HashLine[n].nNumElements = 0; + return INVALID_FUNC_CODE; } -} -S_FUNCTAB::~S_FUNCTAB() -{ - Release(); + return result->second; } -void S_FUNCTAB::Release() +size_t FuncTable::AddFunc(const FuncInfo &fi) { - uint32_t n; - for (n = 0; n < Func_num; n++) + if (fi.name.empty()) { - delete pTable[n].name; - for (uint32_t i = 0; i < pTable[n].var_num; i++) - { - delete pTable[n].pLocal[i].name; - } - pTable[n].pLocal.clear(); - delete pTable[n].decl_file_name; - pTable[n].decl_file_name = nullptr; + return INVALID_FUNC_CODE; } - Buffer_size = 0; - Func_num = 0; - for (n = 0; n < HASHT_SIZE; n++) + + auto result = hash_table_.try_emplace(fi.name, funcs_.size()); // find or create index + auto func_index = result.first->second; + bool isNew = result.second; + + if (isNew) // newly created function, add to table { - HashLine[n].nNumElements = 0; + funcs_.push_back(fi); } -} -bool S_FUNCTAB::GetFunc(FUNCINFO &fi, uint32_t func_code) -{ - if (func_code >= Func_num) - return false; + auto &func = funcs_[func_index]; - if (pTable[func_code].segment_id == IMPORTED_SEGMENT_ID) + if (!isNew) { - if (pTable[func_code].pImportedFunc == nullptr) + if (func.offset != INVALID_FUNC_OFFSET) // function already loaded { - return false; + return INVALID_FUNC_CODE; } - fi = pTable[func_code]; - return true; - } - if (pTable[func_code].offset == INVALID_FUNC_OFFSET) - { - return false; + + func = fi; // function exists, but was unloaded, copy data } - fi = pTable[func_code]; - return true; -} -bool S_FUNCTAB::GetFuncX(FUNCINFO &fi, uint32_t func_code) -{ - if (func_code >= Func_num) - return false; - fi = pTable[func_code]; - return true; + return func_index; } -uint32_t S_FUNCTAB::AddFunc(const FUNCINFO &fi) +bool FuncTable::GetFunc(FuncInfo &fi, size_t func_index) const { - if (fi.name == nullptr) - return INVALID_FUNC_CODE; - const auto hash = MakeHashValue(fi.name); - auto hash_index = MAKEHASHINDEX(hash); - - const auto len = strlen(fi.decl_file_name) + 1; - for (uint32_t n = 0; n < Func_num; n++) + if (func_index >= funcs_.size()) { - if (pTable[n].hash != hash) - continue; - if (_stricmp(pTable[n].name, fi.name) != 0) - continue; - - // function with such name already registred, - if (pTable[n].offset == INVALID_FUNC_OFFSET) - { - // but offset isnt set (function segment unloaded) - // - set function segment and offset info - - pTable[n].fTimeUsage = 0; - pTable[n].nNumberOfCalls = 0; - pTable[n].offset = fi.offset; - pTable[n].segment_id = fi.segment_id; - pTable[n].decl_line = fi.decl_line; - pTable[n].pImportedFunc = fi.pImportedFunc; - - delete pTable[n].decl_file_name; - - // pTable[n].decl_file_name = new char[len]; - // memcpy(pTable[n].decl_file_name, fi.decl_file_name, len); - pTable[n].decl_file_name = _strdup(fi.decl_file_name); - pTable[n].code = n; - UpdateHashTable(n, hash, true); - return n; - } - // and already exist - // this is 'double function name' error - // (possible becose hash function error), user must rename function - return INVALID_FUNC_CODE; - } - // function not found, add anew one - // adjust buffer size - if (Func_num >= Buffer_size) - { - Buffer_size += FUNC_BUFFER_BLOCK_SIZE; - pTable.resize(Buffer_size); + return false; } - pTable[Func_num] = fi; - pTable[Func_num].hash = hash; - pTable[Func_num].name = nullptr; - pTable[Func_num].arguments = fi.arguments; - pTable[Func_num].ext_args = 0; - pTable[Func_num].var_num = 0; - pTable[Func_num].decl_line = fi.decl_line; - pTable[Func_num].fTimeUsage = 0; - pTable[Func_num].nNumberOfCalls = 0; - - // pTable[Func_num].decl_file_name = new char[len]; - // memcpy(pTable[Func_num].decl_file_name, fi.decl_file_name, len); - pTable[Func_num].decl_file_name = _strdup(fi.decl_file_name); - - pTable[Func_num].code = Func_num; - pTable[Func_num].pImportedFunc = fi.pImportedFunc; - - UpdateHashTable(Func_num, hash, true); - - /* DWORD a; - pTable[Func_num].pImportedFunc = testfunc; - a = pTable[Func_num].pImportedFunc(0); - */ - if constexpr (true) // bKeepName) + + if (funcs_[func_index].segment_id == IMPORTED_SEGMENT_ID) { - if (fi.name) + if (funcs_[func_index].imported_func == nullptr) { - // const auto len = strlen(fi.name) + 1; - // pTable[Func_num].name = new char[len]; - // memcpy(pTable[Func_num].name, fi.name, len); - pTable[Func_num].name = _strdup(fi.name); + return false; } + + fi = funcs_[func_index]; // copy func info + return true; } - Func_num++; - - return (Func_num - 1); -} -uint32_t S_FUNCTAB::MakeHashValue(const char *string) -{ - uint32_t hval = 0; - while (*string != 0) + if (funcs_[func_index].offset == INVALID_FUNC_OFFSET) { - auto v = *string++; - if ('A' <= v && v <= 'Z') - v += 'a' - 'A'; // case independent - hval = (hval << 4) + static_cast(v); - const uint32_t g = hval & (static_cast(0xf) << (32 - 4)); - if (g != 0) - { - hval ^= g >> (32 - 8); - hval ^= g; - } + return false; } - return hval; + + fi = funcs_[func_index]; // copy func info + return true; } -void S_FUNCTAB::InvalidateBySegmentID(uint32_t segment_id) +bool FuncTable::GetFuncX(FuncInfo &fi, size_t func_index) const { - for (uint32_t n = 0; n < Func_num; n++) + if (func_index >= funcs_.size()) { - if (pTable[n].segment_id != segment_id) - continue; - UpdateHashTable(n, pTable[n].hash, false); - pTable[n].offset = INVALID_FUNC_OFFSET; - for (uint32_t i = 0; i < pTable[n].var_num; i++) - { - delete pTable[n].pLocal[i].name; - } - pTable[n].pLocal.clear(); - pTable[n].var_num = 0; - pTable[n].arguments = 0; - delete pTable[n].decl_file_name; - pTable[n].decl_file_name = nullptr; + return false; } + + fi = funcs_[func_index]; // copy func info + return true; } -void S_FUNCTAB::InvalidateFunction(uint32_t nFuncHandle) +void FuncTable::InvalidateBySegmentID(uint32_t segment_id) { - if (nFuncHandle < Func_num) + for (auto &fi : funcs_) { - const auto n = nFuncHandle; - UpdateHashTable(n, pTable[n].hash, false); - pTable[n].offset = INVALID_FUNC_OFFSET; - for (uint32_t i = 0; i < pTable[n].var_num; i++) + if (fi.segment_id == segment_id) { - delete pTable[n].pLocal[i].name; + fi.segment_id = INVALID_SEGMENT_ID; // hash is not deleted from table + fi.offset = INVALID_FUNC_OFFSET; + fi.local_vars.clear(); // delete local vars + fi.decl_file_name.clear(); } - pTable[n].pLocal.clear(); - // pTable[n].var_num = 0; - // pTable[n].arguments = 0; - delete pTable[n].decl_file_name; - pTable[n].decl_file_name = nullptr; - pTable[n].pImportedFunc = nullptr; } } -uint32_t S_FUNCTAB::FindFunc(const char *func_name) +bool FuncTable::SetFuncOffset(const std::string &func_name, uint32_t offset) { - if (func_name == nullptr) - return INVALID_FUNC_CODE; - const auto hash = MakeHashValue(func_name); + const auto func_index = FindFunc(func_name); - const auto hash_index = MAKEHASHINDEX(hash); - const auto nNum = HashLine[hash_index].nNumElements; - for (uint32_t n = 0; n < nNum; n++) + if (func_index == INVALID_FUNC_CODE) { - const auto ni = HashLine[hash_index].pElements[n]; - if (pTable[ni].hash == hash) - if (_stricmp(pTable[ni].name, func_name) == 0) - return ni; + return false; } - /* for(n=0;n= Func_num) - return false; - if (lvi.name == nullptr) + if (func_index >= funcs_.size()) + { return false; + } - const auto hash = MakeHashValue(lvi.name); - for (uint32_t n = 0; n < pTable[func_code].var_num; n++) + if (lvi.name.empty()) { - if (hash == pTable[func_code].pLocal[n].hash) // return false; - if (_stricmp(pTable[func_code].pLocal[n].name, lvi.name) == 0) - return false; + return false; } - const auto vindex = pTable[func_code].var_num; - pTable[func_code].var_num++; - pTable[func_code].pLocal.resize(pTable[func_code].var_num); - pTable[func_code].pLocal[vindex].name = nullptr; - if constexpr (true) // bKeepName) + if (FindVar(func_index, lvi.name) != INVALID_VAR_CODE) // var already exists { - // const auto len = strlen(lvi.name) + 1; - // pTable[func_code].pLocal[vindex].name = new char[len]; - // memcpy(pTable[func_code].pLocal[vindex].name, lvi.name, len); - pTable[func_code].pLocal[vindex].name = _strdup(lvi.name); + return false; } - pTable[func_code].pLocal[vindex].bArray = lvi.bArray; - pTable[func_code].pLocal[vindex].hash = hash; - pTable[func_code].pLocal[vindex].type = lvi.type; - pTable[func_code].pLocal[vindex].elements = lvi.elements; + + auto &var = funcs_[func_index].local_vars.emplace_back(lvi); + var.hash = hasher_(var.name); + return true; } -bool S_FUNCTAB::AddFuncArg(uint32_t func_code, LVARINFO &lvi, bool bExt) +bool FuncTable::AddFuncArg(size_t func_index, const LocalVarInfo &lvi, bool is_extern) { - if (func_code >= Func_num) + if (func_index >= funcs_.size()) + { return false; - if (bExt) + } + + if (is_extern) { - pTable[func_code].ext_args++; + ++funcs_[func_index].extern_arguments; return true; } - pTable[func_code].arguments++; - return AddFuncVar(func_code, lvi); + + ++funcs_[func_index].arguments; + return AddFuncVar(func_index, lvi); } -uint32_t S_FUNCTAB::FindVar(uint32_t func_code, const char *var_name) +size_t FuncTable::FindVar(size_t func_index, const std::string &var_name) const { - if (var_name == nullptr) + if (func_index >= funcs_.size()) + { return INVALID_VAR_CODE; - if (func_code >= Func_num) + } + + if (var_name.empty()) + { return INVALID_VAR_CODE; - const auto hash = MakeHashValue(var_name); - for (uint32_t n = 0; n < pTable[func_code].var_num; n++) + } + + const auto &vars = funcs_[func_index].local_vars; + size_t hash = hasher_(var_name); + const auto result = std::find_if(vars.begin(), vars.end(), [this, hash, &var_name](const LocalVarInfo &var) { + return var.hash == hash && comparator_(var.name, var_name); // fast comparison + }); + + if (result == vars.end()) { - if (hash == pTable[func_code].pLocal[n].hash) // return n; - if (_stricmp(var_name, pTable[func_code].pLocal[n].name) == 0) - return n; + return INVALID_VAR_CODE; } - return INVALID_VAR_CODE; + + return result - vars.begin(); } -bool S_FUNCTAB::GetVar(LVARINFO &lvi, uint32_t func_code, uint32_t var_code) +bool FuncTable::GetVar(LocalVarInfo &lvi, size_t func_index, size_t var_index) const { - if (func_code >= Func_num) + if (func_index >= funcs_.size()) + { return false; - if (var_code >= pTable[func_code].var_num) + } + + const auto &vars = funcs_[func_index].local_vars; + + if (var_index >= vars.size()) + { return false; - lvi = pTable[func_code].pLocal[var_code]; - return true; -} + } -void S_FUNCTAB::AddTime(uint32_t func_code, uint64_t time) -{ - if (func_code >= Func_num) - return; - pTable[func_code].fTimeUsage += time; -} + lvi = vars[var_index]; -void S_FUNCTAB::SetTimeUsage(uint32_t func_code, double f) -{ - if (func_code >= Func_num) - return; - pTable[func_code].fTimeUsage = f; + return true; } -void S_FUNCTAB::AddCall(uint32_t func_code) +void FuncTable::AddTime(size_t func_index, uint64_t time) { - if (func_code >= Func_num) - return; - pTable[func_code].nNumberOfCalls++; + if (func_index < funcs_.size()) + { + funcs_[func_index].usage_time += time; + } } -void S_FUNCTAB::UpdateHashTable(uint32_t code, uint32_t hash, bool in) +void FuncTable::AddCall(size_t func_index) { - const auto hash_index = MAKEHASHINDEX(hash); - - for (uint32_t n = 0; n < HashLine[hash_index].nNumElements; n++) + if (func_index < funcs_.size()) { - if (HashLine[hash_index].pElements[n] != code) - continue; - if (!in) - { - // take element out of list - HashLine[hash_index].pElements[n] = HashLine[hash_index].pElements[HashLine[hash_index].nNumElements - 1]; - HashLine[hash_index].nNumElements--; - HashLine[hash_index].pElements.resize(HashLine[hash_index].nNumElements); - return; - } - return; - // ok, already in list (? possible) + ++funcs_[func_index].number_of_calls; } - // not in list - add - HashLine[hash_index].nNumElements++; - HashLine[hash_index].pElements.resize(HashLine[hash_index].nNumElements); - HashLine[hash_index].pElements[HashLine[hash_index].nNumElements - 1] = code; +} + +void FuncTable::Release() +{ + funcs_.clear(); + hash_table_.clear(); } diff --git a/src/apps/ENGINE/s_functab.h b/src/apps/ENGINE/s_functab.h index 52bfb7ff1..a31b222c1 100644 --- a/src/apps/ENGINE/s_functab.h +++ b/src/apps/ENGINE/s_functab.h @@ -2,9 +2,10 @@ #include "s_import_func.h" #include "s_vartab.h" +#include "strutils.h" #include +#include -#define FUNC_BUFFER_BLOCK_SIZE 1024 #define INVALID_FUNC_CODE 0xffffffff #define INVALID_FUNC_OFFSET 0xffffffff #define INTERNAL_SEGMENT_ID 0xffffffff @@ -15,79 +16,76 @@ // when segment_id is INTERNAL_SEGMENT_ID, this function is internal and offset // means internal function number -struct LVARINFO +struct LocalVarInfo { + LocalVarInfo() = default; + + bool IsArray() + { + return elements > 1; + } + + std::string name; + size_t hash; // for faster comparison S_TOKEN_TYPE type; - uint32_t hash; - const char *name; - uint32_t elements; - bool bArray; + size_t elements; }; -struct FUNCINFO +struct FuncInfo { + FuncInfo(); + + std::string name; + + std::vector local_vars; + + // compiler info uint32_t segment_id; uint32_t offset; - uint32_t hash; - const char *name; - uint32_t arguments; - uint32_t var_num; uint32_t stack_offset; - std::vector pLocal; + uint32_t arguments; S_TOKEN_TYPE return_type; - const char *decl_file_name; + + // debug info + std::string decl_file_name; uint32_t decl_line; - uint32_t code; - double fTimeUsage; - uint32_t nNumberOfCalls; - SIMPORTFUNC pImportedFunc; - uint32_t ext_args; -}; -#define HASHT_SIZE 256 + // profile info + uint64_t usage_time; + uint32_t number_of_calls; -struct HASHLINE -{ - HASHLINE() - { - nNumElements = 0; - } - uint32_t nNumElements; - std::vector pElements; + // imported func info + SIMPORTFUNC imported_func; + uint32_t extern_arguments; }; -class S_FUNCTAB +class FuncTable { - uint32_t Buffer_size; - uint32_t Func_num; - std::vector pTable; - // bool bKeepName; + public: + FuncTable() = default; + ~FuncTable(); - HASHLINE HashLine[HASHT_SIZE]; + size_t FindFunc(const std::string &func_name) const; // get func index by name + size_t AddFunc(const FuncInfo &fi); // add func to table, returns func index + bool GetFunc(FuncInfo &fi, size_t func_index) const; // get func by index, returns true if func is registered and loaded + bool GetFuncX(FuncInfo &fi, size_t func_index) const; // get func by index, returns true if func is registered + void InvalidateBySegmentID(uint32_t segment_id); // invalidate all segment's functions + + bool SetFuncOffset(const std::string &func_name, uint32_t offset); // set func's compiler offset + bool AddFuncVar(size_t func_index, const LocalVarInfo &lvi); // add local var to func + bool AddFuncArg(size_t func_index, const LocalVarInfo &lvi, bool is_extern = false); // add arg to func (must precede all regular local vars in order not to break compiler logic) + size_t FindVar(size_t func_index, const std::string &var_name) const; // get func's local var or arg index by name + bool GetVar(LocalVarInfo &lvi, size_t func_index, size_t var_index) const; // get local var or arg by index - public: - S_FUNCTAB(); - ~S_FUNCTAB(); - uint32_t GetFuncNum() - { - return Func_num; - }; - uint32_t AddFunc(const FUNCINFO &fi); - bool GetFunc(FUNCINFO &fi, uint32_t func_code); // return true if func registred and loaded - bool GetFuncX(FUNCINFO &fi, uint32_t func_code); // return true if func registred - uint32_t MakeHashValue(const char *string); - // void KeepNameMode(bool on){bKeepName = on;}; - void Release(); - void InvalidateBySegmentID(uint32_t segment_id); - uint32_t FindFunc(const char *func_name); - bool SetFuncOffset(const char *func_name, uint32_t offset); - bool AddFuncVar(uint32_t func_code, LVARINFO &lvi); - bool AddFuncArg(uint32_t func_code, LVARINFO &lvi, bool bExt = false); - uint32_t FindVar(uint32_t func_code, const char *var_name); - void AddTime(uint32_t func_code, uint64_t time); - void SetTimeUsage(uint32_t func_code, double f); - void AddCall(uint32_t func_code); - void InvalidateFunction(uint32_t nFuncHandle); - void UpdateHashTable(uint32_t code, uint32_t hash, bool in); - bool GetVar(LVARINFO &lvi, uint32_t func_code, uint32_t var_code); + void AddTime(size_t func_index, uint64_t time); + void AddCall(size_t func_index); + + void Release(); // clear table + + private: + + std::vector funcs_; + CaseInsensitiveStringHasher hasher_; + CaseInsensitiveStringComparator comparator_; + std::unordered_map hash_table_; };