| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- /*
- _____ __ ___ __ ____ _ __
- / ___/__ ___ _ ___ / |/ /__ ___ / /_____ __ __/ __/_______(_)__ / /_
- / (_ / _ `/ ' \/ -_) /|_/ / _ \/ _ \/ '_/ -_) // /\ \/ __/ __/ / _ \/ __/
- \___/\_,_/_/_/_/\__/_/ /_/\___/_//_/_/\_\\__/\_, /___/\__/_/ /_/ .__/\__/
- /___/ /_/
-
- See Copyright Notice in gmMachine.h
- */
- #include "gmConfig.h"
- #include "gmFunctionObject.h"
- #include "gmMachine.h"
- gmFunctionObject::gmFunctionObject()
- {
- m_cFunction = NULL;
- m_cUserData = NULL;
- m_debugInfo = NULL;
- m_byteCode = NULL;
- m_byteCodeLength = 0;
- m_maxStackSize = 1; // return value
- m_numLocals = 0;
- m_numParams = 0;
- m_numParamsLocals = 0;
- m_numReferences = 0;
- m_references = NULL;
- }
- void gmFunctionObject::Destruct(gmMachine * a_machine)
- {
- if(m_references)
- {
- a_machine->Sys_Free(m_references);
- m_references = NULL;
- }
- if(m_byteCode)
- {
- a_machine->Sys_Free(m_byteCode);
- m_byteCode = NULL;
- }
- if(m_debugInfo)
- {
- if(m_debugInfo->m_debugName) { a_machine->Sys_Free(m_debugInfo->m_debugName); }
- if(m_debugInfo->m_lineInfo) { a_machine->Sys_Free(m_debugInfo->m_lineInfo); }
- if(m_debugInfo->m_symbols)
- {
- int i;
- for(i = 0; i < m_numParamsLocals; ++i)
- {
- a_machine->Sys_Free(m_debugInfo->m_symbols[i]);
- }
- a_machine->Sys_Free(m_debugInfo->m_symbols);
- }
- a_machine->Sys_Free(m_debugInfo);
- m_debugInfo = NULL;
- }
- #if GM_USE_INCGC
- a_machine->DestructDeleteObject(this);
- #endif //GM_USE_INCGC
- }
- #if GM_USE_INCGC
- bool gmFunctionObject::Trace(gmMachine * a_machine, gmGarbageCollector* a_gc, const int a_workLeftToGo, int& a_workDone)
- {
- int i;
- for(i = 0; i < m_numReferences; ++i)
- {
- gmObject * object = a_machine->GetObject(m_references[i]);
- a_gc->GetNextObject(object);
- ++a_workDone;
- }
-
- ++a_workDone;
- return true;
- }
- #else //GM_USE_INCGC
- void gmFunctionObject::Mark(gmMachine * a_machine, gmuint32 a_mark)
- {
- if(m_mark != GM_MARK_PERSIST) m_mark = a_mark;
- int i;
- for(i = 0; i < m_numReferences; ++i)
- {
- gmObject * object = a_machine->GetObject(m_references[i]);
- if(object->NeedsMark(a_mark)) object->Mark(a_machine, a_mark);
- }
- }
- #endif //GM_USE_INCGC
- bool gmFunctionObject::Init(gmMachine * a_machine, bool a_debug, gmFunctionInfo &a_info, gmuint32 a_sourceId)
- {
- // byte code
- if(a_info.m_byteCodeLength)
- {
- m_byteCode = (gmuint8 *) a_machine->Sys_Alloc(a_info.m_byteCodeLength);
- memcpy(m_byteCode, a_info.m_byteCode, a_info.m_byteCodeLength);
- m_byteCodeLength = a_info.m_byteCodeLength;
- }
- else
- {
- m_byteCode = NULL;
- m_byteCodeLength = 0;
- }
- // stack info
- m_maxStackSize = a_info.m_maxStackSize;
- m_numLocals = a_info.m_numLocals;
- m_numParams = a_info.m_numParams;
- m_numParamsLocals = a_info.m_numParams + a_info.m_numLocals;
- // references
- m_numReferences = 0;
- m_references = NULL;
- if(m_byteCode)
- {
- // find the objects this function references by iterating over the byte code and collecting them.
- // we could perform this step in the compilation phase if we don't want to iterate over the byte code.
-
- gmptr * references = (gmptr *) GM_NEW( char[a_info.m_byteCodeLength] );
- union
- {
- const gmuint8 * instruction;
- const gmuint32 * instruction32;
- };
- instruction = (const gmuint8 *) m_byteCode;
- const gmuint8 * end = instruction + m_byteCodeLength;
- for(;instruction < end;)
- {
- switch(*(instruction32++))
- {
- case BC_GETDOT :
- case BC_SETDOT :
- case BC_BRA :
- case BC_BRZ :
- case BC_BRNZ :
- case BC_BRZK :
- case BC_BRNZK :
- case BC_FOREACH :
- case BC_GETGLOBAL :
- case BC_SETGLOBAL :
- case BC_GETTHIS :
- case BC_SETTHIS : instruction += sizeof(gmptr); break;
- case BC_PUSHINT : instruction += sizeof(gmint); break;
- case BC_PUSHFP : instruction += sizeof(gmfloat); break;
-
- case BC_CALL :
- case BC_GETLOCAL :
- case BC_SETLOCAL : instruction += sizeof(gmuint32); break;
- case BC_PUSHSTR :
- case BC_PUSHFN :
- {
- // if the reference does not already exist, add it.
- gmptr reference = *((gmptr *) instruction);
- instruction += sizeof(gmptr);
- int i;
- for(i = 0; i < m_numReferences; ++i)
- {
- if(references[i] == reference) break;
- }
- if(i == m_numReferences) references[m_numReferences++] = reference;
- break;
- }
- default : break;
- }
- }
- if(m_numReferences > 0)
- {
- m_references = (gmptr *) a_machine->Sys_Alloc(sizeof(gmptr) * m_numReferences);
- memcpy(m_references, references, sizeof(gmptr) * m_numReferences);
- }
- delete [] (char*) references;
- }
-
- // debug info
- m_debugInfo = NULL;
- if(a_debug)
- {
- m_debugInfo = (gmFunctionObjectDebugInfo *) a_machine->Sys_Alloc(sizeof(gmFunctionObjectDebugInfo));
- memset(m_debugInfo, 0, sizeof(gmFunctionObjectDebugInfo));
- // source code id
- m_debugInfo->m_sourceId = a_sourceId;
- // debug name
- if(a_info.m_debugName)
- {
- int len = (int)strlen(a_info.m_debugName) + 1;
- m_debugInfo->m_debugName = (char *) a_machine->Sys_Alloc(len);
- memcpy(m_debugInfo->m_debugName, a_info.m_debugName, len);
- }
- // symbols
- if(a_info.m_symbols)
- {
- m_debugInfo->m_symbols = (char **) a_machine->Sys_Alloc(sizeof(char *) * m_numParamsLocals);
- int i;
- for(i = 0; i < m_numParamsLocals; ++i)
- {
- int len = (int)strlen(a_info.m_symbols[i]) + 1;
- m_debugInfo->m_symbols[i] = (char *) a_machine->Sys_Alloc(len);
- memcpy(m_debugInfo->m_symbols[i], a_info.m_symbols[i], len);
- }
- }
- // line number debugging.
- if(a_info.m_lineInfo)
- {
- // alloc and copy
- m_debugInfo->m_lineInfo = (gmLineInfo *) a_machine->Sys_Alloc(sizeof(gmLineInfo) * a_info.m_lineInfoCount);
- memcpy(m_debugInfo->m_lineInfo, a_info.m_lineInfo, sizeof(gmLineInfo) * a_info.m_lineInfoCount);
- m_debugInfo->m_lineInfoCount = a_info.m_lineInfoCount;
- }
- }
-
- return true;
- }
- int gmFunctionObject::GetLine(int a_address) const
- {
- if(m_debugInfo && m_debugInfo->m_lineInfo)
- {
- int i;
- for(i = 0; i < m_debugInfo->m_lineInfoCount; ++i)
- {
- if(a_address < m_debugInfo->m_lineInfo[i].m_address)
- {
- // return entry before
- if(i > 0) --i;
- return m_debugInfo->m_lineInfo[i].m_lineNumber;
- }
- }
- return m_debugInfo->m_lineInfo[i - 1].m_lineNumber;
- }
- return 0;
- }
- const void * gmFunctionObject::GetInstructionAtLine(int a_line) const
- {
- if(m_debugInfo && m_debugInfo->m_lineInfo && m_byteCode)
- {
- // serach for the first address using this line.
- int i;
- for(i = 0; i < m_debugInfo->m_lineInfoCount; ++i)
- {
- if(m_debugInfo->m_lineInfo[i].m_lineNumber == a_line)
- {
- return (void *) ((char *) m_byteCode + m_debugInfo->m_lineInfo[i].m_address);
- }
- }
- }
- return NULL;
- }
- gmuint32 gmFunctionObject::GetSourceId() const
- {
- if(m_debugInfo)
- {
- return m_debugInfo->m_sourceId;
- }
- return 0;
- }
|