as_scriptfunction.cpp 43 KB

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