gmFunctionObject.cpp 7.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*
  2. _____ __ ___ __ ____ _ __
  3. / ___/__ ___ _ ___ / |/ /__ ___ / /_____ __ __/ __/_______(_)__ / /_
  4. / (_ / _ `/ ' \/ -_) /|_/ / _ \/ _ \/ '_/ -_) // /\ \/ __/ __/ / _ \/ __/
  5. \___/\_,_/_/_/_/\__/_/ /_/\___/_//_/_/\_\\__/\_, /___/\__/_/ /_/ .__/\__/
  6. /___/ /_/
  7. See Copyright Notice in gmMachine.h
  8. */
  9. #include "gmConfig.h"
  10. #include "gmFunctionObject.h"
  11. #include "gmMachine.h"
  12. gmFunctionObject::gmFunctionObject()
  13. {
  14. m_cFunction = NULL;
  15. m_cUserData = NULL;
  16. m_debugInfo = NULL;
  17. m_byteCode = NULL;
  18. m_byteCodeLength = 0;
  19. m_maxStackSize = 1; // return value
  20. m_numLocals = 0;
  21. m_numParams = 0;
  22. m_numParamsLocals = 0;
  23. m_numReferences = 0;
  24. m_references = NULL;
  25. }
  26. void gmFunctionObject::Destruct(gmMachine * a_machine)
  27. {
  28. if(m_references)
  29. {
  30. a_machine->Sys_Free(m_references);
  31. m_references = NULL;
  32. }
  33. if(m_byteCode)
  34. {
  35. a_machine->Sys_Free(m_byteCode);
  36. m_byteCode = NULL;
  37. }
  38. if(m_debugInfo)
  39. {
  40. if(m_debugInfo->m_debugName) { a_machine->Sys_Free(m_debugInfo->m_debugName); }
  41. if(m_debugInfo->m_lineInfo) { a_machine->Sys_Free(m_debugInfo->m_lineInfo); }
  42. if(m_debugInfo->m_symbols)
  43. {
  44. int i;
  45. for(i = 0; i < m_numParamsLocals; ++i)
  46. {
  47. a_machine->Sys_Free(m_debugInfo->m_symbols[i]);
  48. }
  49. a_machine->Sys_Free(m_debugInfo->m_symbols);
  50. }
  51. a_machine->Sys_Free(m_debugInfo);
  52. m_debugInfo = NULL;
  53. }
  54. #if GM_USE_INCGC
  55. a_machine->DestructDeleteObject(this);
  56. #endif //GM_USE_INCGC
  57. }
  58. #if GM_USE_INCGC
  59. bool gmFunctionObject::Trace(gmMachine * a_machine, gmGarbageCollector* a_gc, const int a_workLeftToGo, int& a_workDone)
  60. {
  61. int i;
  62. for(i = 0; i < m_numReferences; ++i)
  63. {
  64. gmObject * object = a_machine->GetObject(m_references[i]);
  65. a_gc->GetNextObject(object);
  66. ++a_workDone;
  67. }
  68. ++a_workDone;
  69. return true;
  70. }
  71. #else //GM_USE_INCGC
  72. void gmFunctionObject::Mark(gmMachine * a_machine, gmuint32 a_mark)
  73. {
  74. if(m_mark != GM_MARK_PERSIST) m_mark = a_mark;
  75. int i;
  76. for(i = 0; i < m_numReferences; ++i)
  77. {
  78. gmObject * object = a_machine->GetObject(m_references[i]);
  79. if(object->NeedsMark(a_mark)) object->Mark(a_machine, a_mark);
  80. }
  81. }
  82. #endif //GM_USE_INCGC
  83. bool gmFunctionObject::Init(gmMachine * a_machine, bool a_debug, gmFunctionInfo &a_info, gmuint32 a_sourceId)
  84. {
  85. // byte code
  86. if(a_info.m_byteCodeLength)
  87. {
  88. m_byteCode = (gmuint8 *) a_machine->Sys_Alloc(a_info.m_byteCodeLength);
  89. memcpy(m_byteCode, a_info.m_byteCode, a_info.m_byteCodeLength);
  90. m_byteCodeLength = a_info.m_byteCodeLength;
  91. }
  92. else
  93. {
  94. m_byteCode = NULL;
  95. m_byteCodeLength = 0;
  96. }
  97. // stack info
  98. m_maxStackSize = a_info.m_maxStackSize;
  99. m_numLocals = a_info.m_numLocals;
  100. m_numParams = a_info.m_numParams;
  101. m_numParamsLocals = a_info.m_numParams + a_info.m_numLocals;
  102. // references
  103. m_numReferences = 0;
  104. m_references = NULL;
  105. if(m_byteCode)
  106. {
  107. // find the objects this function references by iterating over the byte code and collecting them.
  108. // we could perform this step in the compilation phase if we don't want to iterate over the byte code.
  109. gmptr * references = (gmptr *) GM_NEW( char[a_info.m_byteCodeLength] );
  110. union
  111. {
  112. const gmuint8 * instruction;
  113. const gmuint32 * instruction32;
  114. };
  115. instruction = (const gmuint8 *) m_byteCode;
  116. const gmuint8 * end = instruction + m_byteCodeLength;
  117. for(;instruction < end;)
  118. {
  119. switch(*(instruction32++))
  120. {
  121. case BC_GETDOT :
  122. case BC_SETDOT :
  123. case BC_BRA :
  124. case BC_BRZ :
  125. case BC_BRNZ :
  126. case BC_BRZK :
  127. case BC_BRNZK :
  128. case BC_FOREACH :
  129. case BC_GETGLOBAL :
  130. case BC_SETGLOBAL :
  131. case BC_GETTHIS :
  132. case BC_SETTHIS : instruction += sizeof(gmptr); break;
  133. case BC_PUSHINT : instruction += sizeof(gmint); break;
  134. case BC_PUSHFP : instruction += sizeof(gmfloat); break;
  135. case BC_CALL :
  136. case BC_GETLOCAL :
  137. case BC_SETLOCAL : instruction += sizeof(gmuint32); break;
  138. case BC_PUSHSTR :
  139. case BC_PUSHFN :
  140. {
  141. // if the reference does not already exist, add it.
  142. gmptr reference = *((gmptr *) instruction);
  143. instruction += sizeof(gmptr);
  144. int i;
  145. for(i = 0; i < m_numReferences; ++i)
  146. {
  147. if(references[i] == reference) break;
  148. }
  149. if(i == m_numReferences) references[m_numReferences++] = reference;
  150. break;
  151. }
  152. default : break;
  153. }
  154. }
  155. if(m_numReferences > 0)
  156. {
  157. m_references = (gmptr *) a_machine->Sys_Alloc(sizeof(gmptr) * m_numReferences);
  158. memcpy(m_references, references, sizeof(gmptr) * m_numReferences);
  159. }
  160. delete [] (char*) references;
  161. }
  162. // debug info
  163. m_debugInfo = NULL;
  164. if(a_debug)
  165. {
  166. m_debugInfo = (gmFunctionObjectDebugInfo *) a_machine->Sys_Alloc(sizeof(gmFunctionObjectDebugInfo));
  167. memset(m_debugInfo, 0, sizeof(gmFunctionObjectDebugInfo));
  168. // source code id
  169. m_debugInfo->m_sourceId = a_sourceId;
  170. // debug name
  171. if(a_info.m_debugName)
  172. {
  173. int len = (int)strlen(a_info.m_debugName) + 1;
  174. m_debugInfo->m_debugName = (char *) a_machine->Sys_Alloc(len);
  175. memcpy(m_debugInfo->m_debugName, a_info.m_debugName, len);
  176. }
  177. // symbols
  178. if(a_info.m_symbols)
  179. {
  180. m_debugInfo->m_symbols = (char **) a_machine->Sys_Alloc(sizeof(char *) * m_numParamsLocals);
  181. int i;
  182. for(i = 0; i < m_numParamsLocals; ++i)
  183. {
  184. int len = (int)strlen(a_info.m_symbols[i]) + 1;
  185. m_debugInfo->m_symbols[i] = (char *) a_machine->Sys_Alloc(len);
  186. memcpy(m_debugInfo->m_symbols[i], a_info.m_symbols[i], len);
  187. }
  188. }
  189. // line number debugging.
  190. if(a_info.m_lineInfo)
  191. {
  192. // alloc and copy
  193. m_debugInfo->m_lineInfo = (gmLineInfo *) a_machine->Sys_Alloc(sizeof(gmLineInfo) * a_info.m_lineInfoCount);
  194. memcpy(m_debugInfo->m_lineInfo, a_info.m_lineInfo, sizeof(gmLineInfo) * a_info.m_lineInfoCount);
  195. m_debugInfo->m_lineInfoCount = a_info.m_lineInfoCount;
  196. }
  197. }
  198. return true;
  199. }
  200. int gmFunctionObject::GetLine(int a_address) const
  201. {
  202. if(m_debugInfo && m_debugInfo->m_lineInfo)
  203. {
  204. int i;
  205. for(i = 0; i < m_debugInfo->m_lineInfoCount; ++i)
  206. {
  207. if(a_address < m_debugInfo->m_lineInfo[i].m_address)
  208. {
  209. // return entry before
  210. if(i > 0) --i;
  211. return m_debugInfo->m_lineInfo[i].m_lineNumber;
  212. }
  213. }
  214. return m_debugInfo->m_lineInfo[i - 1].m_lineNumber;
  215. }
  216. return 0;
  217. }
  218. const void * gmFunctionObject::GetInstructionAtLine(int a_line) const
  219. {
  220. if(m_debugInfo && m_debugInfo->m_lineInfo && m_byteCode)
  221. {
  222. // serach for the first address using this line.
  223. int i;
  224. for(i = 0; i < m_debugInfo->m_lineInfoCount; ++i)
  225. {
  226. if(m_debugInfo->m_lineInfo[i].m_lineNumber == a_line)
  227. {
  228. return (void *) ((char *) m_byteCode + m_debugInfo->m_lineInfo[i].m_address);
  229. }
  230. }
  231. }
  232. return NULL;
  233. }
  234. gmuint32 gmFunctionObject::GetSourceId() const
  235. {
  236. if(m_debugInfo)
  237. {
  238. return m_debugInfo->m_sourceId;
  239. }
  240. return 0;
  241. }