as_scriptfunction.cpp 43 KB

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