as_scriptfunction.cpp 27 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2011 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. BEGIN_AS_NAMESPACE
  36. #ifdef AS_MAX_PORTABILITY
  37. static void ScriptFunction_AddRef_Generic(asIScriptGeneric *gen)
  38. {
  39. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  40. self->AddRef();
  41. }
  42. static void ScriptFunction_Release_Generic(asIScriptGeneric *gen)
  43. {
  44. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  45. self->Release();
  46. }
  47. static void ScriptFunction_GetRefCount_Generic(asIScriptGeneric *gen)
  48. {
  49. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  50. *(int*)gen->GetAddressOfReturnLocation() = self->GetRefCount();
  51. }
  52. static void ScriptFunction_SetFlag_Generic(asIScriptGeneric *gen)
  53. {
  54. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  55. self->SetFlag();
  56. }
  57. static void ScriptFunction_GetFlag_Generic(asIScriptGeneric *gen)
  58. {
  59. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  60. *(bool*)gen->GetAddressOfReturnLocation() = self->GetFlag();
  61. }
  62. static void ScriptFunction_EnumReferences_Generic(asIScriptGeneric *gen)
  63. {
  64. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  65. asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
  66. self->EnumReferences(engine);
  67. }
  68. static void ScriptFunction_ReleaseAllHandles_Generic(asIScriptGeneric *gen)
  69. {
  70. asCScriptFunction *self = (asCScriptFunction*)gen->GetObject();
  71. asIScriptEngine *engine = *(asIScriptEngine**)gen->GetAddressOfArg(0);
  72. self->ReleaseAllHandles(engine);
  73. }
  74. #endif
  75. void RegisterScriptFunction(asCScriptEngine *engine)
  76. {
  77. // Register the gc behaviours for the script functions
  78. int r;
  79. engine->functionBehaviours.engine = engine;
  80. engine->functionBehaviours.flags = asOBJ_REF | asOBJ_GC;
  81. engine->functionBehaviours.name = "_builtin_function_";
  82. #ifndef AS_MAX_PORTABILITY
  83. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asMETHOD(asCScriptFunction,AddRef), asCALL_THISCALL); asASSERT( r >= 0 );
  84. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asMETHOD(asCScriptFunction,Release), asCALL_THISCALL); asASSERT( r >= 0 );
  85. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asMETHOD(asCScriptFunction,GetRefCount), asCALL_THISCALL); asASSERT( r >= 0 );
  86. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_SETGCFLAG, "void f()", asMETHOD(asCScriptFunction,SetFlag), asCALL_THISCALL); asASSERT( r >= 0 );
  87. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asMETHOD(asCScriptFunction,GetFlag), asCALL_THISCALL); asASSERT( r >= 0 );
  88. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asMETHOD(asCScriptFunction,EnumReferences), asCALL_THISCALL); asASSERT( r >= 0 );
  89. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asMETHOD(asCScriptFunction,ReleaseAllHandles), asCALL_THISCALL); asASSERT( r >= 0 );
  90. #else
  91. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ADDREF, "void f()", asFUNCTION(ScriptFunction_AddRef_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  92. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASE, "void f()", asFUNCTION(ScriptFunction_Release_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  93. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETREFCOUNT, "int f()", asFUNCTION(ScriptFunction_GetRefCount_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  94. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_SETGCFLAG, "void f()", asFUNCTION(ScriptFunction_SetFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  95. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_GETGCFLAG, "bool f()", asFUNCTION(ScriptFunction_GetFlag_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  96. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_ENUMREFS, "void f(int&in)", asFUNCTION(ScriptFunction_EnumReferences_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  97. r = engine->RegisterBehaviourToObjectType(&engine->functionBehaviours, asBEHAVE_RELEASEREFS, "void f(int&in)", asFUNCTION(ScriptFunction_ReleaseAllHandles_Generic), asCALL_GENERIC); asASSERT( r >= 0 );
  98. #endif
  99. }
  100. // internal
  101. asCScriptFunction::asCScriptFunction(asCScriptEngine *engine, asCModule *mod, asEFuncType _funcType)
  102. {
  103. refCount.set(1);
  104. this->engine = engine;
  105. funcType = _funcType;
  106. module = mod;
  107. objectType = 0;
  108. name = "";
  109. isReadOnly = false;
  110. isPrivate = false;
  111. stackNeeded = 0;
  112. sysFuncIntf = 0;
  113. signatureId = 0;
  114. scriptSectionIdx = -1;
  115. dontCleanUpOnException = false;
  116. vfTableIdx = -1;
  117. jitFunction = 0;
  118. gcFlag = false;
  119. userData = 0;
  120. id = 0;
  121. // Notify the GC of script functions
  122. if( funcType == asFUNC_SCRIPT )
  123. engine->gc.AddScriptObjectToGC(this, &engine->functionBehaviours);
  124. }
  125. // internal
  126. asCScriptFunction::~asCScriptFunction()
  127. {
  128. // Clean user data
  129. if( userData && engine->cleanFunctionFunc )
  130. engine->cleanFunctionFunc(this);
  131. // Imported functions are not reference counted, nor are dummy
  132. // functions that are allocated on the stack
  133. asASSERT( funcType == asFUNC_DUMMY ||
  134. funcType == asFUNC_IMPORTED ||
  135. refCount.get() == 0 );
  136. ReleaseReferences();
  137. // Tell engine to free the function id
  138. if( funcType != -1 && funcType != asFUNC_IMPORTED && id )
  139. engine->FreeScriptFunctionId(id);
  140. for( asUINT n = 0; n < variables.GetLength(); n++ )
  141. {
  142. asDELETE(variables[n],asSScriptVariable);
  143. }
  144. if( sysFuncIntf )
  145. {
  146. asDELETE(sysFuncIntf,asSSystemFunctionInterface);
  147. }
  148. for( asUINT p = 0; p < defaultArgs.GetLength(); p++ )
  149. {
  150. if( defaultArgs[p] )
  151. asDELETE(defaultArgs[p], asCString);
  152. }
  153. }
  154. // interface
  155. int asCScriptFunction::GetId() const
  156. {
  157. return id;
  158. }
  159. // interface
  160. int asCScriptFunction::AddRef() const
  161. {
  162. gcFlag = false;
  163. asASSERT( funcType != asFUNC_IMPORTED );
  164. return refCount.atomicInc();
  165. }
  166. // interface
  167. int asCScriptFunction::Release() const
  168. {
  169. gcFlag = false;
  170. asASSERT( funcType != asFUNC_IMPORTED );
  171. int r = refCount.atomicDec();
  172. if( r == 0 && funcType != -1 ) // Dummy functions are allocated on the stack and cannot be deleted
  173. asDELETE(const_cast<asCScriptFunction*>(this),asCScriptFunction);
  174. return r;
  175. }
  176. // interface
  177. void asCScriptEngine::SetEngineUserDataCleanupCallback(asCLEANENGINEFUNC_t callback)
  178. {
  179. cleanEngineFunc = callback;
  180. }
  181. // interface
  182. void asCScriptEngine::SetContextUserDataCleanupCallback(asCLEANCONTEXTFUNC_t callback)
  183. {
  184. cleanContextFunc = callback;
  185. }
  186. // interface
  187. void asCScriptEngine::SetFunctionUserDataCleanupCallback(asCLEANFUNCTIONFUNC_t callback)
  188. {
  189. cleanFunctionFunc = callback;
  190. }
  191. // interface
  192. const char *asCScriptFunction::GetModuleName() const
  193. {
  194. if( module )
  195. {
  196. return module->name.AddressOf();
  197. }
  198. return 0;
  199. }
  200. // interface
  201. asIObjectType *asCScriptFunction::GetObjectType() const
  202. {
  203. return objectType;
  204. }
  205. // interface
  206. const char *asCScriptFunction::GetObjectName() const
  207. {
  208. if( objectType )
  209. return objectType->GetName();
  210. return 0;
  211. }
  212. // interface
  213. const char *asCScriptFunction::GetName() const
  214. {
  215. return name.AddressOf();
  216. }
  217. #ifdef AS_DEPRECATED
  218. // Since 2.20.0
  219. // interface
  220. bool asCScriptFunction::IsClassMethod() const
  221. {
  222. return objectType && objectType->IsInterface() == false;
  223. }
  224. // interface
  225. bool asCScriptFunction::IsInterfaceMethod() const
  226. {
  227. return objectType && objectType->IsInterface();
  228. }
  229. #endif
  230. // interface
  231. bool asCScriptFunction::IsReadOnly() const
  232. {
  233. return isReadOnly;
  234. }
  235. // interface
  236. bool asCScriptFunction::IsPrivate() const
  237. {
  238. return isPrivate;
  239. }
  240. // internal
  241. int asCScriptFunction::GetSpaceNeededForArguments()
  242. {
  243. // We need to check the size for each type
  244. int s = 0;
  245. for( asUINT n = 0; n < parameterTypes.GetLength(); n++ )
  246. s += parameterTypes[n].GetSizeOnStackDWords();
  247. return s;
  248. }
  249. // internal
  250. int asCScriptFunction::GetSpaceNeededForReturnValue()
  251. {
  252. return returnType.GetSizeOnStackDWords();
  253. }
  254. // internal
  255. asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName) const
  256. {
  257. asCString str;
  258. // TODO: default arg: Make the declaration with the default args an option
  259. // Don't add the return type for constructors and destructors
  260. if( !(returnType.GetTokenType() == ttVoid &&
  261. objectType &&
  262. (name == objectType->name || (name.GetLength() > 0 && name[0] == '~'))) )
  263. {
  264. str = returnType.Format();
  265. str += " ";
  266. }
  267. if( objectType && includeObjectName )
  268. {
  269. if( objectType->name != "" )
  270. str += objectType->name + "::";
  271. else
  272. str += "_unnamed_type_::";
  273. }
  274. if( name == "" )
  275. str += "_unnamed_function_(";
  276. else
  277. str += name + "(";
  278. if( parameterTypes.GetLength() > 0 )
  279. {
  280. asUINT n;
  281. for( n = 0; n < parameterTypes.GetLength() - 1; n++ )
  282. {
  283. str += parameterTypes[n].Format();
  284. if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
  285. {
  286. if( inOutFlags[n] == asTM_INREF ) str += "in";
  287. else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
  288. else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
  289. }
  290. if( defaultArgs.GetLength() > n && defaultArgs[n] )
  291. {
  292. asCString tmp;
  293. tmp.Format(" arg%d = %s", n, defaultArgs[n]->AddressOf());
  294. str += tmp;
  295. }
  296. str += ", ";
  297. }
  298. // Add the last parameter
  299. str += parameterTypes[n].Format();
  300. if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
  301. {
  302. if( inOutFlags[n] == asTM_INREF ) str += "in";
  303. else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
  304. else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
  305. }
  306. if( defaultArgs.GetLength() > n && defaultArgs[n] )
  307. {
  308. asCString tmp;
  309. tmp.Format(" arg%d = %s", n, defaultArgs[n]->AddressOf());
  310. str += tmp;
  311. }
  312. }
  313. str += ")";
  314. if( isReadOnly )
  315. str += " const";
  316. return str;
  317. }
  318. // internal
  319. int asCScriptFunction::GetLineNumber(int programPosition)
  320. {
  321. if( lineNumbers.GetLength() == 0 ) return 0;
  322. // Do a binary search in the buffer
  323. int max = (int)lineNumbers.GetLength()/2 - 1;
  324. int min = 0;
  325. int i = max/2;
  326. for(;;)
  327. {
  328. if( lineNumbers[i*2] < programPosition )
  329. {
  330. // Have we found the largest number < programPosition?
  331. if( max == i ) return lineNumbers[i*2+1];
  332. if( lineNumbers[i*2+2] > programPosition ) return lineNumbers[i*2+1];
  333. min = i + 1;
  334. i = (max + min)/2;
  335. }
  336. else if( lineNumbers[i*2] > programPosition )
  337. {
  338. // Have we found the smallest number > programPosition?
  339. if( min == i ) return lineNumbers[i*2+1];
  340. max = i - 1;
  341. i = (max + min)/2;
  342. }
  343. else
  344. {
  345. // We found the exact position
  346. return lineNumbers[i*2+1];
  347. }
  348. }
  349. }
  350. // interface
  351. asEFuncType asCScriptFunction::GetFuncType() const
  352. {
  353. return funcType;
  354. }
  355. // interface
  356. int asCScriptFunction::GetVarCount() const
  357. {
  358. return int(variables.GetLength());
  359. }
  360. // interface
  361. int asCScriptFunction::GetVar(asUINT index, const char **name, int *typeId) const
  362. {
  363. if( index >= variables.GetLength() )
  364. return asINVALID_ARG;
  365. if( name )
  366. *name = variables[index]->name.AddressOf();
  367. if( typeId )
  368. *typeId = engine->GetTypeIdFromDataType(variables[index]->type);
  369. return asSUCCESS;
  370. }
  371. // interface
  372. const char *asCScriptFunction::GetVarDecl(asUINT index) const
  373. {
  374. if( index >= variables.GetLength() )
  375. return 0;
  376. asASSERT(threadManager);
  377. asCString *tempString = &threadManager->GetLocalData()->string;
  378. *tempString = variables[index]->type.Format();
  379. *tempString += " " + variables[index]->name;
  380. return tempString->AddressOf();
  381. }
  382. // internal
  383. void asCScriptFunction::AddVariable(asCString &name, asCDataType &type, int stackOffset)
  384. {
  385. asSScriptVariable *var = asNEW(asSScriptVariable);
  386. var->name = name;
  387. var->type = type;
  388. var->stackOffset = stackOffset;
  389. variables.PushLast(var);
  390. }
  391. // internal
  392. void asCScriptFunction::ComputeSignatureId()
  393. {
  394. // This function will compute the signatureId based on the
  395. // function name, return type, and parameter types. The object
  396. // type for methods is not used, so that class methods and
  397. // interface methods match each other.
  398. for( asUINT n = 0; n < engine->signatureIds.GetLength(); n++ )
  399. {
  400. if( !IsSignatureEqual(engine->signatureIds[n]) ) continue;
  401. // We don't need to increment the reference counter here, because
  402. // asCScriptEngine::FreeScriptFunctionId will maintain the signature
  403. // id as the function is freed.
  404. signatureId = engine->signatureIds[n]->signatureId;
  405. return;
  406. }
  407. signatureId = id;
  408. engine->signatureIds.PushLast(this);
  409. }
  410. // internal
  411. bool asCScriptFunction::IsSignatureEqual(const asCScriptFunction *func) const
  412. {
  413. if( !IsSignatureExceptNameEqual(func) || name != func->name ) return false;
  414. return true;
  415. }
  416. // internal
  417. bool asCScriptFunction::IsSignatureExceptNameEqual(const asCScriptFunction *func) const
  418. {
  419. if( returnType != func->returnType ) return false;
  420. if( isReadOnly != func->isReadOnly ) return false;
  421. if( inOutFlags != func->inOutFlags ) return false;
  422. if( parameterTypes != func->parameterTypes ) return false;
  423. if( (objectType != 0) != (func->objectType != 0) ) return false;
  424. return true;
  425. }
  426. // internal
  427. void asCScriptFunction::AddReferences()
  428. {
  429. asUINT n;
  430. // This array will be used to make sure we only add the reference to the same resource once
  431. // This is especially important for global variables, as it expects the initialization function
  432. // to hold only one reference to the variable. However, if the variable is initialized through
  433. // the default constructor followed by the assignment operator we will have two references to
  434. // the variable in the function.
  435. asCArray<void*> ptrs;
  436. // Only count references if there is any bytecode
  437. if( byteCode.GetLength() )
  438. {
  439. if( returnType.IsObject() )
  440. returnType.GetObjectType()->AddRef();
  441. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  442. if( parameterTypes[p].IsObject() )
  443. parameterTypes[p].GetObjectType()->AddRef();
  444. for( asUINT n = 0; n < objVariableTypes.GetLength(); n++ )
  445. objVariableTypes[n]->AddRef();
  446. }
  447. // Go through the byte code and add references to all resources used by the function
  448. for( n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
  449. {
  450. switch( *(asBYTE*)&byteCode[n] )
  451. {
  452. // Object types
  453. case asBC_OBJTYPE:
  454. case asBC_FREE:
  455. case asBC_REFCPY:
  456. {
  457. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  458. objType->AddRef();
  459. }
  460. break;
  461. // Object type and function
  462. case asBC_ALLOC:
  463. {
  464. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  465. objType->AddRef();
  466. int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
  467. if( func )
  468. engine->scriptFunctions[func]->AddRef();
  469. }
  470. break;
  471. // Global variables
  472. case asBC_PGA:
  473. case asBC_LDG:
  474. case asBC_PshG4:
  475. case asBC_LdGRdR4:
  476. case asBC_CpyGtoV4:
  477. case asBC_CpyVtoG4:
  478. case asBC_SetG4:
  479. // Need to increase the reference for each global variable
  480. {
  481. void *gvarPtr = (void*)(size_t)asBC_PTRARG(&byteCode[n]);
  482. if( !gvarPtr ) break;
  483. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  484. if( !prop ) break;
  485. // Only addref the properties once
  486. if( !ptrs.Exists(gvarPtr) )
  487. {
  488. prop->AddRef();
  489. ptrs.PushLast(gvarPtr);
  490. }
  491. asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id);
  492. if( group != 0 ) group->AddRef();
  493. }
  494. break;
  495. // System functions
  496. case asBC_CALLSYS:
  497. {
  498. int funcId = asBC_INTARG(&byteCode[n]);
  499. asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
  500. if( group != 0 ) group->AddRef();
  501. engine->scriptFunctions[funcId]->AddRef();
  502. }
  503. break;
  504. // Functions
  505. case asBC_CALL:
  506. case asBC_CALLINTF:
  507. {
  508. int func = asBC_INTARG(&byteCode[n]);
  509. engine->scriptFunctions[func]->AddRef();
  510. }
  511. break;
  512. // Function pointers
  513. case asBC_FuncPtr:
  514. {
  515. asCScriptFunction *func = (asCScriptFunction*)(size_t)asBC_PTRARG(&byteCode[n]);
  516. func->AddRef();
  517. }
  518. break;
  519. }
  520. }
  521. }
  522. // internal
  523. void asCScriptFunction::ReleaseReferences()
  524. {
  525. asUINT n;
  526. asCArray<void*> ptrs;
  527. // Only count references if there is any bytecode
  528. if( byteCode.GetLength() )
  529. {
  530. if( returnType.IsObject() )
  531. returnType.GetObjectType()->Release();
  532. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  533. if( parameterTypes[p].IsObject() )
  534. parameterTypes[p].GetObjectType()->Release();
  535. for( asUINT n = 0; n < objVariableTypes.GetLength(); n++ )
  536. if( objVariableTypes[n] )
  537. objVariableTypes[n]->Release();
  538. }
  539. // Go through the byte code and release references to all resources used by the function
  540. for( n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
  541. {
  542. switch( *(asBYTE*)&byteCode[n] )
  543. {
  544. // Object types
  545. case asBC_OBJTYPE:
  546. case asBC_FREE:
  547. case asBC_REFCPY:
  548. {
  549. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  550. if( objType )
  551. objType->Release();
  552. }
  553. break;
  554. // Object type and function
  555. case asBC_ALLOC:
  556. {
  557. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  558. if( objType )
  559. objType->Release();
  560. int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
  561. if( func )
  562. engine->scriptFunctions[func]->Release();
  563. }
  564. break;
  565. // Global variables
  566. case asBC_PGA:
  567. case asBC_LDG:
  568. case asBC_PshG4:
  569. case asBC_LdGRdR4:
  570. case asBC_CpyGtoV4:
  571. case asBC_CpyVtoG4:
  572. case asBC_SetG4:
  573. // Need to increase the reference for each global variable
  574. {
  575. void *gvarPtr = (void*)(size_t)asBC_PTRARG(&byteCode[n]);
  576. if( !gvarPtr ) break;
  577. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  578. if( !prop ) break;
  579. // Only release the properties once
  580. if( !ptrs.Exists(gvarPtr) )
  581. {
  582. prop->Release();
  583. ptrs.PushLast(gvarPtr);
  584. }
  585. asCConfigGroup *group = engine->FindConfigGroupForGlobalVar(prop->id);
  586. if( group != 0 ) group->Release();
  587. }
  588. break;
  589. // System functions
  590. case asBC_CALLSYS:
  591. {
  592. int funcId = asBC_INTARG(&byteCode[n]);
  593. asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
  594. if( group != 0 ) group->Release();
  595. if( funcId )
  596. engine->scriptFunctions[funcId]->Release();
  597. }
  598. break;
  599. // Functions
  600. case asBC_CALL:
  601. case asBC_CALLINTF:
  602. {
  603. int func = asBC_INTARG(&byteCode[n]);
  604. if( func )
  605. engine->scriptFunctions[func]->Release();
  606. }
  607. break;
  608. // Function pointers
  609. case asBC_FuncPtr:
  610. {
  611. asCScriptFunction *func = (asCScriptFunction*)(size_t)asBC_PTRARG(&byteCode[n]);
  612. if( func )
  613. func->Release();
  614. }
  615. break;
  616. }
  617. }
  618. // Release the jit compiled function
  619. if( jitFunction )
  620. engine->jitCompiler->ReleaseJITFunction(jitFunction);
  621. jitFunction = 0;
  622. }
  623. // interface
  624. int asCScriptFunction::GetReturnTypeId() const
  625. {
  626. return engine->GetTypeIdFromDataType(returnType);
  627. }
  628. // interface
  629. int asCScriptFunction::GetParamCount() const
  630. {
  631. return (int)parameterTypes.GetLength();
  632. }
  633. // interface
  634. int asCScriptFunction::GetParamTypeId(int index, asDWORD *flags) const
  635. {
  636. if( index < 0 || (unsigned)index >= parameterTypes.GetLength() )
  637. return asINVALID_ARG;
  638. if( flags )
  639. *flags = inOutFlags[index];
  640. return engine->GetTypeIdFromDataType(parameterTypes[index]);
  641. }
  642. // interface
  643. asIScriptEngine *asCScriptFunction::GetEngine() const
  644. {
  645. return engine;
  646. }
  647. // interface
  648. const char *asCScriptFunction::GetDeclaration(bool includeObjectName) const
  649. {
  650. asASSERT(threadManager);
  651. asCString *tempString = &threadManager->GetLocalData()->string;
  652. *tempString = GetDeclarationStr(includeObjectName);
  653. return tempString->AddressOf();
  654. }
  655. // interface
  656. const char *asCScriptFunction::GetScriptSectionName() const
  657. {
  658. if( scriptSectionIdx >= 0 )
  659. return engine->scriptSectionNames[scriptSectionIdx]->AddressOf();
  660. return 0;
  661. }
  662. // interface
  663. const char *asCScriptFunction::GetConfigGroup() const
  664. {
  665. asCConfigGroup *group = engine->FindConfigGroupForFunction(id);
  666. if( group == 0 )
  667. return 0;
  668. return group->groupName.AddressOf();
  669. }
  670. // internal
  671. void asCScriptFunction::JITCompile()
  672. {
  673. asIJITCompiler *jit = engine->GetJITCompiler();
  674. if( !jit )
  675. return;
  676. // Release the previous function, if any
  677. if( jitFunction )
  678. {
  679. engine->jitCompiler->ReleaseJITFunction(jitFunction);
  680. jitFunction = 0;
  681. }
  682. // Compile for native system
  683. int r = jit->CompileFunction(this, &jitFunction);
  684. if( r < 0 )
  685. {
  686. asASSERT( jitFunction == 0 );
  687. }
  688. }
  689. // interface
  690. asDWORD *asCScriptFunction::GetByteCode(asUINT *length)
  691. {
  692. if( length )
  693. *length = (asUINT)byteCode.GetLength();
  694. if( byteCode.GetLength() )
  695. {
  696. return byteCode.AddressOf();
  697. }
  698. return 0;
  699. }
  700. // interface
  701. void *asCScriptFunction::SetUserData(void *data)
  702. {
  703. void *oldData = userData;
  704. userData = data;
  705. return oldData;
  706. }
  707. // interface
  708. void *asCScriptFunction::GetUserData() const
  709. {
  710. return userData;
  711. }
  712. // internal
  713. asCGlobalProperty *asCScriptFunction::GetPropertyByGlobalVarPtr(void *gvarPtr)
  714. {
  715. for( asUINT g = 0; g < engine->globalProperties.GetLength(); g++ )
  716. if( engine->globalProperties[g] && engine->globalProperties[g]->GetAddressOfValue() == gvarPtr )
  717. return engine->globalProperties[g];
  718. return 0;
  719. }
  720. // internal
  721. int asCScriptFunction::GetRefCount()
  722. {
  723. return refCount.get();
  724. }
  725. // internal
  726. void asCScriptFunction::SetFlag()
  727. {
  728. gcFlag = true;
  729. }
  730. // internal
  731. bool asCScriptFunction::GetFlag()
  732. {
  733. return gcFlag;
  734. }
  735. // internal
  736. void asCScriptFunction::EnumReferences(asIScriptEngine *)
  737. {
  738. // Notify the GC of all object types used
  739. if( returnType.IsObject() )
  740. engine->GCEnumCallback(returnType.GetObjectType());
  741. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  742. if( parameterTypes[p].IsObject() )
  743. engine->GCEnumCallback(parameterTypes[p].GetObjectType());
  744. for( asUINT t = 0; t < objVariableTypes.GetLength(); t++ )
  745. engine->GCEnumCallback(objVariableTypes[t]);
  746. // Notify the GC of all script functions that is accessed
  747. for( asUINT n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
  748. {
  749. switch( *(asBYTE*)&byteCode[n] )
  750. {
  751. case asBC_OBJTYPE:
  752. case asBC_FREE:
  753. case asBC_REFCPY:
  754. {
  755. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  756. engine->GCEnumCallback(objType);
  757. }
  758. break;
  759. case asBC_ALLOC:
  760. {
  761. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  762. engine->GCEnumCallback(objType);
  763. int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
  764. if( func )
  765. engine->GCEnumCallback(engine->scriptFunctions[func]);
  766. }
  767. break;
  768. case asBC_CALL:
  769. case asBC_CALLINTF:
  770. {
  771. int func = asBC_INTARG(&byteCode[n]);
  772. if( func )
  773. engine->GCEnumCallback(engine->scriptFunctions[func]);
  774. }
  775. break;
  776. // Function pointers
  777. case asBC_FuncPtr:
  778. {
  779. asCScriptFunction *func = (asCScriptFunction*)(size_t)asBC_PTRARG(&byteCode[n]);
  780. if( func )
  781. engine->GCEnumCallback(func);
  782. }
  783. break;
  784. // Global variables
  785. case asBC_PGA:
  786. case asBC_LDG:
  787. case asBC_PshG4:
  788. case asBC_LdGRdR4:
  789. case asBC_CpyGtoV4:
  790. case asBC_CpyVtoG4:
  791. case asBC_SetG4:
  792. // Need to enumerate the reference for each global variable
  793. {
  794. // TODO: optimize: Keep an array of accessed global properties
  795. void *gvarPtr = (void*)(size_t)asBC_PTRARG(&byteCode[n]);
  796. asCGlobalProperty *prop = GetPropertyByGlobalVarPtr(gvarPtr);
  797. engine->GCEnumCallback(prop);
  798. }
  799. break;
  800. }
  801. }
  802. }
  803. // internal
  804. void asCScriptFunction::ReleaseAllHandles(asIScriptEngine *)
  805. {
  806. // Release paramaters
  807. if( byteCode.GetLength() )
  808. {
  809. if( returnType.IsObject() )
  810. {
  811. returnType.GetObjectType()->Release();
  812. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  813. }
  814. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  815. if( parameterTypes[p].IsObject() )
  816. {
  817. parameterTypes[p].GetObjectType()->Release();
  818. parameterTypes[p] = asCDataType::CreatePrimitive(ttInt, false);
  819. }
  820. for( asUINT n = 0; n < objVariableTypes.GetLength(); n++ )
  821. objVariableTypes[n]->Release();
  822. objVariableTypes.SetLength(0);
  823. }
  824. // Release all script functions
  825. for( asUINT n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
  826. {
  827. switch( *(asBYTE*)&byteCode[n] )
  828. {
  829. // Object types
  830. case asBC_OBJTYPE:
  831. case asBC_FREE:
  832. case asBC_REFCPY:
  833. {
  834. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  835. objType->Release();
  836. *(void**)&byteCode[n+1] = 0;
  837. }
  838. break;
  839. case asBC_ALLOC:
  840. {
  841. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  842. objType->Release();
  843. *(void**)&byteCode[n+1] = 0;
  844. int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
  845. if( func )
  846. {
  847. engine->scriptFunctions[func]->Release();
  848. byteCode[n+AS_PTR_SIZE+1] = 0;
  849. }
  850. }
  851. break;
  852. case asBC_CALL:
  853. case asBC_CALLINTF:
  854. {
  855. int func = asBC_INTARG(&byteCode[n]);
  856. if( func )
  857. {
  858. engine->scriptFunctions[func]->Release();
  859. byteCode[n+1] = 0;
  860. }
  861. }
  862. break;
  863. // Function pointers
  864. case asBC_FuncPtr:
  865. {
  866. asCScriptFunction *func = (asCScriptFunction*)(size_t)asBC_PTRARG(&byteCode[n]);
  867. if( func )
  868. {
  869. func->Release();
  870. *(size_t*)&byteCode[n+1] = 0;
  871. }
  872. }
  873. break;
  874. // The global variables are not released here. It is enough that the global
  875. // variable itself release the function to break the circle
  876. }
  877. }
  878. }
  879. END_AS_NAMESPACE