as_scriptfunction.cpp 51 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2022 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_scriptfunction.cpp
  25. //
  26. // A container for a compiled script function
  27. //
  28. #include "as_config.h"
  29. #include "as_scriptfunction.h"
  30. #include "as_tokendef.h"
  31. #include "as_scriptengine.h"
  32. #include "as_callfunc.h"
  33. #include "as_bytecode.h"
  34. #include "as_texts.h"
  35. #include "as_scriptnode.h"
  36. #include "as_builder.h"
  37. #include "as_scriptcode.h"
  38. #include <cstdlib> // qsort
  39. BEGIN_AS_NAMESPACE
  40. #ifdef AS_MAX_PORTABILITY
  41. static void ScriptFunction_AddRef_Generic(asIScriptGeneric *gen)
  42. {
  43. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  44. self->AddRef();
  45. }
  46. static void ScriptFunction_Release_Generic(asIScriptGeneric *gen)
  47. {
  48. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  49. self->Release();
  50. }
  51. static void ScriptFunction_GetRefCount_Generic(asIScriptGeneric *gen)
  52. {
  53. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  54. *(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount();
  55. }
  56. static void ScriptFunction_SetFlag_Generic(asIScriptGeneric *gen)
  57. {
  58. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  59. self->SetFlag();
  60. }
  61. static void ScriptFunction_GetFlag_Generic(asIScriptGeneric *gen)
  62. {
  63. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  64. *(bool*)gen->GetAddressOfReturnLocation() = self->GetFlag();
  65. }
  66. static void ScriptFunction_EnumReferences_Generic(asIScriptGeneric *gen)
  67. {
  68. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  69. asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
  70. self->EnumReferences(engine);
  71. }
  72. static void ScriptFunction_ReleaseAllHandles_Generic(asIScriptGeneric *gen)
  73. {
  74. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  75. asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
  76. self->ReleaseAllHandles(engine);
  77. }
  78. static void ScriptFunction_CreateDelegate_Generic(asIScriptGeneric *gen)
  79. {
  80. asCScriptFunction *func = (asCScriptFunction*)gen->GetArgAddress(0);
  81. void *obj = gen->GetArgAddress(1);
  82. gen->SetReturnAddress(CreateDelegate(func, obj));
  83. }
  84. // TODO: operator==
  85. /*static void ScriptFunction_opEquals_Generic(asIScriptGeneric *gen)
  86. {
  87. asCScriptFunction *funcSelf = (asCScriptFunction*)gen->GetObject();
  88. asCScriptFunction *funcOther = (asCScriptFunction*)gen->GetArgAddress(0);
  89. *(bool*)gen->GetAddressOfReturnLocation() = *funcSelf == *funcOther;
  90. }
  91. */
  92. #endif
  93. void RegisterScriptFunction(asCScriptEngine *engine)
  94. {
  95. // Register the gc behaviours for the script functions
  96. int r = 0;
  97. UNUSED_VAR(r); // It is only used in debug mode
  98. engine->functionBehaviours.engine = engine;
  99. engine->functionBehaviours.flags = asOBJ_REF | asOBJ_GC;
  100. engine->functionBehaviours.name = "$func";
  101. #ifndef AS_MAX_PORTABILITY
  102. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCScriptFunction,AddRef), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  103. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCScriptFunction,Release), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  104. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCScriptFunction,GetRefCount), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  105. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCScriptFunction,SetFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  106. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCScriptFunction,GetFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  107. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCScriptFunction,EnumReferences), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  108. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCScriptFunction,ReleaseAllHandles), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  109. // TODO: Need some way to allow the arg type to adapt when the funcdefs are instantiated
  110. // r = engine->RegisterMethodToObjectType(&engine->functionBehaviours, "bool opEquals(const int &in)", asMETHOD(asCScriptFunction,operator==), asCALL_THISCALL); asASSERT( r >= 0 );
  111. #else
  112. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptFunction_AddRef_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  113. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptFunction_Release_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  114. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptFunction_GetRefCount_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  115. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptFunction_SetFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  116. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptFunction_GetFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  117. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptFunction_EnumReferences_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  118. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptFunction_ReleaseAllHandles_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  119. // r = engine->RegisterMethodToObjectType(&engine->functionBehaviours, "bool opEquals(const int &in)", asFUNCTION(ScriptFunction_opEquals_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  120. #endif
  121. // Register the builtin function for creating delegates
  122. // This function returns a handle to the delegate, but since the type is not known at this time it is
  123. // registered to return a void then the return type is changed manually to the builtin function type
  124. // The name of the function is an invalid identifier so it cannot be invoked accidentally from the script
  125. #ifndef AS_MAX_PORTABILITY
  126. r = engine->RegisterGlobalFunction("void f(int &in, int &in)", asFUNCTION(CreateDelegate), asCALL_CDECL); asASSERT( r >= 0 );
  127. #else
  128. r = engine->RegisterGlobalFunction("void f(int &in, int &in)", asFUNCTION(ScriptFunction_CreateDelegate_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  129. #endif
  130. // Rename the function so that it cannot be called manually by the script
  131. int idx = engine->registeredGlobalFuncs.GetIndex(engine->scriptFunctions[r]);
  132. engine->registeredGlobalFuncs.Erase(idx);
  133. engine->scriptFunctions[r]->name = DELEGATE_FACTORY;
  134. engine->registeredGlobalFuncs.Put(engine->scriptFunctions[r]);
  135. // Change the return type so the VM will know the function really returns a handle
  136. engine->scriptFunctions[r]->returnType = asCDataType::CreateType(&engine->functionBehaviours, false);
  137. engine->scriptFunctions[r]->returnType.MakeHandle(true);
  138. }
  139. asCScriptFunction *CreateDelegate(asCScriptFunction *func, void *obj)
  140. {
  141. if( func == 0 || obj == 0 )
  142. {
  143. // TODO: delegate: Should set script exception
  144. return 0;
  145. }
  146. // Create an instance of a asCScriptFunction with the type asFUNC_DELEGATE
  147. // The delegate shouldn't have a function id and is not added to the engine->scriptFunctions
  148. asCScriptFunction *delegate = asNEW(asCScriptFunction)(static_cast<asCScriptEngine*>(func->GetEngine()), 0, asFUNC_DELEGATE);
  149. if( delegate )
  150. delegate->MakeDelegate(func, obj);
  151. return delegate;
  152. }
  153. // internal
  154. void asCScriptFunction::MakeDelegate(asCScriptFunction *func, void *obj)
  155. {
  156. // Increase the reference of the function and object
  157. func->AddRef();
  158. funcForDelegate = func;
  159. func->GetEngine()->AddRefScriptObject(obj, func->GetObjectType());
  160. objForDelegate = obj;
  161. // The return type and parameters are copied from the delegated method to this object
  162. // TODO: optimize: Do we really need to copy? Whenever requested the delegate can simply return the delegated methods' info directly
  163. parameterTypes = func->parameterTypes;
  164. returnType = func->returnType;
  165. inOutFlags = func->inOutFlags;
  166. // The delegate doesn't own the parameters as it will only forward them to the real method
  167. // so the exception handler must not clean up the parameters for the delegate
  168. dontCleanUpOnException = true;
  169. }
  170. // interface
  171. void *asCScriptFunction::GetAuxiliary() const
  172. {
  173. if (sysFuncIntf)
  174. return sysFuncIntf->auxiliary;
  175. return 0;
  176. }
  177. // interface
  178. void *asCScriptFunction::GetDelegateObject() const
  179. {
  180. return objForDelegate;
  181. }
  182. // interface
  183. asITypeInfo *asCScriptFunction::GetDelegateObjectType() const
  184. {
  185. if( objForDelegate == 0 || funcForDelegate == 0 )
  186. return 0;
  187. return funcForDelegate->objectType;
  188. }
  189. // interface
  190. asIScriptFunction *asCScriptFunction::GetDelegateFunction() const
  191. {
  192. return funcForDelegate;
  193. }
  194. // TODO: operator==
  195. /*
  196. // internal
  197. bool asCScriptFunction::operator==(const asCScriptFunction &other) const
  198. {
  199. if( this == &other ) return true;
  200. if( this->funcType == asFUNC_DELEGATE && other.funcType == asFUNC_DELEGATE )
  201. {
  202. if( this->objForDelegate == other.objForDelegate &&
  203. this->funcForDelegate == other.funcForDelegate )
  204. return true;
  205. }
  206. return false;
  207. }
  208. */
  209. // internal
  210. int asCScriptFunction::RegisterListPattern(const char *decl, asCScriptNode *listNodes)
  211. {
  212. if( listNodes == 0 )
  213. return asINVALID_ARG;
  214. // Build the representation of the list pattern from the script nodes
  215. asSListPatternNode *node;
  216. listPattern = asNEW(asSListPatternNode)(asLPT_START);
  217. node = listPattern;
  218. // Recursively parse the child
  219. int r = ParseListPattern(node, decl, listNodes);
  220. node->next = asNEW(asSListPatternNode)(asLPT_END);
  221. return r;
  222. }
  223. // internal
  224. int asCScriptFunction::ParseListPattern(asSListPatternNode *&target, const char *decl, asCScriptNode *listNodes)
  225. {
  226. asSListPatternNode *node = target;
  227. listNodes = listNodes->firstChild;
  228. while( listNodes )
  229. {
  230. if( listNodes->nodeType == snIdentifier )
  231. {
  232. asCString token(&decl[listNodes->tokenPos], listNodes->tokenLength);
  233. if( token == "repeat" )
  234. {
  235. node->next = asNEW(asSListPatternNode)(asLPT_REPEAT);
  236. node = node->next;
  237. }
  238. else if( token == "repeat_same" )
  239. {
  240. // TODO: list: Should make sure this is a sub-list
  241. node->next = asNEW(asSListPatternNode)(asLPT_REPEAT_SAME);
  242. node = node->next;
  243. }
  244. else
  245. {
  246. // Shouldn't happen as the parser already reported the error
  247. asASSERT(false);
  248. }
  249. }
  250. else if( listNodes->nodeType == snDataType )
  251. {
  252. asCDataType dt;
  253. asCBuilder builder(engine, 0);
  254. asCScriptCode code;
  255. code.SetCode("", decl, 0, false);
  256. // For list factory we get the object type from the return type, for list constructor we get it from the object type directly
  257. dt = builder.CreateDataTypeFromNode(listNodes, &code, engine->defaultNamespace, false, objectType ? objectType : CastToObjectType(returnType.GetTypeInfo()));
  258. node->next = asNEW(asSListPatternDataTypeNode)(dt);
  259. node = node->next;
  260. }
  261. else if( listNodes->nodeType == snListPattern )
  262. {
  263. node->next = asNEW(asSListPatternNode)(asLPT_START);
  264. node = node->next;
  265. // Recursively parse the child
  266. int r = ParseListPattern(node, decl, listNodes);
  267. if( r < 0 )
  268. return r;
  269. node->next = asNEW(asSListPatternNode)(asLPT_END);
  270. node = node->next;
  271. }
  272. else
  273. {
  274. // Unexpected token in the list, the parser shouldn't have allowed
  275. asASSERT( false );
  276. return -1;
  277. }
  278. listNodes = listNodes->next;
  279. }
  280. target = node;
  281. return 0;
  282. }
  283. // internal
  284. asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, asEFuncType _funcType)
  285. {
  286. funcType = _funcType;
  287. if( funcType == asFUNC_DELEGATE )
  288. {
  289. // Delegates behave like object instances, rather than script code
  290. externalRefCount.set(1);
  291. internalRefCount.set(0);
  292. }
  293. else
  294. {
  295. internalRefCount.set(1);
  296. externalRefCount.set(0);
  297. }
  298. this->engine = engine;
  299. this->scriptData = 0;
  300. module = mod;
  301. objectType = 0;
  302. name = "";
  303. sysFuncIntf = 0;
  304. signatureId = 0;
  305. dontCleanUpOnException = false;
  306. vfTableIdx = -1;
  307. gcFlag = false;
  308. userData = 0;
  309. id = 0;
  310. accessMask = 0xFFFFFFFF;
  311. nameSpace = engine->nameSpaces[0];
  312. objForDelegate = 0;
  313. funcForDelegate = 0;
  314. listPattern = 0;
  315. funcdefType = 0;
  316. if( funcType == asFUNC_SCRIPT )
  317. AllocateScriptFunctionData();
  318. // Notify the GC of delegates
  319. if( funcType == asFUNC_DELEGATE )
  320. engine->gc.AddScriptObjectToGC(this, &engine->functionBehaviours);
  321. }
  322. void asCScriptFunction::AllocateScriptFunctionData()
  323. {
  324. if( scriptData ) return;
  325. scriptData = asNEW(ScriptFunctionData);
  326. scriptData->stackNeeded = 0;
  327. scriptData->variableSpace = 0;
  328. scriptData->scriptSectionIdx = -1;
  329. scriptData->declaredAt = 0;
  330. scriptData->jitFunction = 0;
  331. }
  332. void asCScriptFunction::DeallocateScriptFunctionData()
  333. {
  334. if( !scriptData ) return;
  335. for( asUINT n = 0; n < scriptData->variables.GetLength(); n++ )
  336. asDELETE(scriptData->variables[n],asSScriptVariable);
  337. scriptData->variables.SetLength(0);
  338. asDELETE(scriptData, ScriptFunctionData);
  339. scriptData = 0;
  340. }
  341. // internal
  342. asCScriptFunction::~asCScriptFunction()
  343. {
  344. // Dummy functions that are allocated on the stack are not reference counted
  345. asASSERT( funcType == asFUNC_DUMMY ||
  346. (externalRefCount.get() == 0 && internalRefCount.get() == 0) );
  347. // Remove the script function from the engine's scriptFunctions array here
  348. // Don't remove it before, because there may still be functions referring to it
  349. // by index until now. If it was removed in DestroyInternal, those would not
  350. // be able to release the refcount, thus causing memory leak.
  351. if( engine && id != 0 && funcType != asFUNC_DUMMY )
  352. engine->RemoveScriptFunction(this);
  353. // If the engine pointer is 0, then DestroyInternal has already been called and there is nothing more to do
  354. if( engine == 0 ) return;
  355. DestroyInternal();
  356. // Finally set the engine pointer to 0 because it must not be accessed again
  357. engine = 0;
  358. }
  359. // internal
  360. void asCScriptFunction::DestroyHalfCreated()
  361. {
  362. asASSERT( externalRefCount.get() == 0 && internalRefCount.get() == 1 );
  363. // Set the funcType to dummy so the destructor won't complain
  364. funcType = asFUNC_DUMMY;
  365. // If the bytecode exist remove it before destroying, otherwise it
  366. // will fail when the destructor releases the references as the bytecode
  367. // is not fully constructed.
  368. if( scriptData )
  369. scriptData->byteCode.SetLength(0);
  370. asDELETE(this, asCScriptFunction);
  371. }
  372. // internal
  373. void asCScriptFunction::DestroyInternal()
  374. {
  375. // Clean up user data
  376. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  377. {
  378. if( userData[n+1] )
  379. {
  380. for( asUINT c = 0; c < engine->cleanFunctionFuncs.GetLength(); c++ )
  381. if( engine->cleanFunctionFuncs[c].type == userData[n] )
  382. engine->cleanFunctionFuncs[c].cleanFunc(this);
  383. }
  384. }
  385. userData.SetLength(0);
  386. // Release all references the function holds to other objects
  387. ReleaseReferences();
  388. parameterTypes.SetLength(0);
  389. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  390. for( asUINT p = 0; p < defaultArgs.GetLength(); p++ )
  391. if( defaultArgs[p] )
  392. asDELETE(defaultArgs[p], asCString);
  393. defaultArgs.SetLength(0);
  394. if( sysFuncIntf )
  395. asDELETE(sysFuncIntf,asSSystemFunctionInterface);
  396. sysFuncIntf = 0;
  397. if( objectType )
  398. {
  399. objectType->ReleaseInternal();
  400. objectType = 0;
  401. }
  402. DeallocateScriptFunctionData();
  403. // Deallocate list pattern data
  404. while( listPattern )
  405. {
  406. asSListPatternNode *n = listPattern->next;
  407. asDELETE(listPattern, asSListPatternNode);
  408. listPattern = n;
  409. }
  410. }
  411. // interface
  412. int asCScriptFunction::GetId() const
  413. {
  414. return id;
  415. }
  416. // interface
  417. int asCScriptFunction::AddRef() const
  418. {
  419. gcFlag = false;
  420. return externalRefCount.atomicInc();
  421. }
  422. // interface
  423. int asCScriptFunction::Release() const
  424. {
  425. gcFlag = false;
  426. int r = externalRefCount.atomicDec();
  427. if( r == 0 &&
  428. funcType != asFUNC_DUMMY ) // Dummy functions are allocated on the stack and cannot be deleted
  429. {
  430. // There are no more external references, if there are also no
  431. // internal references then it is time to delete the function
  432. if( internalRefCount.get() == 0 )
  433. {
  434. // If there are no internal references, then no module is owning the function
  435. // For example if the function was dynamically compiled without adding it to the scope of the module
  436. asASSERT( module == 0 );
  437. asDELETE(const_cast<asCScriptFunction*>(this),asCScriptFunction);
  438. }
  439. }
  440. return r;
  441. }
  442. // internal
  443. int asCScriptFunction::AddRefInternal()
  444. {
  445. return internalRefCount.atomicInc();
  446. }
  447. // internal
  448. int asCScriptFunction::ReleaseInternal()
  449. {
  450. int r = internalRefCount.atomicDec();
  451. if( r == 0 &&
  452. funcType != asFUNC_DUMMY )
  453. {
  454. // There are no more internal references, if there are also no
  455. // external references then it is time to delete the function
  456. if( externalRefCount.get() == 0 )
  457. {
  458. asDELETE(const_cast<asCScriptFunction*>(this),asCScriptFunction);
  459. }
  460. }
  461. return r;
  462. }
  463. // interface
  464. int asCScriptFunction::GetTypeId() const
  465. {
  466. // This const cast is ok, the object won't be modified
  467. asCDataType dt = asCDataType::CreateType(engine->FindMatchingFuncdef(const_cast<asCScriptFunction*>(this), 0), false);
  468. return engine->GetTypeIdFromDataType(dt);
  469. }
  470. // interface
  471. bool asCScriptFunction::IsCompatibleWithTypeId(int typeId) const
  472. {
  473. asCDataType dt = engine->GetDataTypeFromTypeId(typeId);
  474. // Make sure the type is a function
  475. if (!dt.IsFuncdef())
  476. return false;
  477. asCScriptFunction *func = CastToFuncdefType(dt.GetTypeInfo())->funcdef;
  478. if( !IsSignatureExceptNameEqual(func) )
  479. return false;
  480. // If this is a class method, then only return true if the object type is the same
  481. if( objectType != func->objectType )
  482. return false;
  483. return true;
  484. }
  485. // interface
  486. const char *asCScriptFunction::GetModuleName() const
  487. {
  488. if( module )
  489. return module->GetName();
  490. return 0;
  491. }
  492. // interface
  493. asIScriptModule *asCScriptFunction::GetModule() const
  494. {
  495. return module;
  496. }
  497. // interface
  498. asITypeInfo *asCScriptFunction::GetObjectType() const
  499. {
  500. return objectType;
  501. }
  502. // interface
  503. const char *asCScriptFunction::GetObjectName() const
  504. {
  505. if( objectType )
  506. return objectType->GetName();
  507. return 0;
  508. }
  509. // interface
  510. const char *asCScriptFunction::GetName() const
  511. {
  512. return name.AddressOf();
  513. }
  514. // interface
  515. const char *asCScriptFunction::GetNamespace() const
  516. {
  517. if (nameSpace)
  518. return nameSpace->name.AddressOf();
  519. return 0;
  520. }
  521. // interface
  522. bool asCScriptFunction::IsReadOnly() const
  523. {
  524. return traits.GetTrait(asTRAIT_CONST);
  525. }
  526. // interface
  527. bool asCScriptFunction::IsPrivate() const
  528. {
  529. return traits.GetTrait(asTRAIT_PRIVATE);
  530. }
  531. // interface
  532. bool asCScriptFunction::IsProtected() const
  533. {
  534. return traits.GetTrait(asTRAIT_PROTECTED);
  535. }
  536. // internal
  537. int asCScriptFunction::GetSpaceNeededForArguments()
  538. {
  539. // We need to check the size for each type
  540. int s = 0;
  541. for( asUINT n = 0; n < parameterTypes.GetLength(); n++ )
  542. s += parameterTypes[n].GetSizeOnStackDWords();
  543. return s;
  544. }
  545. // internal
  546. int asCScriptFunction::GetSpaceNeededForReturnValue()
  547. {
  548. return returnType.GetSizeOnStackDWords();
  549. }
  550. // internal
  551. bool asCScriptFunction::DoesReturnOnStack() const
  552. {
  553. if( returnType.GetTypeInfo() &&
  554. (returnType.GetTypeInfo()->flags & asOBJ_VALUE) &&
  555. !returnType.IsReference() )
  556. return true;
  557. return false;
  558. }
  559. // internal
  560. asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName, bool includeNamespace, bool includeParamNames) const
  561. {
  562. asCString str;
  563. // TODO: default arg: Make the declaration with the default args an option
  564. // Don't add the return type for constructors and destructors
  565. if( !(returnType.GetTokenType() == ttVoid &&
  566. objectType &&
  567. (name == objectType->name || (name.GetLength() > 0 && name[0] == '~') ||
  568. name == "$beh0" || name == "$beh2")) )
  569. {
  570. str = returnType.Format(nameSpace, includeNamespace);
  571. str += " ";
  572. }
  573. if( objectType && includeObjectName )
  574. {
  575. if( includeNamespace && objectType->nameSpace->name != "" )
  576. str += objectType->nameSpace->name + "::";
  577. if( objectType->name != "" )
  578. str += objectType->name + "::";
  579. else
  580. str += "_unnamed_type_::";
  581. }
  582. else if (funcdefType && funcdefType->parentClass && includeObjectName)
  583. {
  584. if (includeNamespace && funcdefType->parentClass->nameSpace->name != "")
  585. str += funcdefType->parentClass->nameSpace->name + "::";
  586. if (funcdefType->parentClass->name != "")
  587. str += funcdefType->parentClass->name + "::";
  588. else
  589. str += "_unnamed_type_::";
  590. }
  591. else if( includeNamespace && nameSpace->name != "" && !objectType )
  592. {
  593. str += nameSpace->name + "::";
  594. }
  595. if( name == "" )
  596. str += "_unnamed_function_(";
  597. else if( name.SubString(0,4) == "$beh" && name.GetLength() == 5 )
  598. {
  599. if( name[4] == '0' + asBEHAVE_CONSTRUCT )
  600. str += objectType->name + "(";
  601. else if( name[4] == '0' + asBEHAVE_FACTORY )
  602. str += returnType.GetTypeInfo()->name + "(";
  603. else if( name[4] == '0' + asBEHAVE_DESTRUCT )
  604. str += "~" + objectType->name + "(";
  605. else
  606. str += name + "(";
  607. }
  608. else
  609. str += name + "(";
  610. if( parameterTypes.GetLength() > 0 )
  611. {
  612. asUINT n;
  613. for( n = 0; n < parameterTypes.GetLength() - 1; n++ )
  614. {
  615. str += parameterTypes[n].Format(nameSpace, includeNamespace);
  616. if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
  617. {
  618. if( inOutFlags[n] == asTM_INREF ) str += "in";
  619. else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
  620. else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
  621. }
  622. if( includeParamNames && n < parameterNames.GetLength() && parameterNames[n].GetLength() != 0 )
  623. {
  624. str += " ";
  625. str += parameterNames[n];
  626. }
  627. if( defaultArgs.GetLength() > n && defaultArgs[n] )
  628. {
  629. asCString tmp;
  630. tmp.Format(" = %s", defaultArgs[n]->AddressOf());
  631. str += tmp;
  632. }
  633. str += ", ";
  634. }
  635. // Add the last parameter
  636. str += parameterTypes[n].Format(nameSpace, includeNamespace);
  637. if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
  638. {
  639. if( inOutFlags[n] == asTM_INREF ) str += "in";
  640. else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
  641. else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
  642. }
  643. if( includeParamNames && n < parameterNames.GetLength() && parameterNames[n].GetLength() != 0 )
  644. {
  645. str += " ";
  646. str += parameterNames[n];
  647. }
  648. if( defaultArgs.GetLength() > n && defaultArgs[n] )
  649. {
  650. asCString tmp;
  651. tmp.Format(" = %s", defaultArgs[n]->AddressOf());
  652. str += tmp;
  653. }
  654. }
  655. str += ")";
  656. if( IsReadOnly() )
  657. str += " const";
  658. // Add the declaration of the list pattern
  659. if( listPattern )
  660. {
  661. asSListPatternNode *n = listPattern;
  662. bool first = true;
  663. while( n )
  664. {
  665. if( n->type == asLPT_START )
  666. {
  667. str += " {";
  668. first = true;
  669. }
  670. else if( n->type == asLPT_END )
  671. {
  672. str += " }";
  673. first = false;
  674. }
  675. else if( n->type == asLPT_REPEAT )
  676. str += " repeat";
  677. else if( n->type == asLPT_REPEAT_SAME )
  678. str += " repeat_same";
  679. else if( n->type == asLPT_TYPE )
  680. {
  681. if( first )
  682. {
  683. str += " ";
  684. first = false;
  685. }
  686. else
  687. str += ", ";
  688. str += reinterpret_cast<asSListPatternDataTypeNode*>(n)->dataType.Format(nameSpace, includeNamespace);
  689. }
  690. n = n->next;
  691. }
  692. }
  693. return str;
  694. }
  695. // interface
  696. int asCScriptFunction::FindNextLineWithCode(int line) const
  697. {
  698. if( scriptData == 0 ) return -1;
  699. if( scriptData->lineNumbers.GetLength() == 0 ) return -1;
  700. // The line numbers for constructors are not in order due to the way
  701. // class members can be initialized directly in the declaration
  702. if( objectType && objectType->name == name )
  703. {
  704. // Sort all line numbers before looking for the next
  705. asCArray<int> lineNbrs;
  706. for( asUINT n = 1; n < scriptData->lineNumbers.GetLength(); n += 2 )
  707. lineNbrs.PushLast(scriptData->lineNumbers[n]&0xFFFFF);
  708. struct C
  709. {
  710. static int cmp(const void *a, const void *b) { return *(int*)a - *(int*)b; }
  711. };
  712. std::qsort(&lineNbrs[0], lineNbrs.GetLength(), sizeof(int), C::cmp);
  713. if( line < lineNbrs[0] && line < (scriptData->declaredAt&0xFFFFF)) return -1;
  714. if( line > lineNbrs[lineNbrs.GetLength()-1] ) return -1;
  715. // Find the line with code on or right after the input line
  716. // TODO: optimize: Do binary search
  717. for( asUINT n = 0; n < lineNbrs.GetLength(); n++ )
  718. if( line <= lineNbrs[n] )
  719. return lineNbrs[n];
  720. }
  721. else
  722. {
  723. // Check if given line is outside function
  724. if( line < (scriptData->declaredAt&0xFFFFF) ) return -1;
  725. if( line > (scriptData->lineNumbers[scriptData->lineNumbers.GetLength()-1]&0xFFFFF) ) return -1;
  726. // Find the line with code on or right after the input line
  727. // TODO: optimize: Do binary search instead
  728. for( asUINT n = 1; n < scriptData->lineNumbers.GetLength(); n += 2 )
  729. {
  730. if( line <= (scriptData->lineNumbers[n]&0xFFFFF) )
  731. return (scriptData->lineNumbers[n]&0xFFFFF);
  732. }
  733. }
  734. return -1;
  735. }
  736. // internal
  737. int asCScriptFunction::GetLineNumber(int programPosition, int *sectionIdx)
  738. {
  739. asASSERT( scriptData );
  740. if( sectionIdx ) *sectionIdx = scriptData->scriptSectionIdx;
  741. if( scriptData->lineNumbers.GetLength() == 0 ) return 0;
  742. if( sectionIdx )
  743. {
  744. // Find the correct section index if the function is compiled from multiple sections
  745. // This array will be empty most of the time so we don't need a sofisticated algorithm to search it
  746. for( asUINT n = 0; n < scriptData->sectionIdxs.GetLength(); n += 2 )
  747. {
  748. if( scriptData->sectionIdxs[n] <= programPosition )
  749. *sectionIdx = scriptData->sectionIdxs[n+1];
  750. }
  751. }
  752. // Do a binary search in the buffer
  753. int max = (int)scriptData->lineNumbers.GetLength()/2 - 1;
  754. int min = 0;
  755. int i = max/2;
  756. for(;;)
  757. {
  758. if( scriptData->lineNumbers[i*2] < programPosition )
  759. {
  760. // Have we found the largest number < programPosition?
  761. if( max == i ) return scriptData->lineNumbers[i*2+1];
  762. if( scriptData->lineNumbers[i*2+2] > programPosition ) return scriptData->lineNumbers[i*2+1];
  763. min = i + 1;
  764. i = (max + min)/2;
  765. }
  766. else if( scriptData->lineNumbers[i*2] > programPosition )
  767. {
  768. // Have we found the smallest number > programPosition?
  769. if( min == i ) return scriptData->lineNumbers[i*2+1];
  770. max = i - 1;
  771. i = (max + min)/2;
  772. }
  773. else
  774. {
  775. // We found the exact position
  776. return scriptData->lineNumbers[i*2+1];
  777. }
  778. }
  779. }
  780. // interface
  781. asEFuncType asCScriptFunction::GetFuncType() const
  782. {
  783. return funcType;
  784. }
  785. // interface
  786. asUINT asCScriptFunction::GetVarCount() const
  787. {
  788. if( scriptData )
  789. return asUINT(scriptData->variables.GetLength());
  790. return 0;
  791. }
  792. // interface
  793. int asCScriptFunction::GetVar(asUINT index, const char **out_name, int *out_typeId) const
  794. {
  795. if( scriptData == 0 )
  796. return asNOT_SUPPORTED;
  797. if( index >= scriptData->variables.GetLength() )
  798. return asINVALID_ARG;
  799. if( out_name )
  800. *out_name = scriptData->variables[index]->name.AddressOf();
  801. if( out_typeId )
  802. *out_typeId = engine->GetTypeIdFromDataType(scriptData->variables[index]->type);
  803. return asSUCCESS;
  804. }
  805. // interface
  806. const char *asCScriptFunction::GetVarDecl(asUINT index, bool includeNamespace) const
  807. {
  808. if( scriptData == 0 || index >= scriptData->variables.GetLength() )
  809. return 0;
  810. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  811. *tempString = scriptData->variables[index]->type.Format(nameSpace, includeNamespace);
  812. *tempString += " " + scriptData->variables[index]->name;
  813. return tempString->AddressOf();
  814. }
  815. // internal
  816. void asCScriptFunction::AddVariable(const asCString &in_name, asCDataType &in_type, int in_stackOffset, bool in_onHeap)
  817. {
  818. asASSERT( scriptData );
  819. asSScriptVariable *var = asNEW(asSScriptVariable);
  820. if( var == 0 )
  821. {
  822. // Out of memory
  823. return;
  824. }
  825. var->name = in_name;
  826. var->type = in_type;
  827. var->stackOffset = in_stackOffset;
  828. var->onHeap = in_onHeap;
  829. var->declaredAtProgramPos = 0;
  830. scriptData->variables.PushLast(var);
  831. }
  832. // internal
  833. asCTypeInfo *asCScriptFunction::GetTypeInfoOfLocalVar(short varOffset)
  834. {
  835. asASSERT( scriptData );
  836. for( asUINT n = 0; n < scriptData->variables.GetLength(); n++ )
  837. {
  838. if (scriptData->variables[n]->stackOffset == varOffset)
  839. return scriptData->variables[n]->type.GetTypeInfo();
  840. }
  841. return 0;
  842. }
  843. // internal
  844. void asCScriptFunction::ComputeSignatureId()
  845. {
  846. // This function will compute the signatureId based on the
  847. // function name, return type, and parameter types. The object
  848. // type for methods is not used, so that class methods and
  849. // interface methods match each other.
  850. for( asUINT n = 0; n < engine->signatureIds.GetLength(); n++ )
  851. {
  852. if( !IsSignatureEqual(engine->signatureIds[n]) ) continue;
  853. // We don't need to increment the reference counter here, because
  854. // asCScriptEngine::FreeScriptFunctionId will maintain the signature
  855. // id as the function is freed.
  856. signatureId = engine->signatureIds[n]->signatureId;
  857. return;
  858. }
  859. signatureId = id;
  860. engine->signatureIds.PushLast(this);
  861. }
  862. // internal
  863. bool asCScriptFunction::IsSignatureEqual(const asCScriptFunction *func) const
  864. {
  865. if( name != func->name || !IsSignatureExceptNameEqual(func) ) return false;
  866. return true;
  867. }
  868. // internal
  869. bool asCScriptFunction::IsSignatureExceptNameEqual(const asCScriptFunction *func) const
  870. {
  871. return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, func->objectType, func->IsReadOnly());
  872. }
  873. // internal
  874. bool asCScriptFunction::IsSignatureExceptNameEqual(const asCDataType &retType, const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &paramInOut, const asCObjectType *objType, bool readOnly) const
  875. {
  876. if( this->returnType != retType ) return false;
  877. return IsSignatureExceptNameAndReturnTypeEqual(paramTypes, paramInOut, objType, readOnly);
  878. }
  879. // internal
  880. bool asCScriptFunction::IsSignatureExceptNameAndObjectTypeEqual(const asCScriptFunction *func) const
  881. {
  882. return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, objectType, IsReadOnly());
  883. }
  884. // internal
  885. bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCScriptFunction *func) const
  886. {
  887. return IsSignatureExceptNameAndReturnTypeEqual(func->parameterTypes, func->inOutFlags, func->objectType, func->IsReadOnly());
  888. }
  889. // internal
  890. bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &paramInOut, const asCObjectType *objType, bool readOnly) const
  891. {
  892. if( this->IsReadOnly() != readOnly ) return false;
  893. if( (this->objectType != 0) != (objType != 0) ) return false;
  894. if( this->inOutFlags != paramInOut ) return false;
  895. if( this->parameterTypes != paramTypes ) return false;
  896. return true;
  897. }
  898. // internal
  899. void asCScriptFunction::AddReferences()
  900. {
  901. // This array will be used to make sure we only add the reference to the same resource once
  902. // This is especially important for global variables, as it expects the initialization function
  903. // to hold only one reference to the variable. However, if the variable is initialized through
  904. // the default constructor followed by the assignment operator we will have two references to
  905. // the variable in the function.
  906. asCArray<void*> ptrs;
  907. // Only count references if there is any bytecode
  908. if( scriptData && scriptData->byteCode.GetLength() )
  909. {
  910. if( returnType.GetTypeInfo() )
  911. {
  912. returnType.GetTypeInfo()->AddRefInternal();
  913. asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(returnType.GetTypeInfo());
  914. if( group != 0 ) group->AddRef();
  915. }
  916. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  917. if( parameterTypes[p].GetTypeInfo() )
  918. {
  919. parameterTypes[p].GetTypeInfo()->AddRefInternal();
  920. asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(parameterTypes[p].GetTypeInfo());
  921. if( group != 0 ) group->AddRef();
  922. }
  923. for (asUINT v = 0; v < scriptData->variables.GetLength(); v++)
  924. {
  925. asCTypeInfo* ti = reinterpret_cast<asCTypeInfo*>(scriptData->variables[v]->type.GetTypeInfo());
  926. if (ti) // The null handle is also stored, but it doesn't have an object type
  927. {
  928. ti->AddRefInternal();
  929. asCConfigGroup* group = engine->FindConfigGroupForTypeInfo(ti);
  930. if (group != 0) group->AddRef();
  931. }
  932. }
  933. // Go through the byte code and add references to all resources used by the function
  934. asCArray<asDWORD> &bc = scriptData->byteCode;
  935. for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] )
  936. {
  937. switch( *(asBYTE*)&bc[n] )
  938. {
  939. // Object types
  940. case asBC_OBJTYPE:
  941. case asBC_FREE:
  942. case asBC_REFCPY:
  943. case asBC_RefCpyV:
  944. {
  945. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  946. asASSERT( objType );
  947. if( objType )
  948. objType->AddRefInternal();
  949. }
  950. break;
  951. // Object type and function
  952. case asBC_ALLOC:
  953. {
  954. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  955. asASSERT( objType );
  956. if( objType )
  957. objType->AddRefInternal();
  958. int funcId = asBC_INTARG(&bc[n]+AS_PTR_SIZE);
  959. if( funcId )
  960. engine->scriptFunctions[funcId]->AddRefInternal();
  961. }
  962. break;
  963. // Global variables
  964. case asBC_PGA:
  965. case asBC_PshGPtr:
  966. case asBC_LDG:
  967. case asBC_PshG4:
  968. case asBC_LdGRdR4:
  969. case asBC_CpyGtoV4:
  970. case asBC_CpyVtoG4:
  971. case asBC_SetG4:
  972. // Need to increase the reference for each global variable
  973. {
  974. void *gvarPtr = (void*)asBC_PTRARG(&bc[n]);
  975. if( !gvarPtr ) break;
  976. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  977. if (!prop)
  978. {
  979. // The pointer is a string constant. In order to make sure the correct resource
  980. // management is maintained we request a new string constant here, so the compiler
  981. // or bytecode loader can release its copy afterwards.
  982. asCString str;
  983. asUINT length;
  984. int r = engine->stringFactory->GetRawStringData(gvarPtr, 0, &length);
  985. if (r >= 0)
  986. {
  987. str.SetLength(length);
  988. engine->stringFactory->GetRawStringData(gvarPtr, str.AddressOf(), &length);
  989. // Get a new pointer (depending on the string factory implementation it may actually be the same)
  990. gvarPtr = const_cast<void*>(engine->stringFactory->GetStringConstant(str.AddressOf(), length));
  991. asBC_PTRARG(&bc[n]) = (asPWORD)gvarPtr;
  992. }
  993. // If we get an error from the string factory there is not
  994. // anything we can do about it, except report a message.
  995. // TODO: NEWSTRING: Write a message and then exit gracefully
  996. asASSERT(r >= 0);
  997. break;
  998. }
  999. // Only addref the properties once
  1000. if( !ptrs.Exists(gvarPtr) )
  1001. {
  1002. prop->AddRef();
  1003. ptrs.PushLast(gvarPtr);
  1004. }
  1005. asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id);
  1006. if( group != 0 ) group->AddRef();
  1007. }
  1008. break;
  1009. // System functions
  1010. case asBC_CALLSYS:
  1011. {
  1012. int funcId = asBC_INTARG(&bc[n]);
  1013. asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
  1014. if( group != 0 ) group->AddRef();
  1015. asASSERT( funcId > 0 );
  1016. if( funcId > 0 )
  1017. engine->scriptFunctions[funcId]->AddRefInternal();
  1018. }
  1019. break;
  1020. // Functions
  1021. case asBC_CALL:
  1022. case asBC_CALLINTF:
  1023. {
  1024. int funcId = asBC_INTARG(&bc[n]);
  1025. asASSERT( funcId > 0 );
  1026. if( funcId > 0 )
  1027. engine->scriptFunctions[funcId]->AddRefInternal();
  1028. }
  1029. break;
  1030. // Function pointers
  1031. case asBC_FuncPtr:
  1032. {
  1033. asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]);
  1034. asASSERT( func );
  1035. if( func )
  1036. func->AddRefInternal();
  1037. }
  1038. break;
  1039. }
  1040. }
  1041. }
  1042. }
  1043. // internal
  1044. void asCScriptFunction::ReleaseReferences()
  1045. {
  1046. asCArray<void*> ptrs;
  1047. // Only count references if there is any bytecode
  1048. if( scriptData && scriptData->byteCode.GetLength() )
  1049. {
  1050. if( returnType.GetTypeInfo() )
  1051. {
  1052. returnType.GetTypeInfo()->ReleaseInternal();
  1053. asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(returnType.GetTypeInfo());
  1054. if( group != 0 ) group->Release();
  1055. }
  1056. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  1057. if( parameterTypes[p].GetTypeInfo() )
  1058. {
  1059. parameterTypes[p].GetTypeInfo()->ReleaseInternal();
  1060. asCConfigGroup *group = engine->FindConfigGroupForTypeInfo(parameterTypes[p].GetTypeInfo());
  1061. if( group != 0 ) group->Release();
  1062. }
  1063. for (asUINT v = 0; v < scriptData->variables.GetLength(); v++)
  1064. {
  1065. asCTypeInfo* ti = reinterpret_cast<asCTypeInfo*>(scriptData->variables[v]->type.GetTypeInfo());
  1066. if (ti) // The null handle is also stored, but it doesn't have an object type
  1067. {
  1068. ti->ReleaseInternal();
  1069. asCConfigGroup* group = engine->FindConfigGroupForTypeInfo(ti);
  1070. if (group != 0) group->Release();
  1071. }
  1072. }
  1073. // Go through the byte code and release references to all resources used by the function
  1074. asCArray<asDWORD> &bc = scriptData->byteCode;
  1075. for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] )
  1076. {
  1077. switch( *(asBYTE*)&bc[n] )
  1078. {
  1079. // Object types
  1080. case asBC_OBJTYPE:
  1081. case asBC_FREE:
  1082. case asBC_REFCPY:
  1083. case asBC_RefCpyV:
  1084. {
  1085. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  1086. if( objType )
  1087. objType->ReleaseInternal();
  1088. }
  1089. break;
  1090. // Object type and function
  1091. case asBC_ALLOC:
  1092. {
  1093. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  1094. if( objType )
  1095. objType->ReleaseInternal();
  1096. int funcId = asBC_INTARG(&bc[n]+AS_PTR_SIZE);
  1097. if( funcId > 0 )
  1098. {
  1099. asCScriptFunction *fptr = engine->scriptFunctions[funcId];
  1100. if( fptr )
  1101. fptr->ReleaseInternal();
  1102. // The engine may have been forced to destroy the function internals early
  1103. // and this may will make it impossible to find the function by id anymore.
  1104. // This should only happen if the engine is released while the application
  1105. // is still keeping functions alive.
  1106. // TODO: Fix this possible memory leak
  1107. }
  1108. }
  1109. break;
  1110. // Global variables
  1111. case asBC_PGA:
  1112. case asBC_PshGPtr:
  1113. case asBC_LDG:
  1114. case asBC_PshG4:
  1115. case asBC_LdGRdR4:
  1116. case asBC_CpyGtoV4:
  1117. case asBC_CpyVtoG4:
  1118. case asBC_SetG4:
  1119. // Need to increase the reference for each global variable
  1120. {
  1121. void *gvarPtr = (void*)asBC_PTRARG(&bc[n]);
  1122. if( !gvarPtr ) break;
  1123. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  1124. if (!prop)
  1125. {
  1126. // The pointer is a string constant, so it needs to be released by the string factory
  1127. int r = engine->stringFactory->ReleaseStringConstant(gvarPtr);
  1128. UNUSED_VAR(r);
  1129. // If we get an error from the string factory there is not
  1130. // anything we can do about it, except report a message.
  1131. // TODO: Write a message showing that the string couldn't be
  1132. // released. Include the first 10 characters and the length
  1133. // to make it easier to identify which string it was
  1134. asASSERT(r >= 0);
  1135. break;
  1136. }
  1137. // Only release the properties once
  1138. if( !ptrs.Exists(gvarPtr) )
  1139. {
  1140. prop->Release();
  1141. ptrs.PushLast(gvarPtr);
  1142. }
  1143. asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id);
  1144. if( group != 0 ) group->Release();
  1145. }
  1146. break;
  1147. // System functions
  1148. case asBC_CALLSYS:
  1149. {
  1150. int funcId = asBC_INTARG(&bc[n]);
  1151. asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
  1152. if( group != 0 ) group->Release();
  1153. if( funcId )
  1154. {
  1155. asCScriptFunction *fptr = engine->scriptFunctions[funcId];
  1156. if( fptr )
  1157. fptr->ReleaseInternal();
  1158. }
  1159. }
  1160. break;
  1161. // Functions
  1162. case asBC_CALL:
  1163. case asBC_CALLINTF:
  1164. {
  1165. int funcId = asBC_INTARG(&bc[n]);
  1166. if( funcId )
  1167. {
  1168. asCScriptFunction *fptr = engine->scriptFunctions[funcId];
  1169. if( fptr )
  1170. fptr->ReleaseInternal();
  1171. // The engine may have been forced to destroy the function internals early
  1172. // and this may will make it impossible to find the function by id anymore.
  1173. // This should only happen if the engine is released while the application
  1174. // is still keeping functions alive.
  1175. // TODO: Fix this possible memory leak
  1176. }
  1177. }
  1178. break;
  1179. // Function pointers
  1180. case asBC_FuncPtr:
  1181. {
  1182. asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]);
  1183. if( func )
  1184. func->ReleaseInternal();
  1185. }
  1186. break;
  1187. }
  1188. }
  1189. // Release the jit compiled function
  1190. if( scriptData->jitFunction )
  1191. engine->jitCompiler->ReleaseJITFunction(scriptData->jitFunction);
  1192. scriptData->jitFunction = 0;
  1193. }
  1194. // Delegate
  1195. if( objForDelegate )
  1196. engine->ReleaseScriptObject(objForDelegate, funcForDelegate->GetObjectType());
  1197. objForDelegate = 0;
  1198. if( funcForDelegate )
  1199. funcForDelegate->Release();
  1200. funcForDelegate = 0;
  1201. }
  1202. // interface
  1203. int asCScriptFunction::GetReturnTypeId(asDWORD *flags) const
  1204. {
  1205. if( flags )
  1206. {
  1207. if( returnType.IsReference() )
  1208. {
  1209. *flags = asTM_INOUTREF;
  1210. *flags |= returnType.IsReadOnly() ? asTM_CONST : 0;
  1211. }
  1212. else
  1213. *flags = asTM_NONE;
  1214. }
  1215. return engine->GetTypeIdFromDataType(returnType);
  1216. }
  1217. // interface
  1218. asUINT asCScriptFunction::GetParamCount() const
  1219. {
  1220. return (asUINT)parameterTypes.GetLength();
  1221. }
  1222. // interface
  1223. int asCScriptFunction::GetParam(asUINT index, int *out_typeId, asDWORD *out_flags, const char **out_name, const char **out_defaultArg) const
  1224. {
  1225. if( index >= parameterTypes.GetLength() )
  1226. return asINVALID_ARG;
  1227. if( out_typeId )
  1228. *out_typeId = engine->GetTypeIdFromDataType(parameterTypes[index]);
  1229. if( out_flags )
  1230. {
  1231. *out_flags = inOutFlags[index];
  1232. *out_flags |= parameterTypes[index].IsReadOnly() ? asTM_CONST : 0;
  1233. }
  1234. if( out_name )
  1235. {
  1236. // The parameter names are not stored if loading from bytecode without debug information
  1237. if( index < parameterNames.GetLength() )
  1238. *out_name = parameterNames[index].AddressOf();
  1239. else
  1240. *out_name = 0;
  1241. }
  1242. if( out_defaultArg )
  1243. {
  1244. if( index < defaultArgs.GetLength() && defaultArgs[index] )
  1245. *out_defaultArg = defaultArgs[index]->AddressOf();
  1246. else
  1247. *out_defaultArg = 0;
  1248. }
  1249. return asSUCCESS;
  1250. }
  1251. // interface
  1252. asIScriptEngine *asCScriptFunction::GetEngine() const
  1253. {
  1254. return engine;
  1255. }
  1256. // interface
  1257. const char *asCScriptFunction::GetDeclaration(bool includeObjectName, bool includeNamespace, bool includeParamNames) const
  1258. {
  1259. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  1260. *tempString = GetDeclarationStr(includeObjectName, includeNamespace, includeParamNames);
  1261. return tempString->AddressOf();
  1262. }
  1263. // interface
  1264. const char *asCScriptFunction::GetScriptSectionName() const
  1265. {
  1266. if( scriptData && scriptData->scriptSectionIdx >= 0 )
  1267. return engine->scriptSectionNames[scriptData->scriptSectionIdx]->AddressOf();
  1268. return 0;
  1269. }
  1270. // interface
  1271. const char *asCScriptFunction::GetConfigGroup() const
  1272. {
  1273. asCConfigGroup *group = 0;
  1274. if( funcType != asFUNC_FUNCDEF )
  1275. group = engine->FindConfigGroupForFunction(id);
  1276. else
  1277. group = engine->FindConfigGroupForFuncDef(this->funcdefType);
  1278. if( group == 0 )
  1279. return 0;
  1280. return group->groupName.AddressOf();
  1281. }
  1282. // interface
  1283. asDWORD asCScriptFunction::GetAccessMask() const
  1284. {
  1285. return accessMask;
  1286. }
  1287. // internal
  1288. void asCScriptFunction::JITCompile()
  1289. {
  1290. if( funcType != asFUNC_SCRIPT )
  1291. return;
  1292. asASSERT( scriptData );
  1293. asIJITCompiler *jit = engine->GetJITCompiler();
  1294. if( !jit )
  1295. return;
  1296. // Make sure the function has been compiled with JitEntry instructions
  1297. // For functions that has JitEntry this will be a quick test
  1298. asUINT length;
  1299. asDWORD *byteCode = GetByteCode(&length);
  1300. asDWORD *end = byteCode + length;
  1301. bool foundJitEntry = false;
  1302. while( byteCode < end )
  1303. {
  1304. // Determine the instruction
  1305. asEBCInstr op = asEBCInstr(*(asBYTE*)byteCode);
  1306. if( op == asBC_JitEntry )
  1307. {
  1308. foundJitEntry = true;
  1309. break;
  1310. }
  1311. // Move to next instruction
  1312. byteCode += asBCTypeSize[asBCInfo[op].type];
  1313. }
  1314. if( !foundJitEntry )
  1315. {
  1316. asCString msg;
  1317. msg.Format(TXT_NO_JIT_IN_FUNC_s, GetDeclaration());
  1318. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  1319. }
  1320. // Release the previous function, if any
  1321. if( scriptData->jitFunction )
  1322. {
  1323. engine->jitCompiler->ReleaseJITFunction(scriptData->jitFunction);
  1324. scriptData->jitFunction = 0;
  1325. }
  1326. // Compile for native system
  1327. int r = jit->CompileFunction(this, &scriptData->jitFunction);
  1328. if( r < 0 )
  1329. asASSERT( scriptData->jitFunction == 0 );
  1330. }
  1331. // interface
  1332. asDWORD *asCScriptFunction::GetByteCode(asUINT *length)
  1333. {
  1334. if( scriptData == 0 ) return 0;
  1335. if( length )
  1336. *length = (asUINT)scriptData->byteCode.GetLength();
  1337. if( scriptData->byteCode.GetLength() )
  1338. return scriptData->byteCode.AddressOf();
  1339. return 0;
  1340. }
  1341. // interface
  1342. void *asCScriptFunction::SetUserData(void *data, asPWORD type)
  1343. {
  1344. // As a thread might add a new new user data at the same time as another
  1345. // it is necessary to protect both read and write access to the userData member
  1346. ACQUIREEXCLUSIVE(engine->engineRWLock);
  1347. // It is not intended to store a lot of different types of userdata,
  1348. // so a more complex structure like a associative map would just have
  1349. // more overhead than a simple array.
  1350. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  1351. {
  1352. if( userData[n] == type )
  1353. {
  1354. void *oldData = reinterpret_cast<void*>(userData[n+1]);
  1355. userData[n+1] = reinterpret_cast<asPWORD>(data);
  1356. RELEASEEXCLUSIVE(engine->engineRWLock);
  1357. return oldData;
  1358. }
  1359. }
  1360. userData.PushLast(type);
  1361. userData.PushLast(reinterpret_cast<asPWORD>(data));
  1362. RELEASEEXCLUSIVE(engine->engineRWLock);
  1363. return 0;
  1364. }
  1365. // interface
  1366. void *asCScriptFunction::GetUserData(asPWORD type) const
  1367. {
  1368. // There may be multiple threads reading, but when
  1369. // setting the user data nobody must be reading.
  1370. ACQUIRESHARED(engine->engineRWLock);
  1371. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  1372. {
  1373. if( userData[n] == type )
  1374. {
  1375. RELEASESHARED(engine->engineRWLock);
  1376. return reinterpret_cast<void*>(userData[n+1]);
  1377. }
  1378. }
  1379. RELEASESHARED(engine->engineRWLock);
  1380. return 0;
  1381. }
  1382. // internal
  1383. // TODO: cleanup: This method should probably be a member of the engine
  1384. asCGlobalProperty *asCScriptFunction::GetPropertyByGlobalVarPtr(void *gvarPtr)
  1385. {
  1386. asSMapNode<void*, asCGlobalProperty*> *node;
  1387. if( engine->varAddressMap.MoveTo(&node, gvarPtr) )
  1388. {
  1389. asASSERT(gvarPtr == node->value->GetAddressOfValue());
  1390. return node->value;
  1391. }
  1392. return 0;
  1393. }
  1394. // internal
  1395. int asCScriptFunction::GetRefCount()
  1396. {
  1397. asASSERT( funcType == asFUNC_DELEGATE );
  1398. return externalRefCount.get();
  1399. }
  1400. // internal
  1401. void asCScriptFunction::SetFlag()
  1402. {
  1403. gcFlag = true;
  1404. }
  1405. // internal
  1406. bool asCScriptFunction::GetFlag()
  1407. {
  1408. return gcFlag;
  1409. }
  1410. // internal
  1411. void asCScriptFunction::EnumReferences(asIScriptEngine *)
  1412. {
  1413. asASSERT( funcType == asFUNC_DELEGATE );
  1414. // Delegate
  1415. if( objForDelegate )
  1416. engine->GCEnumCallback(objForDelegate);
  1417. }
  1418. // internal
  1419. void asCScriptFunction::ReleaseAllHandles(asIScriptEngine *)
  1420. {
  1421. asASSERT( funcType == asFUNC_DELEGATE );
  1422. // Release paramaters
  1423. // Delegate
  1424. if( objForDelegate )
  1425. engine->ReleaseScriptObject(objForDelegate, funcForDelegate->GetObjectType());
  1426. objForDelegate = 0;
  1427. }
  1428. // interface
  1429. bool asCScriptFunction::IsShared() const
  1430. {
  1431. // All system functions are shared
  1432. if( funcType == asFUNC_SYSTEM ) return true;
  1433. // All class methods for shared classes are also shared
  1434. asASSERT( objectType == 0 || objectType->engine == engine || objectType->engine == 0 );
  1435. if( objectType && (objectType->flags & asOBJ_SHARED) ) return true;
  1436. // funcdefs that are registered by the application are shared
  1437. if (funcType == asFUNC_FUNCDEF && module == 0) return true;
  1438. // Functions that have been specifically marked as shared are shared
  1439. return traits.GetTrait(asTRAIT_SHARED);
  1440. }
  1441. // interface
  1442. bool asCScriptFunction::IsFinal() const
  1443. {
  1444. return traits.GetTrait(asTRAIT_FINAL);
  1445. }
  1446. // interface
  1447. bool asCScriptFunction::IsOverride() const
  1448. {
  1449. return traits.GetTrait(asTRAIT_OVERRIDE);
  1450. }
  1451. // interface
  1452. bool asCScriptFunction::IsExplicit() const
  1453. {
  1454. return traits.GetTrait(asTRAIT_EXPLICIT);
  1455. }
  1456. // interface
  1457. bool asCScriptFunction::IsProperty() const
  1458. {
  1459. return traits.GetTrait(asTRAIT_PROPERTY);
  1460. }
  1461. // internal
  1462. bool asCScriptFunction::IsFactory() const
  1463. {
  1464. if (objectType) return false;
  1465. asCObjectType* type = CastToObjectType(returnType.GetTypeInfo());
  1466. if (type == 0) return false;
  1467. if (type->name != name) return false;
  1468. if (type->nameSpace != nameSpace) return false;
  1469. return true;
  1470. }
  1471. // internal
  1472. asCScriptFunction* asCScriptFunction::FindNextFunctionCalled(asUINT startSearchFromProgramPos, int *outStackDelta, asUINT *outProgramPos)
  1473. {
  1474. if (scriptData == 0)
  1475. return 0;
  1476. if (outProgramPos)
  1477. *outProgramPos = startSearchFromProgramPos;
  1478. // Find out which function that will be called
  1479. asCScriptFunction* calledFunc = 0;
  1480. int stackDelta = 0;
  1481. for (asUINT n = startSearchFromProgramPos; scriptData->byteCode.GetLength(); )
  1482. {
  1483. asBYTE bc = *(asBYTE*)&scriptData->byteCode[n];
  1484. if (bc == asBC_CALL ||
  1485. bc == asBC_CALLSYS ||
  1486. bc == asBC_Thiscall1 ||
  1487. bc == asBC_CALLINTF ||
  1488. bc == asBC_ALLOC ||
  1489. bc == asBC_CALLBND ||
  1490. bc == asBC_CallPtr)
  1491. {
  1492. calledFunc = GetCalledFunction(n);
  1493. if (outProgramPos)
  1494. *outProgramPos = n + asBCTypeSize[asBCInfo[bc].type];
  1495. break;
  1496. }
  1497. // Keep track of the stack size between the
  1498. // instruction that needs to be adjusted and the call
  1499. stackDelta += asBCInfo[bc].stackInc;
  1500. n += asBCTypeSize[asBCInfo[bc].type];
  1501. }
  1502. if (outStackDelta)
  1503. *outStackDelta = stackDelta;
  1504. return calledFunc;
  1505. }
  1506. // internal
  1507. asCScriptFunction* asCScriptFunction::GetCalledFunction(asDWORD programPos)
  1508. {
  1509. if (scriptData == 0)
  1510. return 0;
  1511. asBYTE bc = *(asBYTE*)&scriptData->byteCode[programPos];
  1512. if (bc == asBC_CALL ||
  1513. bc == asBC_CALLSYS ||
  1514. bc == asBC_Thiscall1 ||
  1515. bc == asBC_CALLINTF)
  1516. {
  1517. // Find the function from the function id in bytecode
  1518. int funcId = asBC_INTARG(&scriptData->byteCode[programPos]);
  1519. return engine->scriptFunctions[funcId];
  1520. }
  1521. else if (bc == asBC_ALLOC)
  1522. {
  1523. // Find the function from the function id in the bytecode
  1524. int funcId = asBC_INTARG(&scriptData->byteCode[programPos + AS_PTR_SIZE]);
  1525. return engine->scriptFunctions[funcId];
  1526. }
  1527. else if (bc == asBC_CALLBND)
  1528. {
  1529. // Find the function from the engine's bind array
  1530. int funcId = asBC_INTARG(&scriptData->byteCode[programPos]);
  1531. return engine->importedFunctions[funcId & ~FUNC_IMPORTED]->importedFunctionSignature;
  1532. }
  1533. else if (bc == asBC_CallPtr)
  1534. {
  1535. asUINT v;
  1536. int var = asBC_SWORDARG0(&scriptData->byteCode[programPos]);
  1537. // Find the funcdef from the local variable
  1538. for (v = 0; v < scriptData->variables.GetLength(); v++)
  1539. if (scriptData->variables[v]->stackOffset == var)
  1540. return CastToFuncdefType(scriptData->variables[v]->type.GetTypeInfo())->funcdef;
  1541. // Look in parameters
  1542. int paramPos = 0;
  1543. if (objectType)
  1544. paramPos -= AS_PTR_SIZE;
  1545. if (DoesReturnOnStack())
  1546. paramPos -= AS_PTR_SIZE;
  1547. for (v = 0; v < parameterTypes.GetLength(); v++)
  1548. {
  1549. if (var == paramPos)
  1550. {
  1551. if (parameterTypes[v].IsFuncdef())
  1552. return CastToFuncdefType(parameterTypes[v].GetTypeInfo())->funcdef;
  1553. else
  1554. return 0;
  1555. }
  1556. paramPos -= parameterTypes[v].GetSizeOnStackDWords();
  1557. }
  1558. }
  1559. return 0;
  1560. }
  1561. END_AS_NAMESPACE