/xbmc/visualizations/Vortex/angelscript/angelscript/source/as_scriptfunction.cpp

http://github.com/xbmc/xbmc · C++ · 885 lines · 636 code · 127 blank · 122 comment · 153 complexity · 4ad8794e91a39be120ac319811658427 MD5 · raw file

  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2009 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. andreas@angelcode.com
  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, int _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. stackNeeded = 0;
  111. sysFuncIntf = 0;
  112. signatureId = 0;
  113. scriptSectionIdx = -1;
  114. dontCleanUpOnException = false;
  115. vfTableIdx = -1;
  116. jitFunction = 0;
  117. gcFlag = false;
  118. // Notify the GC of script functions
  119. if( funcType == asFUNC_SCRIPT )
  120. engine->gc.AddScriptObjectToGC(this, &engine->functionBehaviours);
  121. }
  122. // internal
  123. asCScriptFunction::~asCScriptFunction()
  124. {
  125. // Imported functions are not reference counted, nor are dummy
  126. // functions that are allocated on the stack
  127. asASSERT( funcType == -1 ||
  128. funcType == asFUNC_IMPORTED ||
  129. refCount.get() == 0 );
  130. ReleaseReferences();
  131. // Tell engine to free the function id
  132. if( funcType != -1 && funcType != asFUNC_IMPORTED && id )
  133. engine->FreeScriptFunctionId(id);
  134. for( asUINT n = 0; n < variables.GetLength(); n++ )
  135. {
  136. asDELETE(variables[n],asSScriptVariable);
  137. }
  138. if( sysFuncIntf )
  139. {
  140. asDELETE(sysFuncIntf,asSSystemFunctionInterface);
  141. }
  142. }
  143. // interface
  144. int asCScriptFunction::GetId() const
  145. {
  146. return id;
  147. }
  148. // interface
  149. int asCScriptFunction::AddRef()
  150. {
  151. gcFlag = false;
  152. asASSERT( funcType != asFUNC_IMPORTED );
  153. return refCount.atomicInc();
  154. }
  155. // interface
  156. int asCScriptFunction::Release()
  157. {
  158. gcFlag = false;
  159. asASSERT( funcType != asFUNC_IMPORTED );
  160. int r = refCount.atomicDec();
  161. if( r == 0 && funcType != -1 ) // Dummy functions are allocated on the stack and cannot be deleted
  162. asDELETE(this,asCScriptFunction);
  163. return r;
  164. }
  165. // interface
  166. const char *asCScriptFunction::GetModuleName() const
  167. {
  168. if( module )
  169. {
  170. return module->name.AddressOf();
  171. }
  172. return 0;
  173. }
  174. // interface
  175. asIObjectType *asCScriptFunction::GetObjectType() const
  176. {
  177. return objectType;
  178. }
  179. // interface
  180. const char *asCScriptFunction::GetObjectName() const
  181. {
  182. if( objectType )
  183. return objectType->GetName();
  184. return 0;
  185. }
  186. // interface
  187. const char *asCScriptFunction::GetName() const
  188. {
  189. return name.AddressOf();
  190. }
  191. // interface
  192. bool asCScriptFunction::IsClassMethod() const
  193. {
  194. return objectType && objectType->IsInterface() == false;
  195. }
  196. // interface
  197. bool asCScriptFunction::IsInterfaceMethod() const
  198. {
  199. return objectType && objectType->IsInterface();
  200. }
  201. // interface
  202. bool asCScriptFunction::IsReadOnly() const
  203. {
  204. return isReadOnly;
  205. }
  206. // internal
  207. int asCScriptFunction::GetSpaceNeededForArguments()
  208. {
  209. // We need to check the size for each type
  210. int s = 0;
  211. for( asUINT n = 0; n < parameterTypes.GetLength(); n++ )
  212. s += parameterTypes[n].GetSizeOnStackDWords();
  213. return s;
  214. }
  215. // internal
  216. int asCScriptFunction::GetSpaceNeededForReturnValue()
  217. {
  218. return returnType.GetSizeOnStackDWords();
  219. }
  220. // internal
  221. asCString asCScriptFunction::GetDeclarationStr(bool includeObjectName) const
  222. {
  223. asCString str;
  224. str = returnType.Format();
  225. str += " ";
  226. if( objectType && includeObjectName )
  227. {
  228. if( objectType->name != "" )
  229. str += objectType->name + "::";
  230. else
  231. str += "_unnamed_type_::";
  232. }
  233. asASSERT(name.GetLength() > 0);
  234. if( name == "" )
  235. str += "_unnamed_function_(";
  236. else
  237. str += name + "(";
  238. if( parameterTypes.GetLength() > 0 )
  239. {
  240. asUINT n;
  241. for( n = 0; n < parameterTypes.GetLength() - 1; n++ )
  242. {
  243. str += parameterTypes[n].Format();
  244. if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
  245. {
  246. if( inOutFlags[n] == asTM_INREF ) str += "in";
  247. else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
  248. else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
  249. }
  250. str += ", ";
  251. }
  252. str += parameterTypes[n].Format();
  253. if( parameterTypes[n].IsReference() && inOutFlags.GetLength() > n )
  254. {
  255. if( inOutFlags[n] == asTM_INREF ) str += "in";
  256. else if( inOutFlags[n] == asTM_OUTREF ) str += "out";
  257. else if( inOutFlags[n] == asTM_INOUTREF ) str += "inout";
  258. }
  259. }
  260. str += ")";
  261. if( isReadOnly )
  262. str += " const";
  263. return str;
  264. }
  265. // internal
  266. int asCScriptFunction::GetLineNumber(int programPosition)
  267. {
  268. if( lineNumbers.GetLength() == 0 ) return 0;
  269. // Do a binary search in the buffer
  270. int max = (int)lineNumbers.GetLength()/2 - 1;
  271. int min = 0;
  272. int i = max/2;
  273. for(;;)
  274. {
  275. if( lineNumbers[i*2] < programPosition )
  276. {
  277. // Have we found the largest number < programPosition?
  278. if( max == i ) return lineNumbers[i*2+1];
  279. if( lineNumbers[i*2+2] > programPosition ) return lineNumbers[i*2+1];
  280. min = i + 1;
  281. i = (max + min)/2;
  282. }
  283. else if( lineNumbers[i*2] > programPosition )
  284. {
  285. // Have we found the smallest number > programPosition?
  286. if( min == i ) return lineNumbers[i*2+1];
  287. max = i - 1;
  288. i = (max + min)/2;
  289. }
  290. else
  291. {
  292. // We found the exact position
  293. return lineNumbers[i*2+1];
  294. }
  295. }
  296. }
  297. // internal
  298. void asCScriptFunction::AddVariable(asCString &name, asCDataType &type, int stackOffset)
  299. {
  300. asSScriptVariable *var = asNEW(asSScriptVariable);
  301. var->name = name;
  302. var->type = type;
  303. var->stackOffset = stackOffset;
  304. variables.PushLast(var);
  305. }
  306. // internal
  307. void asCScriptFunction::ComputeSignatureId()
  308. {
  309. // This function will compute the signatureId based on the
  310. // function name, return type, and parameter types. The object
  311. // type for methods is not used, so that class methods and
  312. // interface methods match each other.
  313. for( asUINT n = 0; n < engine->signatureIds.GetLength(); n++ )
  314. {
  315. if( !IsSignatureEqual(engine->signatureIds[n]) ) continue;
  316. // We don't need to increment the reference counter here, because
  317. // asCScriptEngine::FreeScriptFunctionId will maintain the signature
  318. // id as the function is freed.
  319. signatureId = engine->signatureIds[n]->signatureId;
  320. return;
  321. }
  322. signatureId = id;
  323. engine->signatureIds.PushLast(this);
  324. }
  325. // internal
  326. bool asCScriptFunction::IsSignatureEqual(const asCScriptFunction *func) const
  327. {
  328. if( name != func->name ) return false;
  329. if( returnType != func->returnType ) return false;
  330. if( isReadOnly != func->isReadOnly ) return false;
  331. if( inOutFlags != func->inOutFlags ) return false;
  332. if( parameterTypes != func->parameterTypes ) return false;
  333. if( (objectType != 0) != (func->objectType != 0) ) return false;
  334. return true;
  335. }
  336. // internal
  337. void asCScriptFunction::AddReferences()
  338. {
  339. asUINT n;
  340. // Only count references if there is any bytecode
  341. if( byteCode.GetLength() )
  342. {
  343. if( returnType.IsObject() )
  344. returnType.GetObjectType()->AddRef();
  345. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  346. if( parameterTypes[p].IsObject() )
  347. parameterTypes[p].GetObjectType()->AddRef();
  348. }
  349. // TODO: global: The global var address should be stored in the instruction directly
  350. // Go through the byte code and add references to all resources used by the function
  351. for( n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
  352. {
  353. switch( *(asBYTE*)&byteCode[n] )
  354. {
  355. // Object types
  356. case asBC_OBJTYPE:
  357. case asBC_FREE:
  358. case asBC_REFCPY:
  359. {
  360. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  361. objType->AddRef();
  362. }
  363. break;
  364. // Object type and function
  365. case asBC_ALLOC:
  366. {
  367. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  368. objType->AddRef();
  369. int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
  370. if( func )
  371. engine->scriptFunctions[func]->AddRef();
  372. }
  373. break;
  374. // Global variables
  375. case asBC_LDG:
  376. case asBC_PGA:
  377. case asBC_PshG4:
  378. case asBC_SetG4:
  379. case asBC_CpyVtoG4:
  380. // Need to increase the reference for each global variable
  381. {
  382. int gvarIdx = asBC_WORDARG0(&byteCode[n]);
  383. asCConfigGroup *group = GetConfigGroupByGlobalVarPtrIndex(gvarIdx);
  384. if( group != 0 ) group->AddRef();
  385. }
  386. break;
  387. case asBC_LdGRdR4:
  388. case asBC_CpyGtoV4:
  389. // Need to increase the reference for each global variable
  390. {
  391. int gvarIdx = asBC_WORDARG1(&byteCode[n]);
  392. asCConfigGroup *group = GetConfigGroupByGlobalVarPtrIndex(gvarIdx);
  393. if( group != 0 ) group->AddRef();
  394. }
  395. break;
  396. // System functions
  397. case asBC_CALLSYS:
  398. {
  399. int funcId = asBC_INTARG(&byteCode[n]);
  400. asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
  401. if( group != 0 ) group->AddRef();
  402. engine->scriptFunctions[funcId]->AddRef();
  403. }
  404. break;
  405. // Functions
  406. case asBC_CALL:
  407. case asBC_CALLINTF:
  408. {
  409. int func = asBC_INTARG(&byteCode[n]);
  410. engine->scriptFunctions[func]->AddRef();
  411. }
  412. break;
  413. }
  414. }
  415. // Add reference to the global properties
  416. for( n = 0; n < globalVarPointers.GetLength(); n++ )
  417. {
  418. asCGlobalProperty *prop = GetPropertyByGlobalVarPtrIndex(n);
  419. prop->AddRef();
  420. }
  421. }
  422. // internal
  423. void asCScriptFunction::ReleaseReferences()
  424. {
  425. asUINT n;
  426. // Only count references if there is any bytecode
  427. if( byteCode.GetLength() )
  428. {
  429. if( returnType.IsObject() )
  430. returnType.GetObjectType()->Release();
  431. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  432. if( parameterTypes[p].IsObject() )
  433. parameterTypes[p].GetObjectType()->Release();
  434. }
  435. // TODO: global: The global var address should be stored in the instruction directly
  436. // Go through the byte code and release references to all resources used by the function
  437. for( n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
  438. {
  439. switch( *(asBYTE*)&byteCode[n] )
  440. {
  441. // Object types
  442. case asBC_OBJTYPE:
  443. case asBC_FREE:
  444. case asBC_REFCPY:
  445. {
  446. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  447. if( objType )
  448. objType->Release();
  449. }
  450. break;
  451. // Object type and function
  452. case asBC_ALLOC:
  453. {
  454. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  455. if( objType )
  456. objType->Release();
  457. int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
  458. if( func )
  459. engine->scriptFunctions[func]->Release();
  460. }
  461. break;
  462. // Global variables
  463. case asBC_LDG:
  464. case asBC_PGA:
  465. case asBC_PshG4:
  466. case asBC_SetG4:
  467. case asBC_CpyVtoG4:
  468. // Need to decrease the reference for each global variable
  469. {
  470. int gvarIdx = asBC_WORDARG0(&byteCode[n]);
  471. asCConfigGroup *group = GetConfigGroupByGlobalVarPtrIndex(gvarIdx);
  472. if( group != 0 ) group->Release();
  473. }
  474. break;
  475. case asBC_LdGRdR4:
  476. case asBC_CpyGtoV4:
  477. // Need to decrease the reference for each global variable
  478. {
  479. int gvarIdx = asBC_WORDARG1(&byteCode[n]);
  480. asCConfigGroup *group = GetConfigGroupByGlobalVarPtrIndex(gvarIdx);
  481. if( group != 0 ) group->Release();
  482. }
  483. break;
  484. // System functions
  485. case asBC_CALLSYS:
  486. {
  487. int funcId = asBC_INTARG(&byteCode[n]);
  488. asCConfigGroup *group = engine->FindConfigGroupForFunction(funcId);
  489. if( group != 0 ) group->Release();
  490. if( funcId )
  491. engine->scriptFunctions[funcId]->Release();
  492. }
  493. break;
  494. // Functions
  495. case asBC_CALL:
  496. case asBC_CALLINTF:
  497. {
  498. int func = asBC_INTARG(&byteCode[n]);
  499. if( func )
  500. engine->scriptFunctions[func]->Release();
  501. }
  502. break;
  503. }
  504. }
  505. // Release the global properties
  506. for( n = 0; n < globalVarPointers.GetLength(); n++ )
  507. {
  508. asCGlobalProperty *prop = GetPropertyByGlobalVarPtrIndex(n);
  509. prop->Release();
  510. }
  511. // Release the jit compiled function
  512. if( jitFunction )
  513. engine->jitCompiler->ReleaseJITFunction(jitFunction);
  514. jitFunction = 0;
  515. }
  516. // interface
  517. int asCScriptFunction::GetReturnTypeId() const
  518. {
  519. return engine->GetTypeIdFromDataType(returnType);
  520. }
  521. // interface
  522. int asCScriptFunction::GetParamCount() const
  523. {
  524. return (int)parameterTypes.GetLength();
  525. }
  526. // interface
  527. int asCScriptFunction::GetParamTypeId(int index, asDWORD *flags) const
  528. {
  529. if( index < 0 || (unsigned)index >= parameterTypes.GetLength() )
  530. return asINVALID_ARG;
  531. if( flags )
  532. *flags = inOutFlags[index];
  533. return engine->GetTypeIdFromDataType(parameterTypes[index]);
  534. }
  535. // interface
  536. asIScriptEngine *asCScriptFunction::GetEngine() const
  537. {
  538. return engine;
  539. }
  540. // interface
  541. const char *asCScriptFunction::GetDeclaration(bool includeObjectName) const
  542. {
  543. asASSERT(threadManager);
  544. asCString *tempString = &threadManager->GetLocalData()->string;
  545. *tempString = GetDeclarationStr(includeObjectName);
  546. return tempString->AddressOf();
  547. }
  548. // interface
  549. const char *asCScriptFunction::GetScriptSectionName() const
  550. {
  551. if( scriptSectionIdx >= 0 )
  552. return engine->scriptSectionNames[scriptSectionIdx]->AddressOf();
  553. return 0;
  554. }
  555. // interface
  556. const char *asCScriptFunction::GetConfigGroup() const
  557. {
  558. asCConfigGroup *group = engine->FindConfigGroupForFunction(id);
  559. if( group == 0 )
  560. return 0;
  561. return group->groupName.AddressOf();
  562. }
  563. // internal
  564. void asCScriptFunction::JITCompile()
  565. {
  566. asIJITCompiler *jit = engine->GetJITCompiler();
  567. if( !jit )
  568. return;
  569. // Release the previous function, if any
  570. if( jitFunction )
  571. {
  572. engine->jitCompiler->ReleaseJITFunction(jitFunction);
  573. jitFunction = 0;
  574. }
  575. // Compile for native system
  576. int r = jit->CompileFunction(this, &jitFunction);
  577. if( r < 0 )
  578. {
  579. asASSERT( jitFunction == 0 );
  580. }
  581. }
  582. // interface
  583. asDWORD *asCScriptFunction::GetByteCode(asUINT *length)
  584. {
  585. if( length )
  586. *length = (asUINT)byteCode.GetLength();
  587. if( byteCode.GetLength() )
  588. {
  589. return byteCode.AddressOf();
  590. }
  591. return 0;
  592. }
  593. // internal
  594. int asCScriptFunction::GetGlobalVarPtrIndex(int gvarId)
  595. {
  596. void *ptr = engine->globalProperties[gvarId]->GetAddressOfValue();
  597. // Check if this pointer has been stored already
  598. for( int n = 0; n < (signed)globalVarPointers.GetLength(); n++ )
  599. if( globalVarPointers[n] == ptr )
  600. return n;
  601. // Add the new variable to the array
  602. globalVarPointers.PushLast(ptr);
  603. return (int)globalVarPointers.GetLength()-1;
  604. }
  605. // internal
  606. asCConfigGroup *asCScriptFunction::GetConfigGroupByGlobalVarPtrIndex(int index)
  607. {
  608. void *gvarPtr = globalVarPointers[index];
  609. int gvarId = -1;
  610. for( asUINT g = 0; g < engine->registeredGlobalProps.GetLength(); g++ )
  611. {
  612. if( engine->registeredGlobalProps[g] && engine->registeredGlobalProps[g]->GetAddressOfValue() == gvarPtr )
  613. {
  614. gvarId = engine->registeredGlobalProps[g]->id;
  615. break;
  616. }
  617. }
  618. if( gvarId >= 0 )
  619. {
  620. // Find the config group from the property id
  621. return engine->FindConfigGroupForGlobalVar(gvarId);
  622. }
  623. return 0;
  624. }
  625. // internal
  626. asCGlobalProperty *asCScriptFunction::GetPropertyByGlobalVarPtrIndex(int index)
  627. {
  628. void *gvarPtr = globalVarPointers[index];
  629. for( asUINT g = 0; g < engine->globalProperties.GetLength(); g++ )
  630. if( engine->globalProperties[g] && engine->globalProperties[g]->GetAddressOfValue() == gvarPtr )
  631. return engine->globalProperties[g];
  632. return 0;
  633. }
  634. // internal
  635. int asCScriptFunction::GetRefCount()
  636. {
  637. return refCount.get();
  638. }
  639. // internal
  640. void asCScriptFunction::SetFlag()
  641. {
  642. gcFlag = true;
  643. }
  644. // internal
  645. bool asCScriptFunction::GetFlag()
  646. {
  647. return gcFlag;
  648. }
  649. // internal
  650. void asCScriptFunction::EnumReferences(asIScriptEngine *)
  651. {
  652. // Notify the GC of all object types used
  653. if( returnType.IsObject() )
  654. engine->GCEnumCallback(returnType.GetObjectType());
  655. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  656. if( parameterTypes[p].IsObject() )
  657. engine->GCEnumCallback(parameterTypes[p].GetObjectType());
  658. // Notify the GC of all script functions that is accessed
  659. for( asUINT n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
  660. {
  661. switch( *(asBYTE*)&byteCode[n] )
  662. {
  663. case asBC_OBJTYPE:
  664. case asBC_FREE:
  665. case asBC_REFCPY:
  666. {
  667. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  668. engine->GCEnumCallback(objType);
  669. }
  670. break;
  671. case asBC_ALLOC:
  672. {
  673. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  674. engine->GCEnumCallback(objType);
  675. int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
  676. if( func )
  677. engine->GCEnumCallback(engine->scriptFunctions[func]);
  678. }
  679. break;
  680. case asBC_CALL:
  681. case asBC_CALLINTF:
  682. {
  683. int func = asBC_INTARG(&byteCode[n]);
  684. if( func )
  685. engine->GCEnumCallback(engine->scriptFunctions[func]);
  686. }
  687. break;
  688. }
  689. }
  690. }
  691. // internal
  692. void asCScriptFunction::ReleaseAllHandles(asIScriptEngine *)
  693. {
  694. // Release paramaters
  695. if( byteCode.GetLength() )
  696. {
  697. if( returnType.IsObject() )
  698. {
  699. returnType.GetObjectType()->Release();
  700. returnType = asCDataType::CreatePrimitive(ttVoid, false);
  701. }
  702. for( asUINT p = 0; p < parameterTypes.GetLength(); p++ )
  703. if( parameterTypes[p].IsObject() )
  704. {
  705. parameterTypes[p].GetObjectType()->Release();
  706. parameterTypes[p] = asCDataType::CreatePrimitive(ttInt, false);
  707. }
  708. }
  709. // Release all script functions
  710. for( asUINT n = 0; n < byteCode.GetLength(); n += asBCTypeSize[asBCInfo[*(asBYTE*)&byteCode[n]].type] )
  711. {
  712. switch( *(asBYTE*)&byteCode[n] )
  713. {
  714. // Object types
  715. case asBC_OBJTYPE:
  716. case asBC_FREE:
  717. case asBC_REFCPY:
  718. {
  719. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  720. objType->Release();
  721. *(void**)&byteCode[n+1] = 0;
  722. }
  723. break;
  724. case asBC_ALLOC:
  725. {
  726. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(&byteCode[n]);
  727. objType->Release();
  728. *(void**)&byteCode[n+1] = 0;
  729. int func = asBC_INTARG(&byteCode[n]+AS_PTR_SIZE);
  730. if( func )
  731. {
  732. engine->scriptFunctions[func]->Release();
  733. byteCode[n+AS_PTR_SIZE+1] = 0;
  734. }
  735. }
  736. break;
  737. case asBC_CALL:
  738. case asBC_CALLINTF:
  739. {
  740. int func = asBC_INTARG(&byteCode[n]);
  741. if( func )
  742. {
  743. engine->scriptFunctions[func]->Release();
  744. byteCode[n+1] = 0;
  745. }
  746. }
  747. break;
  748. }
  749. }
  750. }
  751. END_AS_NAMESPACE