as_scriptfunction.cpp 42 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2013 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. BEGIN_AS_NAMESPACE
  39. #ifdef AS_MAX_PORTABILITY
  40. static void ScriptFunction_AddRef_Generic(asIScriptGeneric *gen)
  41. {
  42. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  43. self->AddRef();
  44. }
  45. static void ScriptFunction_Release_Generic(asIScriptGeneric *gen)
  46. {
  47. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  48. self->Release();
  49. }
  50. static void ScriptFunction_GetRefCount_Generic(asIScriptGeneric *gen)
  51. {
  52. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  53. *(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount();
  54. }
  55. static void ScriptFunction_SetFlag_Generic(asIScriptGeneric *gen)
  56. {
  57. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  58. self->SetFlag();
  59. }
  60. static void ScriptFunction_GetFlag_Generic(asIScriptGeneric *gen)
  61. {
  62. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  63. *(bool*)gen->GetAddressOfReturnLocation() = self->GetFlag();
  64. }
  65. static void ScriptFunction_EnumReferences_Generic(asIScriptGeneric *gen)
  66. {
  67. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  68. asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
  69. self->EnumReferences(engine);
  70. }
  71. static void ScriptFunction_ReleaseAllHandles_Generic(asIScriptGeneric *gen)
  72. {
  73. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  74. asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
  75. self->ReleaseAllHandles(engine);
  76. }
  77. static void ScriptFunction_CreateDelegate_Generic(asIScriptGeneric *gen)
  78. {
  79. asCScriptFunction *func = (asCScriptFunction*)gen->GetArgAddress(0);
  80. void *obj = gen->GetArgAddress(1);
  81. gen->SetReturnAddress(CreateDelegate(func, obj));
  82. }
  83. #endif
  84. void RegisterScriptFunction(asCScriptEngine *engine)
  85. {
  86. // Register the gc behaviours for the script functions
  87. int r = 0;
  88. UNUSED_VAR(r); // It is only used in debug mode
  89. engine->functionBehaviours.engine = engine;
  90. engine->functionBehaviours.flags = asOBJ_REF | asOBJ_GC | asOBJ_SCRIPT_FUNCTION;
  91. engine->functionBehaviours.name = "_builtin_function_";
  92. #ifndef AS_MAX_PORTABILITY
  93. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCScriptFunction,AddRef), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  94. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCScriptFunction,Release), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  95. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCScriptFunction,GetRefCount), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  96. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCScriptFunction,SetFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  97. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCScriptFunction,GetFlag), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  98. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCScriptFunction,EnumReferences), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  99. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCScriptFunction,ReleaseAllHandles), asCALL_THISCALL, 0); asASSERT( r >= 0 );
  100. #else
  101. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptFunction_AddRef_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  102. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptFunction_Release_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  103. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptFunction_GetRefCount_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  104. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptFunction_SetFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  105. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptFunction_GetFlag_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  106. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptFunction_EnumReferences_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  107. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptFunction_ReleaseAllHandles_Generic), asCALL_GENERIC, 0); asASSERT( r >= 0 );
  108. #endif
  109. // Register the builtin function for creating delegates
  110. // This function returns a handle to the delegate, but since the type is not known at this time it is
  111. // registered to return a void then the return type is changed manually to the builtin function type
  112. // The name of the function is an invalid identifier so it cannot be invoked accidentally from the script
  113. #ifndef AS_MAX_PORTABILITY
  114. r = engine->RegisterGlobalFunction("void f(int &in, int &in)", asFUNCTION(CreateDelegate), asCALL_CDECL); asASSERT( r >= 0 );
  115. #else
  116. r = engine->RegisterGlobalFunction("void f(int &in, int &in)", asFUNCTION(ScriptFunction_CreateDelegate_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  117. #endif
  118. // Change the return type so the VM will know the function really returns a handle
  119. engine->scriptFunctions[r]->name = DELEGATE_FACTORY;
  120. engine->scriptFunctions[r]->returnType = asCDataType::CreateObject(&engine->functionBehaviours, false);
  121. engine->scriptFunctions[r]->returnType.MakeHandle(true);
  122. }
  123. asCScriptFunction *CreateDelegate(asCScriptFunction *func, void *obj)
  124. {
  125. if( func == 0 || obj == 0 )
  126. {
  127. // TODO: delegate: Should set script exception
  128. return 0;
  129. }
  130. // Create an instance of a asCScriptFunction with the type asFUNC_DELEGATE
  131. // The delegate shouldn't have a function id and is not added to the engine->scriptFunctions
  132. asCScriptFunction *delegate = asNEW(asCScriptFunction)(static_cast<asCScriptEngine*>(func->GetEngine()), 0, asFUNC_DELEGATE);
  133. if( delegate )
  134. delegate->MakeDelegate(func, obj);
  135. return delegate;
  136. }
  137. // internal
  138. void asCScriptFunction::MakeDelegate(asCScriptFunction *func, void *obj)
  139. {
  140. // Increase the reference of the function and object
  141. func->AddRef();
  142. funcForDelegate = func;
  143. func->GetEngine()->AddRefScriptObject(obj, func->GetObjectType());
  144. objForDelegate = obj;
  145. // The return type and parameters are copied from the delegated method to this object
  146. // TODO: optimize: Do we really need to copy? Whenever requested the delegate can simply return the delegated methods' info directly
  147. parameterTypes = func->parameterTypes;
  148. returnType = func->returnType;
  149. inOutFlags = func->inOutFlags;
  150. // The delegate doesn't own the parameters as it will only forward them to the real method
  151. // so the exception handler must not clean up the parameters for the delegate
  152. dontCleanUpOnException = true;
  153. }
  154. // interface
  155. void *asCScriptFunction::GetDelegateObject() const
  156. {
  157. return objForDelegate;
  158. }
  159. // interface
  160. asIObjectType *asCScriptFunction::GetDelegateObjectType() const
  161. {
  162. if( objForDelegate == 0 || funcForDelegate == 0 )
  163. return 0;
  164. return funcForDelegate->objectType;
  165. }
  166. // interface
  167. asIScriptFunction *asCScriptFunction::GetDelegateFunction() const
  168. {
  169. return funcForDelegate;
  170. }
  171. // internal
  172. int asCScriptFunction::RegisterListPattern(const char *decl, asCScriptNode *listNodes)
  173. {
  174. if( listNodes == 0 )
  175. return asINVALID_ARG;
  176. // Build the representation of the list pattern from the script nodes
  177. asSListPatternNode *node;
  178. listPattern = asNEW(asSListPatternNode)(asLPT_START);
  179. node = listPattern;
  180. // Recursively parse the child
  181. int r = ParseListPattern(node, decl, listNodes);
  182. node->next = asNEW(asSListPatternNode)(asLPT_END);
  183. return r;
  184. }
  185. // internal
  186. int asCScriptFunction::ParseListPattern(asSListPatternNode *&target, const char *decl, asCScriptNode *listNodes)
  187. {
  188. asSListPatternNode *node = target;
  189. listNodes = listNodes->firstChild;
  190. while( listNodes )
  191. {
  192. if( listNodes->nodeType == snIdentifier )
  193. {
  194. node->next = asNEW(asSListPatternNode)(asLPT_REPEAT);
  195. node = node->next;
  196. }
  197. else if( listNodes->nodeType == snDataType )
  198. {
  199. asCDataType dt;
  200. asCBuilder builder(engine, 0);
  201. asCScriptCode code;
  202. code.SetCode("", decl, 0, false);
  203. dt = builder.CreateDataTypeFromNode(listNodes, &code, engine->defaultNamespace, false, returnType.GetObjectType());
  204. node->next = asNEW(asSListPatternDataTypeNode)(dt);
  205. node = node->next;
  206. }
  207. else if( listNodes->nodeType == snListPattern )
  208. {
  209. node->next = asNEW(asSListPatternNode)(asLPT_START);
  210. node = node->next;
  211. // Recursively parse the child
  212. int r = ParseListPattern(node, decl, listNodes);
  213. if( r < 0 )
  214. return r;
  215. node->next = asNEW(asSListPatternNode)(asLPT_END);
  216. node = node->next;
  217. }
  218. else
  219. {
  220. // Unexpected token in the list, the parser shouldn't have allowed
  221. asASSERT( false );
  222. return -1;
  223. }
  224. listNodes = listNodes->next;
  225. }
  226. target = node;
  227. return 0;
  228. }
  229. // internal
  230. asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, asEFuncType _funcType)
  231. {
  232. refCount.set(1);
  233. this->engine = engine;
  234. this->scriptData = 0;
  235. funcType = _funcType;
  236. module = mod;
  237. objectType = 0;
  238. name = "";
  239. isReadOnly = false;
  240. isPrivate = false;
  241. isFinal = false;
  242. isOverride = false;
  243. sysFuncIntf = 0;
  244. signatureId = 0;
  245. dontCleanUpOnException = false;
  246. vfTableIdx = -1;
  247. gcFlag = false;
  248. userData = 0;
  249. id = 0;
  250. accessMask = 0xFFFFFFFF;
  251. isShared = false;
  252. nameSpace = engine->nameSpaces[0];
  253. objForDelegate = 0;
  254. funcForDelegate = 0;
  255. listPattern = 0;
  256. if( funcType == asFUNC_SCRIPT )
  257. AllocateScriptFunctionData();
  258. // Notify the GC of script functions
  259. if( (funcType == asFUNC_SCRIPT && mod == 0) || (funcType == asFUNC_DELEGATE) )
  260. engine->gc.AddScriptObjectToGC(this, &engine->functionBehaviours);
  261. }
  262. void asCScriptFunction::AllocateScriptFunctionData()
  263. {
  264. if( scriptData ) return;
  265. scriptData = asNEW(ScriptFunctionData);
  266. scriptData->stackNeeded = 0;
  267. scriptData->variableSpace = 0;
  268. scriptData->scriptSectionIdx = -1;
  269. scriptData->jitFunction = 0;
  270. }
  271. void asCScriptFunction::DeallocateScriptFunctionData()
  272. {
  273. if( !scriptData ) return;
  274. for( asUINT n = 0; n < scriptData->variables.GetLength(); n++ )
  275. asDELETE(scriptData->variables[n],asSScriptVariable);
  276. scriptData->variables.SetLength(0);
  277. asDELETE(scriptData, ScriptFunctionData);
  278. scriptData = 0;
  279. }
  280. // internal
  281. asCScriptFunction::~asCScriptFunction()
  282. {
  283. // Imported functions are not reference counted, nor are dummy
  284. // functions that are allocated on the stack
  285. asASSERT( funcType == asFUNC_DUMMY ||
  286. funcType == asFUNC_IMPORTED ||
  287. refCount.get() == 0 );
  288. // If the engine pointer is 0, then DestroyInternal has already been called and there is nothing more to do
  289. if( engine == 0 ) return;
  290. DestroyInternal();
  291. // Tell engine to free the function id. This will make it impossible to
  292. // refer to the function by id. Where this is done, it is quite possible
  293. // they will leak.
  294. if( funcType != -1 && funcType != asFUNC_IMPORTED && id )
  295. engine->FreeScriptFunctionId(id);
  296. id = 0;
  297. // Finally set the engine pointer to 0 because it must not be accessed again
  298. engine = 0;
  299. }
  300. // internal
  301. void asCScriptFunction::DestroyInternal()
  302. {
  303. // Clean up user data
  304. if( userData && engine->cleanFunctionFunc )
  305. engine->cleanFunctionFunc(this);
  306. userData = 0;
  307. // Release all references the function holds to other objects
  308. ReleaseReferences();
  309. parameterTypes.SetLength(0);
  310. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  311. for( asUINT p = 0; p < defaultArgs.GetLength(); p++ )
  312. if( defaultArgs[p] )
  313. asDELETE(defaultArgs[p], asCString);
  314. defaultArgs.SetLength(0);
  315. if( sysFuncIntf )
  316. asDELETE(sysFuncIntf,asSSystemFunctionInterface);
  317. sysFuncIntf = 0;
  318. DeallocateScriptFunctionData();
  319. // Deallocate list pattern data
  320. while( listPattern )
  321. {
  322. asSListPatternNode *n = listPattern->next;
  323. asDELETE(listPattern, asSListPatternNode);
  324. listPattern = n;
  325. }
  326. }
  327. // interface
  328. int asCScriptFunction::GetId() const
  329. {
  330. return id;
  331. }
  332. // interface
  333. int asCScriptFunction::AddRef() const
  334. {
  335. gcFlag = false;
  336. asASSERT( funcType != asFUNC_IMPORTED );
  337. return refCount.atomicInc();
  338. }
  339. // interface
  340. int asCScriptFunction::Release() const
  341. {
  342. gcFlag = false;
  343. asASSERT( funcType != asFUNC_IMPORTED );
  344. int r = refCount.atomicDec();
  345. if( r == 0 &&
  346. funcType != asFUNC_FUNCDEF && // Funcdefs are treated as object types and will be deleted by ClearUnusedTypes()
  347. funcType != asFUNC_DUMMY ) // Dummy functions are allocated on the stack and cannot be deleted
  348. asDELETE(const_cast<asCScriptFunction*>(this),asCScriptFunction);
  349. return r;
  350. }
  351. // internal
  352. void asCScriptFunction::Orphan(asIScriptModule *mod)
  353. {
  354. if( mod && module == mod )
  355. {
  356. module = 0;
  357. if( funcType == asFUNC_SCRIPT && refCount.get() > 1 )
  358. {
  359. // This function is being orphaned, so notify the GC so it can check for circular references
  360. engine->gc.AddScriptObjectToGC(this, &engine->functionBehaviours);
  361. }
  362. }
  363. Release();
  364. }
  365. // interface
  366. int asCScriptFunction::GetTypeId() const
  367. {
  368. // This const cast is ok, the object won't be modified
  369. asCDataType dt = asCDataType::CreateFuncDef(const_cast<asCScriptFunction*>(this));
  370. return engine->GetTypeIdFromDataType(dt);
  371. }
  372. // interface
  373. bool asCScriptFunction::IsCompatibleWithTypeId(int typeId) const
  374. {
  375. asCDataType dt = engine->GetDataTypeFromTypeId(typeId);
  376. // Make sure the type is a function
  377. asCScriptFunction *func = dt.GetFuncDef();
  378. if( func == 0 )
  379. return false;
  380. if( !IsSignatureExceptNameEqual(func) )
  381. return false;
  382. // If this is a class method, then only return true if the object type is the same
  383. if( objectType != func->objectType )
  384. return false;
  385. return true;
  386. }
  387. // interface
  388. const char *asCScriptFunction::GetModuleName() const
  389. {
  390. if( module )
  391. {
  392. return module->name.AddressOf();
  393. }
  394. return 0;
  395. }
  396. // interface
  397. asIScriptModule *asCScriptFunction::GetModule() const
  398. {
  399. return module;
  400. }
  401. // interface
  402. asIObjectType *asCScriptFunction::GetObjectType() const
  403. {
  404. return objectType;
  405. }
  406. // interface
  407. const char *asCScriptFunction::GetObjectName() const
  408. {
  409. if( objectType )
  410. return objectType->GetName();
  411. return 0;
  412. }
  413. // interface
  414. const char *asCScriptFunction::GetName() const
  415. {
  416. return name.AddressOf();
  417. }
  418. // interface
  419. const char *asCScriptFunction::GetNamespace() const
  420. {
  421. return nameSpace->name.AddressOf();
  422. }
  423. // interface
  424. bool asCScriptFunction::IsReadOnly() const
  425. {
  426. return isReadOnly;
  427. }
  428. // interface
  429. bool asCScriptFunction::IsPrivate() const
  430. {
  431. return isPrivate;
  432. }
  433. // internal
  434. int asCScriptFunction::GetSpaceNeededForArguments()
  435. {
  436. // We need to check the size for each type
  437. int s = 0;
  438. for( asUINT n = 0; n < parameterTypes.GetLength(); n++ )
  439. s += parameterTypes[n].GetSizeOnStackDWords();
  440. return s;
  441. }
  442. // internal
  443. int asCScriptFunction::GetSpaceNeededForReturnValue()
  444. {
  445. return returnType.GetSizeOnStackDWords();
  446. }
  447. // internal
  448. bool asCScriptFunction::DoesReturnOnStack() const
  449. {
  450. if( returnType.GetObjectType() &&
  451. (returnType.GetObjectType()->flags & asOBJ_VALUE) &&
  452. !returnType.IsReference() )
  453. return true;
  454. return false;
  455. }
  456. // internal
  457. asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName, bool includeNamespace) const
  458. {
  459. asCString str;
  460. // TODO: default arg: Make the declaration with the default args an option
  461. // Don't add the return type for constructors and destructors
  462. if( !(returnType.GetTokenType() == ttVoid &&
  463. objectType &&
  464. (name == objectType->name || (name.GetLength() > 0 && name[0] == '~'))) )
  465. {
  466. str = returnType.Format();
  467. str += " ";
  468. }
  469. if( objectType && includeObjectName )
  470. {
  471. if( includeNamespace )
  472. str += objectType->nameSpace->name + "::";
  473. if( objectType->name != "" )
  474. str += objectType->name + "::";
  475. else
  476. str += "_unnamed_type_::";
  477. }
  478. else if( includeNamespace )
  479. {
  480. str += nameSpace->name + "::";
  481. }
  482. if( name == "" )
  483. str += "_unnamed_function_(";
  484. else
  485. str += name + "(";
  486. if( parameterTypes.GetLength() > 0 )
  487. {
  488. asUINT n;
  489. for( n = 0; n < parameterTypes.GetLength() - 1; n++ )
  490. {
  491. str += parameterTypes[n].Format();
  492. if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
  493. {
  494. if( inOutFlags[n] == asTM_INREF ) str += "in";
  495. else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
  496. else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
  497. }
  498. if( defaultArgs.GetLength() > n && defaultArgs[n] )
  499. {
  500. asCString tmp;
  501. tmp.Format(" = %s", defaultArgs[n]->AddressOf());
  502. str += tmp;
  503. }
  504. str += ", ";
  505. }
  506. // Add the last parameter
  507. str += parameterTypes[n].Format();
  508. if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
  509. {
  510. if( inOutFlags[n] == asTM_INREF ) str += "in";
  511. else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
  512. else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
  513. }
  514. if( defaultArgs.GetLength() > n && defaultArgs[n] )
  515. {
  516. asCString tmp;
  517. tmp.Format(" = %s", defaultArgs[n]->AddressOf());
  518. str += tmp;
  519. }
  520. }
  521. str += ")";
  522. if( isReadOnly )
  523. str += " const";
  524. // Add the declaration of the list pattern
  525. if( listPattern )
  526. {
  527. asSListPatternNode *n = listPattern;
  528. while( n )
  529. {
  530. if( n->type == asLPT_START )
  531. str += " {";
  532. else if( n->type == asLPT_END )
  533. str += " }";
  534. else if( n->type == asLPT_REPEAT )
  535. str += " repeat";
  536. else if( n->type == asLPT_TYPE )
  537. {
  538. str += " ";
  539. str += reinterpret_cast<asSListPatternDataTypeNode*>(n)->dataType.Format();
  540. }
  541. n = n->next;
  542. }
  543. }
  544. return str;
  545. }
  546. // interface
  547. int asCScriptFunction::FindNextLineWithCode(int line) const
  548. {
  549. if( scriptData == 0 ) return -1;
  550. if( scriptData->lineNumbers.GetLength() == 0 ) return -1;
  551. // Check if given line is outside function
  552. // TODO: should start at declaration instead of first line of code
  553. if( line < (scriptData->lineNumbers[1]&0xFFFFF) ) return -1;
  554. if( line > (scriptData->lineNumbers[scriptData->lineNumbers.GetLength()-1]&0xFFFFF) ) return -1;
  555. // Find the line with code on or right after the input line
  556. // TODO: optimize: Do binary search instead
  557. if( line == (scriptData->lineNumbers[1]&0xFFFFF) ) return line;
  558. for( asUINT n = 3; n < scriptData->lineNumbers.GetLength(); n += 2 )
  559. {
  560. if( line <= (scriptData->lineNumbers[n]&0xFFFFF) )
  561. return (scriptData->lineNumbers[n]&0xFFFFF);
  562. }
  563. return -1;
  564. }
  565. // internal
  566. int asCScriptFunction::GetLineNumber(int programPosition, int *sectionIdx)
  567. {
  568. asASSERT( scriptData );
  569. if( sectionIdx ) *sectionIdx = scriptData->scriptSectionIdx;
  570. if( scriptData->lineNumbers.GetLength() == 0 ) return 0;
  571. if( sectionIdx )
  572. {
  573. // Find the correct section index if the function is compiled from multiple sections
  574. // This array will be empty most of the time so we don't need a sofisticated algorithm to search it
  575. for( asUINT n = 0; n < scriptData->sectionIdxs.GetLength(); n += 2 )
  576. {
  577. if( scriptData->sectionIdxs[n] <= programPosition )
  578. *sectionIdx = scriptData->sectionIdxs[n+1];
  579. }
  580. }
  581. // Do a binary search in the buffer
  582. int max = (int)scriptData->lineNumbers.GetLength()/2 - 1;
  583. int min = 0;
  584. int i = max/2;
  585. for(;;)
  586. {
  587. if( scriptData->lineNumbers[i*2] < programPosition )
  588. {
  589. // Have we found the largest number < programPosition?
  590. if( max == i ) return scriptData->lineNumbers[i*2+1];
  591. if( scriptData->lineNumbers[i*2+2] > programPosition ) return scriptData->lineNumbers[i*2+1];
  592. min = i + 1;
  593. i = (max + min)/2;
  594. }
  595. else if( scriptData->lineNumbers[i*2] > programPosition )
  596. {
  597. // Have we found the smallest number > programPosition?
  598. if( min == i ) return scriptData->lineNumbers[i*2+1];
  599. max = i - 1;
  600. i = (max + min)/2;
  601. }
  602. else
  603. {
  604. // We found the exact position
  605. return scriptData->lineNumbers[i*2+1];
  606. }
  607. }
  608. }
  609. // interface
  610. asEFuncType asCScriptFunction::GetFuncType() const
  611. {
  612. return funcType;
  613. }
  614. // interface
  615. asUINT asCScriptFunction::GetVarCount() const
  616. {
  617. if( scriptData )
  618. return asUINT(scriptData->variables.GetLength());
  619. return 0;
  620. }
  621. // interface
  622. int asCScriptFunction::GetVar(asUINT index, const char **name, int *typeId) const
  623. {
  624. if( scriptData == 0 )
  625. return asNOT_SUPPORTED;
  626. if( index >= scriptData->variables.GetLength() )
  627. return asINVALID_ARG;
  628. if( name )
  629. *name = scriptData->variables[index]->name.AddressOf();
  630. if( typeId )
  631. *typeId = engine->GetTypeIdFromDataType(scriptData->variables[index]->type);
  632. return asSUCCESS;
  633. }
  634. // interface
  635. const char *asCScriptFunction::GetVarDecl(asUINT index) const
  636. {
  637. if( scriptData == 0 || index >= scriptData->variables.GetLength() )
  638. return 0;
  639. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  640. *tempString = scriptData->variables[index]->type.Format();
  641. *tempString += " " + scriptData->variables[index]->name;
  642. return tempString->AddressOf();
  643. }
  644. // internal
  645. void asCScriptFunction::AddVariable(asCString &name, asCDataType &type, int stackOffset)
  646. {
  647. asASSERT( scriptData );
  648. asSScriptVariable *var = asNEW(asSScriptVariable);
  649. if( var == 0 )
  650. {
  651. // Out of memory
  652. return;
  653. }
  654. var->name = name;
  655. var->type = type;
  656. var->stackOffset = stackOffset;
  657. var->declaredAtProgramPos = 0;
  658. scriptData->variables.PushLast(var);
  659. }
  660. // internal
  661. asCObjectType *asCScriptFunction::GetObjectTypeOfLocalVar(short varOffset)
  662. {
  663. asASSERT( scriptData );
  664. for( asUINT n = 0; n < scriptData->objVariablePos.GetLength(); n++ )
  665. {
  666. if( scriptData->objVariablePos[n] == varOffset )
  667. return scriptData->objVariableTypes[n];
  668. }
  669. return 0;
  670. }
  671. // internal
  672. void asCScriptFunction::ComputeSignatureId()
  673. {
  674. // This function will compute the signatureId based on the
  675. // function name, return type, and parameter types. The object
  676. // type for methods is not used, so that class methods and
  677. // interface methods match each other.
  678. for( asUINT n = 0; n < engine->signatureIds.GetLength(); n++ )
  679. {
  680. if( !IsSignatureEqual(engine->signatureIds[n]) ) continue;
  681. // We don't need to increment the reference counter here, because
  682. // asCScriptEngine::FreeScriptFunctionId will maintain the signature
  683. // id as the function is freed.
  684. signatureId = engine->signatureIds[n]->signatureId;
  685. return;
  686. }
  687. signatureId = id;
  688. engine->signatureIds.PushLast(this);
  689. }
  690. // internal
  691. bool asCScriptFunction::IsSignatureEqual(const asCScriptFunction *func) const
  692. {
  693. if( !IsSignatureExceptNameEqual(func) || name != func->name ) return false;
  694. return true;
  695. }
  696. // internal
  697. bool asCScriptFunction::IsSignatureExceptNameEqual(const asCScriptFunction *func) const
  698. {
  699. return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, func->objectType, func->isReadOnly);
  700. }
  701. // internal
  702. bool asCScriptFunction::IsSignatureExceptNameEqual(const asCDataType &retType, const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &paramInOut, const asCObjectType *objType, bool readOnly) const
  703. {
  704. if( this->returnType != retType ) return false;
  705. return IsSignatureExceptNameAndReturnTypeEqual(paramTypes, paramInOut, objType, readOnly);
  706. }
  707. // internal
  708. bool asCScriptFunction::IsSignatureExceptNameAndObjectTypeEqual(const asCScriptFunction *func) const
  709. {
  710. return IsSignatureExceptNameEqual(func->returnType, func->parameterTypes, func->inOutFlags, objectType, isReadOnly);
  711. }
  712. // internal
  713. bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCScriptFunction *func) const
  714. {
  715. return IsSignatureExceptNameAndReturnTypeEqual(func->parameterTypes, func->inOutFlags, func->objectType, func->isReadOnly);
  716. }
  717. // internal
  718. bool asCScriptFunction::IsSignatureExceptNameAndReturnTypeEqual(const asCArray<asCDataType> &paramTypes, const asCArray<asETypeModifiers> &paramInOut, const asCObjectType *objType, bool readOnly) const
  719. {
  720. if( this->isReadOnly != readOnly ) return false;
  721. if( this->inOutFlags != paramInOut ) return false;
  722. if( this->parameterTypes != paramTypes ) return false;
  723. if( (this->objectType != 0) != (objType != 0) ) return false;
  724. return true;
  725. }
  726. // internal
  727. void asCScriptFunction::AddReferences()
  728. {
  729. // This array will be used to make sure we only add the reference to the same resource once
  730. // This is especially important for global variables, as it expects the initialization function
  731. // to hold only one reference to the variable. However, if the variable is initialized through
  732. // the default constructor followed by the assignment operator we will have two references to
  733. // the variable in the function.
  734. asCArray<void*> ptrs;
  735. // Only count references if there is any bytecode
  736. if( scriptData && scriptData->byteCode.GetLength() )
  737. {
  738. if( returnType.IsObject() )
  739. returnType.GetObjectType()->AddRef();
  740. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  741. if( parameterTypes[p].IsObject() )
  742. parameterTypes[p].GetObjectType()->AddRef();
  743. for( asUINT v = 0; v < scriptData->objVariableTypes.GetLength(); v++ )
  744. scriptData->objVariableTypes[v]->AddRef();
  745. // Go through the byte code and add references to all resources used by the function
  746. asCArray<asDWORD> &bc = scriptData->byteCode;
  747. for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] )
  748. {
  749. switch( *(asBYTE*)&bc[n] )
  750. {
  751. // Object types
  752. case asBC_OBJTYPE:
  753. case asBC_FREE:
  754. case asBC_REFCPY:
  755. case asBC_RefCpyV:
  756. {
  757. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  758. objType->AddRef();
  759. }
  760. break;
  761. // Object type and function
  762. case asBC_ALLOC:
  763. {
  764. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  765. objType->AddRef();
  766. int func = asBC_INTARG(&bc[n]+AS_PTR_SIZE);
  767. if( func )
  768. engine->scriptFunctions[func]->AddRef();
  769. }
  770. break;
  771. // Global variables
  772. case asBC_PGA:
  773. case asBC_PshGPtr:
  774. case asBC_LDG:
  775. case asBC_PshG4:
  776. case asBC_LdGRdR4:
  777. case asBC_CpyGtoV4:
  778. case asBC_CpyVtoG4:
  779. case asBC_SetG4:
  780. // Need to increase the reference for each global variable
  781. {
  782. void *gvarPtr = (void*)asBC_PTRARG(&bc[n]);
  783. if( !gvarPtr ) break;
  784. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  785. if( !prop ) break;
  786. // Only addref the properties once
  787. if( !ptrs.Exists(gvarPtr) )
  788. {
  789. prop->AddRef();
  790. ptrs.PushLast(gvarPtr);
  791. }
  792. asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id);
  793. if( group != 0 ) group->AddRef();
  794. }
  795. break;
  796. // System functions
  797. case asBC_CALLSYS:
  798. {
  799. int funcId = asBC_INTARG(&bc[n]);
  800. asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
  801. if( group != 0 ) group->AddRef();
  802. engine->scriptFunctions[funcId]->AddRef();
  803. }
  804. break;
  805. // Functions
  806. case asBC_CALL:
  807. case asBC_CALLINTF:
  808. {
  809. int func = asBC_INTARG(&bc[n]);
  810. engine->scriptFunctions[func]->AddRef();
  811. }
  812. break;
  813. // Function pointers
  814. case asBC_FuncPtr:
  815. {
  816. asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]);
  817. func->AddRef();
  818. }
  819. break;
  820. }
  821. }
  822. }
  823. }
  824. // internal
  825. void asCScriptFunction::ReleaseReferences()
  826. {
  827. asCArray<void*> ptrs;
  828. // Only count references if there is any bytecode
  829. if( scriptData && scriptData->byteCode.GetLength() )
  830. {
  831. if( returnType.IsObject() )
  832. returnType.GetObjectType()->Release();
  833. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  834. if( parameterTypes[p].IsObject() )
  835. parameterTypes[p].GetObjectType()->Release();
  836. for( asUINT v = 0; v < scriptData->objVariableTypes.GetLength(); v++ )
  837. if( scriptData->objVariableTypes[v] )
  838. scriptData->objVariableTypes[v]->Release();
  839. // Go through the byte code and release references to all resources used by the function
  840. asCArray<asDWORD> &bc = scriptData->byteCode;
  841. for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] )
  842. {
  843. switch( *(asBYTE*)&bc[n] )
  844. {
  845. // Object types
  846. case asBC_OBJTYPE:
  847. case asBC_FREE:
  848. case asBC_REFCPY:
  849. case asBC_RefCpyV:
  850. {
  851. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  852. if( objType )
  853. objType->Release();
  854. }
  855. break;
  856. // Object type and function
  857. case asBC_ALLOC:
  858. {
  859. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  860. if( objType )
  861. objType->Release();
  862. int func = asBC_INTARG(&bc[n]+AS_PTR_SIZE);
  863. if( func )
  864. {
  865. asCScriptFunction *fptr = engine->scriptFunctions[func];
  866. if( fptr )
  867. fptr->Release();
  868. // The engine may have been forced to destroy the function internals early
  869. // and this may will make it impossible to find the function by id anymore.
  870. // This should only happen if the engine is released while the application
  871. // is still keeping functions alive.
  872. // TODO: Fix this possible memory leak
  873. }
  874. }
  875. break;
  876. // Global variables
  877. case asBC_PGA:
  878. case asBC_PshGPtr:
  879. case asBC_LDG:
  880. case asBC_PshG4:
  881. case asBC_LdGRdR4:
  882. case asBC_CpyGtoV4:
  883. case asBC_CpyVtoG4:
  884. case asBC_SetG4:
  885. // Need to increase the reference for each global variable
  886. {
  887. void *gvarPtr = (void*)asBC_PTRARG(&bc[n]);
  888. if( !gvarPtr ) break;
  889. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  890. if( !prop ) break;
  891. // Only release the properties once
  892. if( !ptrs.Exists(gvarPtr) )
  893. {
  894. prop->Release();
  895. ptrs.PushLast(gvarPtr);
  896. }
  897. asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id);
  898. if( group != 0 ) group->Release();
  899. }
  900. break;
  901. // System functions
  902. case asBC_CALLSYS:
  903. {
  904. int funcId = asBC_INTARG(&bc[n]);
  905. asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
  906. if( group != 0 ) group->Release();
  907. if( funcId )
  908. engine->scriptFunctions[funcId]->Release();
  909. }
  910. break;
  911. // Functions
  912. case asBC_CALL:
  913. case asBC_CALLINTF:
  914. {
  915. int func = asBC_INTARG(&bc[n]);
  916. if( func )
  917. {
  918. asCScriptFunction *fptr = engine->scriptFunctions[func];
  919. if( fptr )
  920. fptr->Release();
  921. // The engine may have been forced to destroy the function internals early
  922. // and this may will make it impossible to find the function by id anymore.
  923. // This should only happen if the engine is released while the application
  924. // is still keeping functions alive.
  925. // TODO: Fix this possible memory leak
  926. }
  927. }
  928. break;
  929. // Function pointers
  930. case asBC_FuncPtr:
  931. {
  932. asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]);
  933. if( func )
  934. func->Release();
  935. }
  936. break;
  937. }
  938. }
  939. // Release the jit compiled function
  940. if( scriptData->jitFunction )
  941. engine->jitCompiler->ReleaseJITFunction(scriptData->jitFunction);
  942. scriptData->jitFunction = 0;
  943. }
  944. // Delegate
  945. if( objForDelegate )
  946. engine->ReleaseScriptObject(objForDelegate, funcForDelegate->GetObjectType());
  947. objForDelegate = 0;
  948. if( funcForDelegate )
  949. funcForDelegate->Release();
  950. funcForDelegate = 0;
  951. }
  952. // interface
  953. int asCScriptFunction::GetReturnTypeId(asDWORD *flags) const
  954. {
  955. if( flags )
  956. {
  957. if( returnType.IsReference() )
  958. {
  959. *flags = asTM_INOUTREF;
  960. *flags |= returnType.IsReadOnly() ? asTM_CONST : 0;
  961. }
  962. else
  963. *flags = asTM_NONE;
  964. }
  965. return engine->GetTypeIdFromDataType(returnType);
  966. }
  967. // interface
  968. asUINT asCScriptFunction::GetParamCount() const
  969. {
  970. return (asUINT)parameterTypes.GetLength();
  971. }
  972. // interface
  973. int asCScriptFunction::GetParamTypeId(asUINT index, asDWORD *flags) const
  974. {
  975. if( index >= parameterTypes.GetLength() )
  976. return asINVALID_ARG;
  977. if( flags )
  978. {
  979. *flags = inOutFlags[index];
  980. *flags |= parameterTypes[index].IsReadOnly() ? asTM_CONST : 0;
  981. }
  982. return engine->GetTypeIdFromDataType(parameterTypes[index]);
  983. }
  984. // interface
  985. asIScriptEngine *asCScriptFunction::GetEngine() const
  986. {
  987. return engine;
  988. }
  989. // interface
  990. const char *asCScriptFunction::GetDeclaration(bool includeObjectName, bool includeNamespace) const
  991. {
  992. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  993. *tempString = GetDeclarationStr(includeObjectName, includeNamespace);
  994. return tempString->AddressOf();
  995. }
  996. // interface
  997. const char *asCScriptFunction::GetScriptSectionName() const
  998. {
  999. if( scriptData && scriptData->scriptSectionIdx >= 0 )
  1000. return engine->scriptSectionNames[scriptData->scriptSectionIdx]->AddressOf();
  1001. return 0;
  1002. }
  1003. // interface
  1004. const char *asCScriptFunction::GetConfigGroup() const
  1005. {
  1006. asCConfigGroup *group = 0;
  1007. if( funcType != asFUNC_FUNCDEF )
  1008. group = engine->FindConfigGroupForFunction(id);
  1009. else
  1010. group = engine->FindConfigGroupForFuncDef(this);
  1011. if( group == 0 )
  1012. return 0;
  1013. return group->groupName.AddressOf();
  1014. }
  1015. // interface
  1016. asDWORD asCScriptFunction::GetAccessMask() const
  1017. {
  1018. return accessMask;
  1019. }
  1020. // internal
  1021. void asCScriptFunction::JITCompile()
  1022. {
  1023. if( funcType != asFUNC_SCRIPT )
  1024. return;
  1025. asASSERT( scriptData );
  1026. asIJITCompiler *jit = engine->GetJITCompiler();
  1027. if( !jit )
  1028. return;
  1029. // Release the previous function, if any
  1030. if( scriptData->jitFunction )
  1031. {
  1032. engine->jitCompiler->ReleaseJITFunction(scriptData->jitFunction);
  1033. scriptData->jitFunction = 0;
  1034. }
  1035. // Compile for native system
  1036. int r = jit->CompileFunction(this, &scriptData->jitFunction);
  1037. if( r < 0 )
  1038. {
  1039. asASSERT( scriptData->jitFunction == 0 );
  1040. }
  1041. }
  1042. // interface
  1043. asDWORD *asCScriptFunction::GetByteCode(asUINT *length)
  1044. {
  1045. if( scriptData == 0 ) return 0;
  1046. if( length )
  1047. *length = (asUINT)scriptData->byteCode.GetLength();
  1048. if( scriptData->byteCode.GetLength() )
  1049. return scriptData->byteCode.AddressOf();
  1050. return 0;
  1051. }
  1052. // interface
  1053. void *asCScriptFunction::SetUserData(void *data)
  1054. {
  1055. void *oldData = userData;
  1056. userData = data;
  1057. return oldData;
  1058. }
  1059. // interface
  1060. void *asCScriptFunction::GetUserData() const
  1061. {
  1062. return userData;
  1063. }
  1064. // internal
  1065. // TODO: cleanup: This method should probably be a member of the engine
  1066. asCGlobalProperty *asCScriptFunction::GetPropertyByGlobalVarPtr(void *gvarPtr)
  1067. {
  1068. asSMapNode<void*, asCGlobalProperty*> *node;
  1069. if( engine->varAddressMap.MoveTo(&node, gvarPtr) )
  1070. {
  1071. asASSERT(gvarPtr == node->value->GetAddressOfValue());
  1072. return node->value;
  1073. }
  1074. return 0;
  1075. }
  1076. // internal
  1077. int asCScriptFunction::GetRefCount()
  1078. {
  1079. return refCount.get();
  1080. }
  1081. // internal
  1082. void asCScriptFunction::SetFlag()
  1083. {
  1084. gcFlag = true;
  1085. }
  1086. // internal
  1087. bool asCScriptFunction::GetFlag()
  1088. {
  1089. return gcFlag;
  1090. }
  1091. // internal
  1092. void asCScriptFunction::EnumReferences(asIScriptEngine *)
  1093. {
  1094. // Notify the GC of all object types used
  1095. if( returnType.IsObject() )
  1096. engine->GCEnumCallback(returnType.GetObjectType());
  1097. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  1098. if( parameterTypes[p].IsObject() )
  1099. engine->GCEnumCallback(parameterTypes[p].GetObjectType());
  1100. if( scriptData )
  1101. {
  1102. for( asUINT t = 0; t < scriptData->objVariableTypes.GetLength(); t++ )
  1103. engine->GCEnumCallback(scriptData->objVariableTypes[t]);
  1104. // Notify the GC of all script functions that is accessed
  1105. asCArray<asDWORD> &bc = scriptData->byteCode;
  1106. for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] )
  1107. {
  1108. switch( *(asBYTE*)&bc[n] )
  1109. {
  1110. case asBC_OBJTYPE:
  1111. case asBC_FREE:
  1112. case asBC_REFCPY:
  1113. case asBC_RefCpyV:
  1114. {
  1115. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  1116. engine->GCEnumCallback(objType);
  1117. }
  1118. break;
  1119. case asBC_ALLOC:
  1120. {
  1121. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  1122. engine->GCEnumCallback(objType);
  1123. int func = asBC_INTARG(&bc[n]+AS_PTR_SIZE);
  1124. if( func )
  1125. engine->GCEnumCallback(engine->scriptFunctions[func]);
  1126. }
  1127. break;
  1128. case asBC_CALL:
  1129. case asBC_CALLINTF:
  1130. {
  1131. int func = asBC_INTARG(&bc[n]);
  1132. if( func )
  1133. engine->GCEnumCallback(engine->scriptFunctions[func]);
  1134. }
  1135. break;
  1136. // Function pointers
  1137. case asBC_FuncPtr:
  1138. {
  1139. asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]);
  1140. if( func )
  1141. engine->GCEnumCallback(func);
  1142. }
  1143. break;
  1144. // Global variables
  1145. case asBC_PGA:
  1146. case asBC_PshGPtr:
  1147. case asBC_LDG:
  1148. case asBC_PshG4:
  1149. case asBC_LdGRdR4:
  1150. case asBC_CpyGtoV4:
  1151. case asBC_CpyVtoG4:
  1152. case asBC_SetG4:
  1153. // Need to enumerate the reference for each global variable
  1154. {
  1155. // TODO: optimize: Keep an array of accessed global properties
  1156. void *gvarPtr = (void*)asBC_PTRARG(&bc[n]);
  1157. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  1158. engine->GCEnumCallback(prop);
  1159. }
  1160. break;
  1161. }
  1162. }
  1163. }
  1164. // Delegate
  1165. if( objForDelegate )
  1166. engine->GCEnumCallback(objForDelegate);
  1167. if( funcForDelegate )
  1168. engine->GCEnumCallback(funcForDelegate);
  1169. }
  1170. // internal
  1171. void asCScriptFunction::ReleaseAllHandles(asIScriptEngine *)
  1172. {
  1173. // Release paramaters
  1174. if( scriptData && scriptData->byteCode.GetLength() )
  1175. {
  1176. if( returnType.IsObject() )
  1177. {
  1178. returnType.GetObjectType()->Release();
  1179. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  1180. }
  1181. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  1182. if( parameterTypes[p].IsObject() )
  1183. {
  1184. parameterTypes[p].GetObjectType()->Release();
  1185. parameterTypes[p] = asCDataType::CreatePrimitive(ttInt, false);
  1186. }
  1187. for( asUINT n = 0; n < scriptData->objVariableTypes.GetLength(); n++ )
  1188. scriptData->objVariableTypes[n]->Release();
  1189. scriptData->objVariableTypes.SetLength(0);
  1190. // Release all script functions
  1191. asCArray<asDWORD> &bc = scriptData->byteCode;
  1192. for( asUINT n = 0; n < bc.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&bc[n]].type] )
  1193. {
  1194. switch( *(asBYTE*)&bc[n] )
  1195. {
  1196. // Object types
  1197. case asBC_OBJTYPE:
  1198. case asBC_FREE:
  1199. case asBC_REFCPY:
  1200. case asBC_RefCpyV:
  1201. {
  1202. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  1203. if( objType )
  1204. {
  1205. objType->Release();
  1206. *(asPWORD*)&bc[n+1] = 0;
  1207. }
  1208. }
  1209. break;
  1210. case asBC_ALLOC:
  1211. {
  1212. asCObjectType *objType = (asCObjectType*)asBC_PTRARG(&bc[n]);
  1213. if( objType )
  1214. {
  1215. objType->Release();
  1216. *(asPWORD*)&bc[n+1] = 0;
  1217. }
  1218. int func = asBC_INTARG(&bc[n]+AS_PTR_SIZE);
  1219. if( func )
  1220. {
  1221. engine->scriptFunctions[func]->Release();
  1222. bc[n+AS_PTR_SIZE+1] = 0;
  1223. }
  1224. }
  1225. break;
  1226. case asBC_CALL:
  1227. case asBC_CALLINTF:
  1228. {
  1229. int func = asBC_INTARG(&bc[n]);
  1230. if( func )
  1231. {
  1232. engine->scriptFunctions[func]->Release();
  1233. bc[n+1] = 0;
  1234. }
  1235. }
  1236. break;
  1237. // Function pointers
  1238. case asBC_FuncPtr:
  1239. {
  1240. asCScriptFunction *func = (asCScriptFunction*)asBC_PTRARG(&bc[n]);
  1241. if( func )
  1242. {
  1243. func->Release();
  1244. *(asPWORD*)&bc[n+1] = 0;
  1245. }
  1246. }
  1247. break;
  1248. // The global variables are not released here. It is enough that the global
  1249. // variable itself release the function to break the circle
  1250. }
  1251. }
  1252. }
  1253. // Delegate
  1254. if( objForDelegate )
  1255. engine->ReleaseScriptObject(objForDelegate, funcForDelegate->GetObjectType());
  1256. objForDelegate = 0;
  1257. if( funcForDelegate )
  1258. funcForDelegate->Release();
  1259. funcForDelegate = 0;
  1260. }
  1261. // internal
  1262. bool asCScriptFunction::IsShared() const
  1263. {
  1264. // All system functions are shared
  1265. if( funcType == asFUNC_SYSTEM ) return true;
  1266. // All class methods for shared classes are also shared
  1267. if( objectType && (objectType->flags & asOBJ_SHARED) ) return true;
  1268. // Functions that have been specifically marked as shared are shared
  1269. return isShared;
  1270. }
  1271. // internal
  1272. bool asCScriptFunction::IsFinal() const
  1273. {
  1274. return isFinal;
  1275. }
  1276. // internal
  1277. bool asCScriptFunction::IsOverride() const
  1278. {
  1279. return isOverride;
  1280. }
  1281. END_AS_NAMESPACE