as_scriptfunction.cpp 49 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2014 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: 2.29.0: 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 | asOBJ_SCRIPT_FUNCTION;
  100. engine->functionBehaviours.name = "_builtin_function_";
  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: 2.29.0: 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::CreateObject(&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::GetDelegateObject() const
  172. {
  173. return objForDelegate;
  174. }
  175. // interface
  176. asIObjectType *asCScriptFunction::GetDelegateObjectType() const
  177. {
  178. if( objForDelegate == 0 || funcForDelegate == 0 )
  179. return 0;
  180. return funcForDelegate->objectType;
  181. }
  182. // interface
  183. asIScriptFunction *asCScriptFunction::GetDelegateFunction() const
  184. {
  185. return funcForDelegate;
  186. }
  187. // TODO: 2.29.0: operator==
  188. /*
  189. // internal
  190. bool asCScriptFunction::operator==(const asCScriptFunction &other) const
  191. {
  192. if( this == &other ) return true;
  193. if( this->funcType == asFUNC_DELEGATE && other.funcType == asFUNC_DELEGATE )
  194. {
  195. if( this->objForDelegate == other.objForDelegate &&
  196. this->funcForDelegate == other.funcForDelegate )
  197. return true;
  198. }
  199. return false;
  200. }
  201. */
  202. // internal
  203. int asCScriptFunction::RegisterListPattern(const char *decl, asCScriptNode *listNodes)
  204. {
  205. if( listNodes == 0 )
  206. return asINVALID_ARG;
  207. // Build the representation of the list pattern from the script nodes
  208. asSListPatternNode *node;
  209. listPattern = asNEW(asSListPatternNode)(asLPT_START);
  210. node = listPattern;
  211. // Recursively parse the child
  212. int r = ParseListPattern(node, decl, listNodes);
  213. node->next = asNEW(asSListPatternNode)(asLPT_END);
  214. return r;
  215. }
  216. // internal
  217. int asCScriptFunction::ParseListPattern(asSListPatternNode *&target, const char *decl, asCScriptNode *listNodes)
  218. {
  219. asSListPatternNode *node = target;
  220. listNodes = listNodes->firstChild;
  221. while( listNodes )
  222. {
  223. if( listNodes->nodeType == snIdentifier )
  224. {
  225. asCString token(&decl[listNodes->tokenPos], listNodes->tokenLength);
  226. if( token == "repeat" )
  227. {
  228. node->next = asNEW(asSListPatternNode)(asLPT_REPEAT);
  229. node = node->next;
  230. }
  231. else if( token == "repeat_same" )
  232. {
  233. // TODO: list: Should make sure this is a sub-list
  234. node->next = asNEW(asSListPatternNode)(asLPT_REPEAT_SAME);
  235. node = node->next;
  236. }
  237. else
  238. {
  239. // Shouldn't happen as the parser already reported the error
  240. asASSERT(false);
  241. }
  242. }
  243. else if( listNodes->nodeType == snDataType )
  244. {
  245. asCDataType dt;
  246. asCBuilder builder(engine, 0);
  247. asCScriptCode code;
  248. code.SetCode("", decl, 0, false);
  249. dt = builder.CreateDataTypeFromNode(listNodes, &code, engine->defaultNamespace, false, returnType.GetObjectType());
  250. node->next = asNEW(asSListPatternDataTypeNode)(dt);
  251. node = node->next;
  252. }
  253. else if( listNodes->nodeType == snListPattern )
  254. {
  255. node->next = asNEW(asSListPatternNode)(asLPT_START);
  256. node = node->next;
  257. // Recursively parse the child
  258. int r = ParseListPattern(node, decl, listNodes);
  259. if( r < 0 )
  260. return r;
  261. node->next = asNEW(asSListPatternNode)(asLPT_END);
  262. node = node->next;
  263. }
  264. else
  265. {
  266. // Unexpected token in the list, the parser shouldn't have allowed
  267. asASSERT( false );
  268. return -1;
  269. }
  270. listNodes = listNodes->next;
  271. }
  272. target = node;
  273. return 0;
  274. }
  275. // internal
  276. asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, asEFuncType _funcType)
  277. {
  278. refCount.set(1);
  279. this->engine = engine;
  280. this->scriptData = 0;
  281. funcType = _funcType;
  282. module = mod;
  283. objectType = 0;
  284. name = "";
  285. isReadOnly = false;
  286. isPrivate = false;
  287. isFinal = false;
  288. isOverride = false;
  289. sysFuncIntf = 0;
  290. signatureId = 0;
  291. dontCleanUpOnException = false;
  292. vfTableIdx = -1;
  293. gcFlag = false;
  294. userData = 0;
  295. id = 0;
  296. accessMask = 0xFFFFFFFF;
  297. isShared = false;
  298. nameSpace = engine->nameSpaces[0];
  299. objForDelegate = 0;
  300. funcForDelegate = 0;
  301. listPattern = 0;
  302. if( funcType == asFUNC_SCRIPT )
  303. AllocateScriptFunctionData();
  304. // Notify the GC of script functions
  305. if( (funcType == asFUNC_SCRIPT && mod == 0) || (funcType == asFUNC_DELEGATE) )
  306. engine->gc.AddScriptObjectToGC(this, &engine->functionBehaviours);
  307. }
  308. void asCScriptFunction::AllocateScriptFunctionData()
  309. {
  310. if( scriptData ) return;
  311. scriptData = asNEW(ScriptFunctionData);
  312. scriptData->stackNeeded = 0;
  313. scriptData->variableSpace = 0;
  314. scriptData->scriptSectionIdx = -1;
  315. scriptData->declaredAt = 0;
  316. scriptData->jitFunction = 0;
  317. }
  318. void asCScriptFunction::DeallocateScriptFunctionData()
  319. {
  320. if( !scriptData ) return;
  321. for( asUINT n = 0; n < scriptData->variables.GetLength(); n++ )
  322. asDELETE(scriptData->variables[n],asSScriptVariable);
  323. scriptData->variables.SetLength(0);
  324. asDELETE(scriptData, ScriptFunctionData);
  325. scriptData = 0;
  326. }
  327. // internal
  328. asCScriptFunction::~asCScriptFunction()
  329. {
  330. // Imported functions are not reference counted, nor are dummy
  331. // functions that are allocated on the stack
  332. asASSERT( funcType == asFUNC_DUMMY ||
  333. funcType == asFUNC_IMPORTED ||
  334. refCount.get() == 0 );
  335. // If the engine pointer is 0, then DestroyInternal has already been called and there is nothing more to do
  336. if( engine == 0 ) return;
  337. DestroyInternal();
  338. // Tell engine to free the function id. This will make it impossible to
  339. // refer to the function by id. Where this is done, it is quite possible
  340. // they will leak.
  341. if( funcType != -1 && funcType != asFUNC_IMPORTED && id )
  342. engine->FreeScriptFunctionId(id);
  343. id = 0;
  344. // Finally set the engine pointer to 0 because it must not be accessed again
  345. engine = 0;
  346. }
  347. // internal
  348. void asCScriptFunction::DestroyHalfCreated()
  349. {
  350. asASSERT( refCount.get() == 1 );
  351. // Set the funcType to dummy so the destructor won't complain
  352. funcType = asFUNC_DUMMY;
  353. // If the bytecode exist remove it before destroying, otherwise it
  354. // will fail when the destructor releases the references as the bytecode
  355. // is not fully constructed.
  356. if( scriptData )
  357. scriptData->byteCode.SetLength(0);
  358. delete this;
  359. }
  360. // internal
  361. void asCScriptFunction::DestroyInternal()
  362. {
  363. // Clean up user data
  364. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  365. {
  366. if( userData[n+1] )
  367. {
  368. for( asUINT c = 0; c < engine->cleanFunctionFuncs.GetLength(); c++ )
  369. if( engine->cleanFunctionFuncs[c].type == userData[n] )
  370. engine->cleanFunctionFuncs[c].cleanFunc(this);
  371. }
  372. }
  373. userData.SetLength(0);
  374. // Release all references the function holds to other objects
  375. ReleaseReferences();
  376. parameterTypes.SetLength(0);
  377. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  378. for( asUINT p = 0; p < defaultArgs.GetLength(); p++ )
  379. if( defaultArgs[p] )
  380. asDELETE(defaultArgs[p], asCString);
  381. defaultArgs.SetLength(0);
  382. if( sysFuncIntf )
  383. asDELETE(sysFuncIntf,asSSystemFunctionInterface);
  384. sysFuncIntf = 0;
  385. DeallocateScriptFunctionData();
  386. // Deallocate list pattern data
  387. while( listPattern )
  388. {
  389. asSListPatternNode *n = listPattern->next;
  390. asDELETE(listPattern, asSListPatternNode);
  391. listPattern = n;
  392. }
  393. }
  394. // interface
  395. int asCScriptFunction::GetId() const
  396. {
  397. return id;
  398. }
  399. // interface
  400. int asCScriptFunction::AddRef() const
  401. {
  402. gcFlag = false;
  403. asASSERT( funcType != asFUNC_IMPORTED );
  404. return refCount.atomicInc();
  405. }
  406. // interface
  407. int asCScriptFunction::Release() const
  408. {
  409. gcFlag = false;
  410. asASSERT( funcType != asFUNC_IMPORTED );
  411. int r = refCount.atomicDec();
  412. if( r == 0 &&
  413. funcType != asFUNC_FUNCDEF && // Funcdefs are treated as object types and will be deleted by ClearUnusedTypes()
  414. funcType != asFUNC_DUMMY ) // Dummy functions are allocated on the stack and cannot be deleted
  415. asDELETE(const_cast<asCScriptFunction*>(this),asCScriptFunction);
  416. return r;
  417. }
  418. // internal
  419. void asCScriptFunction::Orphan(asIScriptModule *mod)
  420. {
  421. if( mod && module == mod )
  422. {
  423. module = 0;
  424. if( funcType == asFUNC_SCRIPT && refCount.get() > 1 )
  425. {
  426. // This function is being orphaned, so notify the GC so it can check for circular references
  427. engine->gc.AddScriptObjectToGC(this, &engine->functionBehaviours);
  428. }
  429. }
  430. Release();
  431. }
  432. // interface
  433. int asCScriptFunction::GetTypeId() const
  434. {
  435. // This const cast is ok, the object won't be modified
  436. asCDataType dt = asCDataType::CreateFuncDef(const_cast<asCScriptFunction*>(this));
  437. return engine->GetTypeIdFromDataType(dt);
  438. }
  439. // interface
  440. bool asCScriptFunction::IsCompatibleWithTypeId(int typeId) const
  441. {
  442. asCDataType dt = engine->GetDataTypeFromTypeId(typeId);
  443. // Make sure the type is a function
  444. asCScriptFunction *func = dt.GetFuncDef();
  445. if( func == 0 )
  446. return false;
  447. if( !IsSignatureExceptNameEqual(func) )
  448. return false;
  449. // If this is a class method, then only return true if the object type is the same
  450. if( objectType != func->objectType )
  451. return false;
  452. return true;
  453. }
  454. // interface
  455. const char *asCScriptFunction::GetModuleName() const
  456. {
  457. if( module )
  458. {
  459. return module->name.AddressOf();
  460. }
  461. return 0;
  462. }
  463. // interface
  464. asIScriptModule *asCScriptFunction::GetModule() const
  465. {
  466. return module;
  467. }
  468. // interface
  469. asIObjectType *asCScriptFunction::GetObjectType() const
  470. {
  471. return objectType;
  472. }
  473. // interface
  474. const char *asCScriptFunction::GetObjectName() const
  475. {
  476. if( objectType )
  477. return objectType->GetName();
  478. return 0;
  479. }
  480. // interface
  481. const char *asCScriptFunction::GetName() const
  482. {
  483. return name.AddressOf();
  484. }
  485. // interface
  486. const char *asCScriptFunction::GetNamespace() const
  487. {
  488. return nameSpace->name.AddressOf();
  489. }
  490. // interface
  491. bool asCScriptFunction::IsReadOnly() const
  492. {
  493. return isReadOnly;
  494. }
  495. // interface
  496. bool asCScriptFunction::IsPrivate() const
  497. {
  498. return isPrivate;
  499. }
  500. // internal
  501. int asCScriptFunction::GetSpaceNeededForArguments()
  502. {
  503. // We need to check the size for each type
  504. int s = 0;
  505. for( asUINT n = 0; n < parameterTypes.GetLength(); n++ )
  506. s += parameterTypes[n].GetSizeOnStackDWords();
  507. return s;
  508. }
  509. // internal
  510. int asCScriptFunction::GetSpaceNeededForReturnValue()
  511. {
  512. return returnType.GetSizeOnStackDWords();
  513. }
  514. // internal
  515. bool asCScriptFunction::DoesReturnOnStack() const
  516. {
  517. if( returnType.GetObjectType() &&
  518. (returnType.GetObjectType()->flags & asOBJ_VALUE) &&
  519. !returnType.IsReference() )
  520. return true;
  521. return false;
  522. }
  523. // internal
  524. asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName, bool includeNamespace, bool includeParamNames) const
  525. {
  526. asCString str;
  527. // TODO: default arg: Make the declaration with the default args an option
  528. // Don't add the return type for constructors and destructors
  529. if( !(returnType.GetTokenType() == ttVoid &&
  530. objectType &&
  531. (name == objectType->name || (name.GetLength() > 0 && name[0] == '~') ||
  532. name == "_beh_0_" || name == "_beh_2_")) )
  533. {
  534. str = returnType.Format();
  535. str += " ";
  536. }
  537. if( objectType && includeObjectName )
  538. {
  539. if( includeNamespace )
  540. str += objectType->nameSpace->name + "::";
  541. if( objectType->name != "" )
  542. str += objectType->name + "::";
  543. else
  544. str += "_unnamed_type_::";
  545. }
  546. else if( includeNamespace )
  547. {
  548. str += nameSpace->name + "::";
  549. }
  550. if( name == "" )
  551. str += "_unnamed_function_(";
  552. else if( name.SubString(0,5) == "_beh_" && name.GetLength() == 7 )
  553. {
  554. if( name[5] == '0' + asBEHAVE_CONSTRUCT )
  555. str += objectType->name + "(";
  556. else if( name[5] == '0' + asBEHAVE_FACTORY )
  557. str += returnType.GetObjectType()->name + "(";
  558. else if( name[5] == '0' + asBEHAVE_DESTRUCT )
  559. str += "~" + objectType->name + "(";
  560. else
  561. str += name + "(";
  562. }
  563. else
  564. str += name + "(";
  565. if( parameterTypes.GetLength() > 0 )
  566. {
  567. asUINT n;
  568. for( n = 0; n < parameterTypes.GetLength() - 1; n++ )
  569. {
  570. str += parameterTypes[n].Format();
  571. if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
  572. {
  573. if( inOutFlags[n] == asTM_INREF ) str += "in";
  574. else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
  575. else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
  576. }
  577. if( includeParamNames && n < parameterNames.GetLength() && parameterNames[n].GetLength() != 0 )
  578. {
  579. str += " ";
  580. str += parameterNames[n];
  581. }
  582. if( defaultArgs.GetLength() > n && defaultArgs[n] )
  583. {
  584. asCString tmp;
  585. tmp.Format(" = %s", defaultArgs[n]->AddressOf());
  586. str += tmp;
  587. }
  588. str += ", ";
  589. }
  590. // Add the last parameter
  591. str += parameterTypes[n].Format();
  592. if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
  593. {
  594. if( inOutFlags[n] == asTM_INREF ) str += "in";
  595. else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
  596. else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
  597. }
  598. if( includeParamNames && n < parameterNames.GetLength() && parameterNames[n].GetLength() != 0 )
  599. {
  600. str += " ";
  601. str += parameterNames[n];
  602. }
  603. if( defaultArgs.GetLength() > n && defaultArgs[n] )
  604. {
  605. asCString tmp;
  606. tmp.Format(" = %s", defaultArgs[n]->AddressOf());
  607. str += tmp;
  608. }
  609. }
  610. str += ")";
  611. if( isReadOnly )
  612. str += " const";
  613. // Add the declaration of the list pattern
  614. if( listPattern )
  615. {
  616. asSListPatternNode *n = listPattern;
  617. bool first = true;
  618. while( n )
  619. {
  620. if( n->type == asLPT_START )
  621. {
  622. str += " {";
  623. first = true;
  624. }
  625. else if( n->type == asLPT_END )
  626. {
  627. str += " }";
  628. first = false;
  629. }
  630. else if( n->type == asLPT_REPEAT )
  631. str += " repeat";
  632. else if( n->type == asLPT_REPEAT_SAME )
  633. str += " repeat_same";
  634. else if( n->type == asLPT_TYPE )
  635. {
  636. if( first )
  637. {
  638. str += " ";
  639. first = false;
  640. }
  641. else
  642. str += ", ";
  643. str += reinterpret_cast<asSListPatternDataTypeNode*>(n)->dataType.Format();
  644. }
  645. n = n->next;
  646. }
  647. }
  648. return str;
  649. }
  650. // interface
  651. int asCScriptFunction::FindNextLineWithCode(int line) const
  652. {
  653. if( scriptData == 0 ) return -1;
  654. if( scriptData->lineNumbers.GetLength() == 0 ) return -1;
  655. // The line numbers for constructors are not in order due to the way
  656. // class members can be initialized directly in the declaration
  657. if( objectType && objectType->name == name )
  658. {
  659. // Sort all line numbers before looking for the next
  660. asCArray<int> lineNbrs;
  661. for( asUINT n = 1; n < scriptData->lineNumbers.GetLength(); n += 2 )
  662. lineNbrs.PushLast(scriptData->lineNumbers[n]&0xFFFFF);
  663. struct C
  664. {
  665. static int cmp(const void *a, const void *b) { return *(int*)a - *(int*)b; }
  666. };
  667. std::qsort(&lineNbrs[0], lineNbrs.GetLength(), sizeof(int), C::cmp);
  668. if( line < lineNbrs[0] && line < (scriptData->declaredAt&0xFFFFF)) return -1;
  669. if( line > lineNbrs[lineNbrs.GetLength()-1] ) return -1;
  670. // Find the line with code on or right after the input line
  671. // TODO: optimize: Do binary search
  672. for( asUINT n = 0; n < lineNbrs.GetLength(); n++ )
  673. if( line <= lineNbrs[n] )
  674. return lineNbrs[n];
  675. }
  676. else
  677. {
  678. // Check if given line is outside function
  679. if( line < (scriptData->declaredAt&0xFFFFF) ) return -1;
  680. if( line > (scriptData->lineNumbers[scriptData->lineNumbers.GetLength()-1]&0xFFFFF) ) return -1;
  681. // Find the line with code on or right after the input line
  682. // TODO: optimize: Do binary search instead
  683. for( asUINT n = 1; n < scriptData->lineNumbers.GetLength(); n += 2 )
  684. {
  685. if( line <= (scriptData->lineNumbers[n]&0xFFFFF) )
  686. return (scriptData->lineNumbers[n]&0xFFFFF);
  687. }
  688. }
  689. return -1;
  690. }
  691. // internal
  692. int asCScriptFunction::GetLineNumber(int programPosition, int *sectionIdx)
  693. {
  694. asASSERT( scriptData );
  695. if( sectionIdx ) *sectionIdx = scriptData->scriptSectionIdx;
  696. if( scriptData->lineNumbers.GetLength() == 0 ) return 0;
  697. if( sectionIdx )
  698. {
  699. // Find the correct section index if the function is compiled from multiple sections
  700. // This array will be empty most of the time so we don't need a sofisticated algorithm to search it
  701. for( asUINT n = 0; n < scriptData->sectionIdxs.GetLength(); n += 2 )
  702. {
  703. if( scriptData->sectionIdxs[n] <= programPosition )
  704. *sectionIdx = scriptData->sectionIdxs[n+1];
  705. }
  706. }
  707. // Do a binary search in the buffer
  708. int max = (int)scriptData->lineNumbers.GetLength()/2 - 1;
  709. int min = 0;
  710. int i = max/2;
  711. for(;;)
  712. {
  713. if( scriptData->lineNumbers[i*2] < programPosition )
  714. {
  715. // Have we found the largest number < programPosition?
  716. if( max == i ) return scriptData->lineNumbers[i*2+1];
  717. if( scriptData->lineNumbers[i*2+2] > programPosition ) return scriptData->lineNumbers[i*2+1];
  718. min = i + 1;
  719. i = (max + min)/2;
  720. }
  721. else if( scriptData->lineNumbers[i*2] > programPosition )
  722. {
  723. // Have we found the smallest number > programPosition?
  724. if( min == i ) return scriptData->lineNumbers[i*2+1];
  725. max = i - 1;
  726. i = (max + min)/2;
  727. }
  728. else
  729. {
  730. // We found the exact position
  731. return scriptData->lineNumbers[i*2+1];
  732. }
  733. }
  734. }
  735. // interface
  736. asEFuncType asCScriptFunction::GetFuncType() const
  737. {
  738. return funcType;
  739. }
  740. // interface
  741. asUINT asCScriptFunction::GetVarCount() const
  742. {
  743. if( scriptData )
  744. return asUINT(scriptData->variables.GetLength());
  745. return 0;
  746. }
  747. // interface
  748. int asCScriptFunction::GetVar(asUINT index, const char **name, int *typeId) const
  749. {
  750. if( scriptData == 0 )
  751. return asNOT_SUPPORTED;
  752. if( index >= scriptData->variables.GetLength() )
  753. return asINVALID_ARG;
  754. if( name )
  755. *name = scriptData->variables[index]->name.AddressOf();
  756. if( typeId )
  757. *typeId = engine->GetTypeIdFromDataType(scriptData->variables[index]->type);
  758. return asSUCCESS;
  759. }
  760. // interface
  761. const char *asCScriptFunction::GetVarDecl(asUINT index, bool includeNamespace) const
  762. {
  763. if( scriptData == 0 || index >= scriptData->variables.GetLength() )
  764. return 0;
  765. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  766. *tempString = scriptData->variables[index]->type.Format(includeNamespace);
  767. *tempString += " " + scriptData->variables[index]->name;
  768. return tempString->AddressOf();
  769. }
  770. // internal
  771. void asCScriptFunction::AddVariable(asCString &name, asCDataType &type, int stackOffset)
  772. {
  773. asASSERT( scriptData );
  774. asSScriptVariable *var = asNEW(asSScriptVariable);
  775. if( var == 0 )
  776. {
  777. // Out of memory
  778. return;
  779. }
  780. var->name = name;
  781. var->type = type;
  782. var->stackOffset = stackOffset;
  783. var->declaredAtProgramPos = 0;
  784. scriptData->variables.PushLast(var);
  785. }
  786. // internal
  787. asCObjectType *asCScriptFunction::GetObjectTypeOfLocalVar(short varOffset)
  788. {
  789. asASSERT( scriptData );
  790. for( asUINT n = 0; n < scriptData->objVariablePos.GetLength(); n++ )
  791. {
  792. if( scriptData->objVariablePos[n] == varOffset )
  793. return scriptData->objVariableTypes[n];
  794. }
  795. return 0;
  796. }
  797. // internal
  798. void asCScriptFunction::ComputeSignatureId()
  799. {
  800. // This function will compute the signatureId based on the
  801. // function name, return type, and parameter types. The object
  802. // type for methods is not used, so that class methods and
  803. // interface methods match each other.
  804. for( asUINT n = 0; n < engine->signatureIds.GetLength(); n++ )
  805. {
  806. if( !IsSignatureEqual(engine->signatureIds[n]) ) continue;
  807. // We don't need to increment the reference counter here, because
  808. // asCScriptEngine::FreeScriptFunctionId will maintain the signature
  809. // id as the function is freed.
  810. signatureId = engine->signatureIds[n]->signatureId;
  811. return;
  812. }
  813. signatureId = id;
  814. engine->signatureIds.PushLast(this);
  815. }
  816. // internal
  817. bool asCScriptFunction::IsSignatureEqual(const asCScriptFunction *func) const
  818. {
  819. if( !IsSignatureExceptNameEqual(func) || name != func->name ) return false;
  820. return true;
  821. }
  822. // internal
  823. bool asCScriptFunction::IsSignatureExceptNameEqual(const asCScriptFunction *func) const
  824. {
  825. return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, func->objectType, func->isReadOnly);
  826. }
  827. // internal
  828. bool asCScriptFunction::IsSignatureExceptNameEqual(const asCDataType &retType, const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &paramInOut, const asCObjectType *objType, bool readOnly) const
  829. {
  830. if( this->returnType != retType ) return false;
  831. return IsSignatureExceptNameAndReturnTypeEqual(paramTypes, paramInOut, objType, readOnly);
  832. }
  833. // internal
  834. bool asCScriptFunction::IsSignatureExceptNameAndObjectTypeEqual(const asCScriptFunction *func) const
  835. {
  836. return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, objectType, isReadOnly);
  837. }
  838. // internal
  839. bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCScriptFunction *func) const
  840. {
  841. return IsSignatureExceptNameAndReturnTypeEqual(func->parameterTypes, func->inOutFlags, func->objectType, func->isReadOnly);
  842. }
  843. // internal
  844. bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &paramInOut, const asCObjectType *objType, bool readOnly) const
  845. {
  846. if( this->isReadOnly != readOnly ) return false;
  847. if( this->inOutFlags != paramInOut ) return false;
  848. if( this->parameterTypes != paramTypes ) return false;
  849. if( (this->objectType != 0) != (objType != 0) ) return false;
  850. return true;
  851. }
  852. // internal
  853. void asCScriptFunction::AddReferences()
  854. {
  855. // This array will be used to make sure we only add the reference to the same resource once
  856. // This is especially important for global variables, as it expects the initialization function
  857. // to hold only one reference to the variable. However, if the variable is initialized through
  858. // the default constructor followed by the assignment operator we will have two references to
  859. // the variable in the function.
  860. asCArray<void*> ptrs;
  861. // Only count references if there is any bytecode
  862. if( scriptData && scriptData->byteCode.GetLength() )
  863. {
  864. if( returnType.IsObject() )
  865. returnType.GetObjectType()->AddRef();
  866. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  867. if( parameterTypes[p].IsObject() )
  868. parameterTypes[p].GetObjectType()->AddRef();
  869. for( asUINT v = 0; v < scriptData->objVariableTypes.GetLength(); v++ )
  870. if( scriptData->objVariableTypes[v] ) // The null handle is also stored, but it doesn't have an object type
  871. scriptData->objVariableTypes[v]->AddRef();
  872. // Go through the byte code and add references to all resources used by the function
  873. asCArray<asDWORD> &bc = scriptData->byteCode;
  874. for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] )
  875. {
  876. switch( *(asBYTE*)&bc[n] )
  877. {
  878. // Object types
  879. case asBC_OBJTYPE:
  880. case asBC_FREE:
  881. case asBC_REFCPY:
  882. case asBC_RefCpyV:
  883. {
  884. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  885. objType->AddRef();
  886. }
  887. break;
  888. // Object type and function
  889. case asBC_ALLOC:
  890. {
  891. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  892. objType->AddRef();
  893. int func = asBC_INTARG(&bc[n]+AS_PTR_SIZE);
  894. if( func )
  895. engine->scriptFunctions[func]->AddRef();
  896. }
  897. break;
  898. // Global variables
  899. case asBC_PGA:
  900. case asBC_PshGPtr:
  901. case asBC_LDG:
  902. case asBC_PshG4:
  903. case asBC_LdGRdR4:
  904. case asBC_CpyGtoV4:
  905. case asBC_CpyVtoG4:
  906. case asBC_SetG4:
  907. // Need to increase the reference for each global variable
  908. {
  909. void *gvarPtr = (void*)asBC_PTRARG(&bc[n]);
  910. if( !gvarPtr ) break;
  911. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  912. if( !prop ) break;
  913. // Only addref the properties once
  914. if( !ptrs.Exists(gvarPtr) )
  915. {
  916. prop->AddRef();
  917. ptrs.PushLast(gvarPtr);
  918. }
  919. asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id);
  920. if( group != 0 ) group->AddRef();
  921. }
  922. break;
  923. // System functions
  924. case asBC_CALLSYS:
  925. {
  926. int funcId = asBC_INTARG(&bc[n]);
  927. asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
  928. if( group != 0 ) group->AddRef();
  929. engine->scriptFunctions[funcId]->AddRef();
  930. }
  931. break;
  932. // Functions
  933. case asBC_CALL:
  934. case asBC_CALLINTF:
  935. {
  936. int func = asBC_INTARG(&bc[n]);
  937. engine->scriptFunctions[func]->AddRef();
  938. }
  939. break;
  940. // Function pointers
  941. case asBC_FuncPtr:
  942. {
  943. asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]);
  944. func->AddRef();
  945. }
  946. break;
  947. }
  948. }
  949. }
  950. }
  951. // internal
  952. void asCScriptFunction::ReleaseReferences()
  953. {
  954. asCArray<void*> ptrs;
  955. // Only count references if there is any bytecode
  956. if( scriptData && scriptData->byteCode.GetLength() )
  957. {
  958. if( returnType.IsObject() )
  959. returnType.GetObjectType()->Release();
  960. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  961. if( parameterTypes[p].IsObject() )
  962. parameterTypes[p].GetObjectType()->Release();
  963. for( asUINT v = 0; v < scriptData->objVariableTypes.GetLength(); v++ )
  964. if( scriptData->objVariableTypes[v] )
  965. scriptData->objVariableTypes[v]->Release();
  966. // Go through the byte code and release references to all resources used by the function
  967. asCArray<asDWORD> &bc = scriptData->byteCode;
  968. for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] )
  969. {
  970. switch( *(asBYTE*)&bc[n] )
  971. {
  972. // Object types
  973. case asBC_OBJTYPE:
  974. case asBC_FREE:
  975. case asBC_REFCPY:
  976. case asBC_RefCpyV:
  977. {
  978. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  979. if( objType )
  980. objType->Release();
  981. }
  982. break;
  983. // Object type and function
  984. case asBC_ALLOC:
  985. {
  986. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  987. if( objType )
  988. objType->Release();
  989. int func = asBC_INTARG(&bc[n]+AS_PTR_SIZE);
  990. if( func )
  991. {
  992. asCScriptFunction *fptr = engine->scriptFunctions[func];
  993. if( fptr )
  994. fptr->Release();
  995. // The engine may have been forced to destroy the function internals early
  996. // and this may will make it impossible to find the function by id anymore.
  997. // This should only happen if the engine is released while the application
  998. // is still keeping functions alive.
  999. // TODO: Fix this possible memory leak
  1000. }
  1001. }
  1002. break;
  1003. // Global variables
  1004. case asBC_PGA:
  1005. case asBC_PshGPtr:
  1006. case asBC_LDG:
  1007. case asBC_PshG4:
  1008. case asBC_LdGRdR4:
  1009. case asBC_CpyGtoV4:
  1010. case asBC_CpyVtoG4:
  1011. case asBC_SetG4:
  1012. // Need to increase the reference for each global variable
  1013. {
  1014. void *gvarPtr = (void*)asBC_PTRARG(&bc[n]);
  1015. if( !gvarPtr ) break;
  1016. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  1017. if( !prop ) break;
  1018. // Only release the properties once
  1019. if( !ptrs.Exists(gvarPtr) )
  1020. {
  1021. prop->Release();
  1022. ptrs.PushLast(gvarPtr);
  1023. }
  1024. asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id);
  1025. if( group != 0 ) group->Release();
  1026. }
  1027. break;
  1028. // System functions
  1029. case asBC_CALLSYS:
  1030. {
  1031. int funcId = asBC_INTARG(&bc[n]);
  1032. asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
  1033. if( group != 0 ) group->Release();
  1034. if( funcId )
  1035. engine->scriptFunctions[funcId]->Release();
  1036. }
  1037. break;
  1038. // Functions
  1039. case asBC_CALL:
  1040. case asBC_CALLINTF:
  1041. {
  1042. int func = asBC_INTARG(&bc[n]);
  1043. if( func )
  1044. {
  1045. asCScriptFunction *fptr = engine->scriptFunctions[func];
  1046. if( fptr )
  1047. fptr->Release();
  1048. // The engine may have been forced to destroy the function internals early
  1049. // and this may will make it impossible to find the function by id anymore.
  1050. // This should only happen if the engine is released while the application
  1051. // is still keeping functions alive.
  1052. // TODO: Fix this possible memory leak
  1053. }
  1054. }
  1055. break;
  1056. // Function pointers
  1057. case asBC_FuncPtr:
  1058. {
  1059. asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]);
  1060. if( func )
  1061. func->Release();
  1062. }
  1063. break;
  1064. }
  1065. }
  1066. // Release the jit compiled function
  1067. if( scriptData->jitFunction )
  1068. engine->jitCompiler->ReleaseJITFunction(scriptData->jitFunction);
  1069. scriptData->jitFunction = 0;
  1070. }
  1071. // Delegate
  1072. if( objForDelegate )
  1073. engine->ReleaseScriptObject(objForDelegate, funcForDelegate->GetObjectType());
  1074. objForDelegate = 0;
  1075. if( funcForDelegate )
  1076. funcForDelegate->Release();
  1077. funcForDelegate = 0;
  1078. }
  1079. // interface
  1080. int asCScriptFunction::GetReturnTypeId(asDWORD *flags) const
  1081. {
  1082. if( flags )
  1083. {
  1084. if( returnType.IsReference() )
  1085. {
  1086. *flags = asTM_INOUTREF;
  1087. *flags |= returnType.IsReadOnly() ? asTM_CONST : 0;
  1088. }
  1089. else
  1090. *flags = asTM_NONE;
  1091. }
  1092. return engine->GetTypeIdFromDataType(returnType);
  1093. }
  1094. // interface
  1095. asUINT asCScriptFunction::GetParamCount() const
  1096. {
  1097. return (asUINT)parameterTypes.GetLength();
  1098. }
  1099. // interface
  1100. int asCScriptFunction::GetParam(asUINT index, int *typeId, asDWORD *flags, const char **name, const char **defaultArg) const
  1101. {
  1102. if( index >= parameterTypes.GetLength() )
  1103. return asINVALID_ARG;
  1104. if( typeId )
  1105. *typeId = engine->GetTypeIdFromDataType(parameterTypes[index]);
  1106. if( flags )
  1107. {
  1108. *flags = inOutFlags[index];
  1109. *flags |= parameterTypes[index].IsReadOnly() ? asTM_CONST : 0;
  1110. }
  1111. if( name )
  1112. {
  1113. // The parameter names are not stored if loading from bytecode without debug information
  1114. if( index < parameterNames.GetLength() )
  1115. *name = parameterNames[index].AddressOf();
  1116. else
  1117. *name = 0;
  1118. }
  1119. if( defaultArg )
  1120. {
  1121. if( index < defaultArgs.GetLength() && defaultArgs[index] )
  1122. *defaultArg = defaultArgs[index]->AddressOf();
  1123. else
  1124. *defaultArg = 0;
  1125. }
  1126. return asSUCCESS;
  1127. }
  1128. #ifdef AS_DEPRECATED
  1129. // Deprecated since 2014-04-06, 2.29.0
  1130. int asCScriptFunction::GetParamTypeId(asUINT index, asDWORD *flags) const
  1131. {
  1132. if( index >= parameterTypes.GetLength() )
  1133. return asINVALID_ARG;
  1134. if( flags )
  1135. {
  1136. *flags = inOutFlags[index];
  1137. *flags |= parameterTypes[index].IsReadOnly() ? asTM_CONST : 0;
  1138. }
  1139. return engine->GetTypeIdFromDataType(parameterTypes[index]);
  1140. }
  1141. #endif
  1142. // interface
  1143. asIScriptEngine *asCScriptFunction::GetEngine() const
  1144. {
  1145. return engine;
  1146. }
  1147. // interface
  1148. const char *asCScriptFunction::GetDeclaration(bool includeObjectName, bool includeNamespace, bool includeParamNames) const
  1149. {
  1150. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  1151. *tempString = GetDeclarationStr(includeObjectName, includeNamespace, includeParamNames);
  1152. return tempString->AddressOf();
  1153. }
  1154. // interface
  1155. const char *asCScriptFunction::GetScriptSectionName() const
  1156. {
  1157. if( scriptData && scriptData->scriptSectionIdx >= 0 )
  1158. return engine->scriptSectionNames[scriptData->scriptSectionIdx]->AddressOf();
  1159. return 0;
  1160. }
  1161. // interface
  1162. const char *asCScriptFunction::GetConfigGroup() const
  1163. {
  1164. asCConfigGroup *group = 0;
  1165. if( funcType != asFUNC_FUNCDEF )
  1166. group = engine->FindConfigGroupForFunction(id);
  1167. else
  1168. group = engine->FindConfigGroupForFuncDef(this);
  1169. if( group == 0 )
  1170. return 0;
  1171. return group->groupName.AddressOf();
  1172. }
  1173. // interface
  1174. asDWORD asCScriptFunction::GetAccessMask() const
  1175. {
  1176. return accessMask;
  1177. }
  1178. // internal
  1179. void asCScriptFunction::JITCompile()
  1180. {
  1181. if( funcType != asFUNC_SCRIPT )
  1182. return;
  1183. asASSERT( scriptData );
  1184. asIJITCompiler *jit = engine->GetJITCompiler();
  1185. if( !jit )
  1186. return;
  1187. // Make sure the function has been compiled with JitEntry instructions
  1188. // For functions that has JitEntry this will be a quick test
  1189. asUINT length;
  1190. asDWORD *byteCode = GetByteCode(&length);
  1191. asDWORD *end = byteCode + length;
  1192. bool foundJitEntry = false;
  1193. while( byteCode < end )
  1194. {
  1195. // Determine the instruction
  1196. asEBCInstr op = asEBCInstr(*(asBYTE*)byteCode);
  1197. if( op == asBC_JitEntry )
  1198. {
  1199. foundJitEntry = true;
  1200. break;
  1201. }
  1202. // Move to next instruction
  1203. byteCode += asBCTypeSize[asBCInfo[op].type];
  1204. }
  1205. if( !foundJitEntry )
  1206. {
  1207. asCString msg;
  1208. msg.Format(TXT_NO_JIT_IN_FUNC_s, GetDeclaration());
  1209. engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  1210. }
  1211. // Release the previous function, if any
  1212. if( scriptData->jitFunction )
  1213. {
  1214. engine->jitCompiler->ReleaseJITFunction(scriptData->jitFunction);
  1215. scriptData->jitFunction = 0;
  1216. }
  1217. // Compile for native system
  1218. int r = jit->CompileFunction(this, &scriptData->jitFunction);
  1219. if( r < 0 )
  1220. asASSERT( scriptData->jitFunction == 0 );
  1221. }
  1222. // interface
  1223. asDWORD *asCScriptFunction::GetByteCode(asUINT *length)
  1224. {
  1225. if( scriptData == 0 ) return 0;
  1226. if( length )
  1227. *length = (asUINT)scriptData->byteCode.GetLength();
  1228. if( scriptData->byteCode.GetLength() )
  1229. return scriptData->byteCode.AddressOf();
  1230. return 0;
  1231. }
  1232. // interface
  1233. void *asCScriptFunction::SetUserData(void *data, asPWORD type)
  1234. {
  1235. // As a thread might add a new new user data at the same time as another
  1236. // it is necessary to protect both read and write access to the userData member
  1237. ACQUIREEXCLUSIVE(engine->engineRWLock);
  1238. // It is not intended to store a lot of different types of userdata,
  1239. // so a more complex structure like a associative map would just have
  1240. // more overhead than a simple array.
  1241. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  1242. {
  1243. if( userData[n] == type )
  1244. {
  1245. void *oldData = reinterpret_cast<void*>(userData[n+1]);
  1246. userData[n+1] = reinterpret_cast<asPWORD>(data);
  1247. RELEASEEXCLUSIVE(engine->engineRWLock);
  1248. return oldData;
  1249. }
  1250. }
  1251. userData.PushLast(type);
  1252. userData.PushLast(reinterpret_cast<asPWORD>(data));
  1253. RELEASEEXCLUSIVE(engine->engineRWLock);
  1254. return 0;
  1255. }
  1256. // interface
  1257. void *asCScriptFunction::GetUserData(asPWORD type) const
  1258. {
  1259. // There may be multiple threads reading, but when
  1260. // setting the user data nobody must be reading.
  1261. ACQUIRESHARED(engine->engineRWLock);
  1262. for( asUINT n = 0; n < userData.GetLength(); n += 2 )
  1263. {
  1264. if( userData[n] == type )
  1265. {
  1266. RELEASESHARED(engine->engineRWLock);
  1267. return reinterpret_cast<void*>(userData[n+1]);
  1268. }
  1269. }
  1270. RELEASESHARED(engine->engineRWLock);
  1271. return 0;
  1272. }
  1273. // internal
  1274. // TODO: cleanup: This method should probably be a member of the engine
  1275. asCGlobalProperty *asCScriptFunction::GetPropertyByGlobalVarPtr(void *gvarPtr)
  1276. {
  1277. asSMapNode<void*, asCGlobalProperty*> *node;
  1278. if( engine->varAddressMap.MoveTo(&node, gvarPtr) )
  1279. {
  1280. asASSERT(gvarPtr == node->value->GetAddressOfValue());
  1281. return node->value;
  1282. }
  1283. return 0;
  1284. }
  1285. // internal
  1286. int asCScriptFunction::GetRefCount()
  1287. {
  1288. return refCount.get();
  1289. }
  1290. // internal
  1291. void asCScriptFunction::SetFlag()
  1292. {
  1293. gcFlag = true;
  1294. }
  1295. // internal
  1296. bool asCScriptFunction::GetFlag()
  1297. {
  1298. return gcFlag;
  1299. }
  1300. // internal
  1301. void asCScriptFunction::EnumReferences(asIScriptEngine *)
  1302. {
  1303. // Notify the GC of all object types used
  1304. if( returnType.IsObject() )
  1305. engine->GCEnumCallback(returnType.GetObjectType());
  1306. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  1307. if( parameterTypes[p].IsObject() )
  1308. engine->GCEnumCallback(parameterTypes[p].GetObjectType());
  1309. if( scriptData )
  1310. {
  1311. for( asUINT t = 0; t < scriptData->objVariableTypes.GetLength(); t++ )
  1312. engine->GCEnumCallback(scriptData->objVariableTypes[t]);
  1313. // Notify the GC of all script functions that is accessed
  1314. asCArray<asDWORD> &bc = scriptData->byteCode;
  1315. for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] )
  1316. {
  1317. switch( *(asBYTE*)&bc[n] )
  1318. {
  1319. case asBC_OBJTYPE:
  1320. case asBC_FREE:
  1321. case asBC_REFCPY:
  1322. case asBC_RefCpyV:
  1323. {
  1324. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  1325. engine->GCEnumCallback(objType);
  1326. }
  1327. break;
  1328. case asBC_ALLOC:
  1329. {
  1330. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  1331. engine->GCEnumCallback(objType);
  1332. int func = asBC_INTARG(&bc[n]+AS_PTR_SIZE);
  1333. if( func )
  1334. engine->GCEnumCallback(engine->scriptFunctions[func]);
  1335. }
  1336. break;
  1337. case asBC_CALL:
  1338. case asBC_CALLINTF:
  1339. {
  1340. int func = asBC_INTARG(&bc[n]);
  1341. if( func )
  1342. engine->GCEnumCallback(engine->scriptFunctions[func]);
  1343. }
  1344. break;
  1345. // Function pointers
  1346. case asBC_FuncPtr:
  1347. {
  1348. asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]);
  1349. if( func )
  1350. engine->GCEnumCallback(func);
  1351. }
  1352. break;
  1353. // Global variables
  1354. case asBC_PGA:
  1355. case asBC_PshGPtr:
  1356. case asBC_LDG:
  1357. case asBC_PshG4:
  1358. case asBC_LdGRdR4:
  1359. case asBC_CpyGtoV4:
  1360. case asBC_CpyVtoG4:
  1361. case asBC_SetG4:
  1362. // Need to enumerate the reference for each global variable
  1363. {
  1364. // TODO: optimize: Keep an array of accessed global properties
  1365. void *gvarPtr = (void*)asBC_PTRARG(&bc[n]);
  1366. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  1367. engine->GCEnumCallback(prop);
  1368. }
  1369. break;
  1370. }
  1371. }
  1372. }
  1373. // Delegate
  1374. if( objForDelegate )
  1375. engine->GCEnumCallback(objForDelegate);
  1376. if( funcForDelegate )
  1377. engine->GCEnumCallback(funcForDelegate);
  1378. }
  1379. // internal
  1380. void asCScriptFunction::ReleaseAllHandles(asIScriptEngine *)
  1381. {
  1382. // Release paramaters
  1383. if( scriptData && scriptData->byteCode.GetLength() )
  1384. {
  1385. if( returnType.IsObject() )
  1386. {
  1387. returnType.GetObjectType()->Release();
  1388. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  1389. }
  1390. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  1391. if( parameterTypes[p].IsObject() )
  1392. {
  1393. parameterTypes[p].GetObjectType()->Release();
  1394. parameterTypes[p] = asCDataType::CreatePrimitive(ttInt, false);
  1395. }
  1396. for( asUINT n = 0; n < scriptData->objVariableTypes.GetLength(); n++ )
  1397. if( scriptData->objVariableTypes[n] ) // Null handle is also stored, but it doesn't have an object type
  1398. scriptData->objVariableTypes[n]->Release();
  1399. scriptData->objVariableTypes.SetLength(0);
  1400. // Release all script functions
  1401. asCArray<asDWORD> &bc = scriptData->byteCode;
  1402. for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] )
  1403. {
  1404. switch( *(asBYTE*)&bc[n] )
  1405. {
  1406. // Object types
  1407. case asBC_OBJTYPE:
  1408. case asBC_FREE:
  1409. case asBC_REFCPY:
  1410. case asBC_RefCpyV:
  1411. {
  1412. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  1413. if( objType )
  1414. {
  1415. objType->Release();
  1416. *(asPWORD*)&bc[n+1] = 0;
  1417. }
  1418. }
  1419. break;
  1420. case asBC_ALLOC:
  1421. {
  1422. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  1423. if( objType )
  1424. {
  1425. objType->Release();
  1426. *(asPWORD*)&bc[n+1] = 0;
  1427. }
  1428. int func = asBC_INTARG(&bc[n]+AS_PTR_SIZE);
  1429. if( func )
  1430. {
  1431. engine->scriptFunctions[func]->Release();
  1432. bc[n+AS_PTR_SIZE+1] = 0;
  1433. }
  1434. }
  1435. break;
  1436. case asBC_CALL:
  1437. case asBC_CALLINTF:
  1438. {
  1439. int func = asBC_INTARG(&bc[n]);
  1440. if( func )
  1441. {
  1442. engine->scriptFunctions[func]->Release();
  1443. bc[n+1] = 0;
  1444. }
  1445. }
  1446. break;
  1447. // Function pointers
  1448. case asBC_FuncPtr:
  1449. {
  1450. asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]);
  1451. if( func )
  1452. {
  1453. func->Release();
  1454. *(asPWORD*)&bc[n+1] = 0;
  1455. }
  1456. }
  1457. break;
  1458. // The global variables are not released here. It is enough that the global
  1459. // variable itself release the function to break the circle
  1460. }
  1461. }
  1462. }
  1463. // Delegate
  1464. if( objForDelegate )
  1465. engine->ReleaseScriptObject(objForDelegate, funcForDelegate->GetObjectType());
  1466. objForDelegate = 0;
  1467. if( funcForDelegate )
  1468. funcForDelegate->Release();
  1469. funcForDelegate = 0;
  1470. }
  1471. // internal
  1472. bool asCScriptFunction::IsShared() const
  1473. {
  1474. // All system functions are shared
  1475. if( funcType == asFUNC_SYSTEM ) return true;
  1476. // All class methods for shared classes are also shared
  1477. if( objectType && (objectType->flags & asOBJ_SHARED) ) return true;
  1478. // Functions that have been specifically marked as shared are shared
  1479. return isShared;
  1480. }
  1481. // internal
  1482. bool asCScriptFunction::IsFinal() const
  1483. {
  1484. return isFinal;
  1485. }
  1486. // internal
  1487. bool asCScriptFunction::IsOverride() const
  1488. {
  1489. return isOverride;
  1490. }
  1491. END_AS_NAMESPACE