as_scriptfunction.cpp 37 KB

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