as_module.cpp 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2021 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_module.cpp
  25. //
  26. // A class that holds a script module
  27. //
  28. #include "as_config.h"
  29. #include "as_module.h"
  30. #include "as_builder.h"
  31. #include "as_context.h"
  32. #include "as_texts.h"
  33. #include "as_debug.h"
  34. #include "as_restore.h"
  35. BEGIN_AS_NAMESPACE
  36. // internal
  37. asCModule::asCModule(const char *name, asCScriptEngine *engine)
  38. {
  39. m_name = name;
  40. m_engine = engine;
  41. m_userData = 0;
  42. m_builder = 0;
  43. m_isGlobalVarInitialized = false;
  44. m_accessMask = 1;
  45. m_defaultNamespace = engine->nameSpaces[0];
  46. }
  47. // internal
  48. asCModule::~asCModule()
  49. {
  50. InternalReset();
  51. // The builder is not removed by InternalReset because it holds the script
  52. // sections that will be built, so we need to explictly remove it now if it exists
  53. if( m_builder )
  54. {
  55. asDELETE(m_builder,asCBuilder);
  56. m_builder = 0;
  57. }
  58. if( m_engine )
  59. {
  60. // Clean the user data
  61. for( asUINT n = 0; n < m_userData.GetLength(); n += 2 )
  62. {
  63. if( m_userData[n+1] )
  64. {
  65. for( asUINT c = 0; c < m_engine->cleanModuleFuncs.GetLength(); c++ )
  66. if( m_engine->cleanModuleFuncs[c].type == m_userData[n] )
  67. m_engine->cleanModuleFuncs[c].cleanFunc(this);
  68. }
  69. }
  70. // Remove the module from the engine
  71. ACQUIREEXCLUSIVE(m_engine->engineRWLock);
  72. // The module must have been discarded before it is deleted
  73. asASSERT( !m_engine->scriptModules.Exists(this) );
  74. m_engine->discardedModules.RemoveValue(this);
  75. RELEASEEXCLUSIVE(m_engine->engineRWLock);
  76. }
  77. }
  78. // interface
  79. void asCModule::Discard()
  80. {
  81. // Reset the global variables already so that no object in the global variables keep the module alive forever.
  82. // If any live object tries to access the global variables during clean up they will fail with a script exception,
  83. // so the application must keep that in mind before discarding a module.
  84. CallExit();
  85. // Keep a local copy of the engine pointer, because once the module is moved do the discarded
  86. // pile, it is possible that another thread might discard it while we are still in here. So no
  87. // further access to members may be done after that
  88. asCScriptEngine *engine = m_engine;
  89. // Instead of deleting the module immediately, move it to the discarded pile
  90. // This will turn it invisible to the application, yet keep it alive until all
  91. // external references to its entities have been released.
  92. ACQUIREEXCLUSIVE(engine->engineRWLock);
  93. if( engine->lastModule == this )
  94. engine->lastModule = 0;
  95. engine->scriptModules.RemoveValue(this);
  96. engine->discardedModules.PushLast(this);
  97. RELEASEEXCLUSIVE(engine->engineRWLock);
  98. // Allow the engine to go over the list of discarded modules to see what can be cleaned up at this moment.
  99. // Don't do this if the engine is already shutting down, as it will be done explicitly by the engine itself with error reporting
  100. if( !engine->shuttingDown )
  101. {
  102. if( engine->ep.autoGarbageCollect )
  103. engine->GarbageCollect();
  104. else
  105. {
  106. // GarbageCollect calls DeleteDiscardedModules, so no need
  107. // to call it again if we already called GarbageCollect
  108. engine->DeleteDiscardedModules();
  109. }
  110. }
  111. }
  112. // interface
  113. void *asCModule::SetUserData(void *data, asPWORD type)
  114. {
  115. // As a thread might add a new new user data at the same time as another
  116. // it is necessary to protect both read and write access to the userData member
  117. ACQUIREEXCLUSIVE(m_engine->engineRWLock);
  118. // It is not intended to store a lot of different types of userdata,
  119. // so a more complex structure like a associative map would just have
  120. // more overhead than a simple array.
  121. for( asUINT n = 0; n < m_userData.GetLength(); n += 2 )
  122. {
  123. if( m_userData[n] == type )
  124. {
  125. void *oldData = reinterpret_cast<void*>(m_userData[n+1]);
  126. m_userData[n+1] = reinterpret_cast<asPWORD>(data);
  127. RELEASEEXCLUSIVE(m_engine->engineRWLock);
  128. return oldData;
  129. }
  130. }
  131. m_userData.PushLast(type);
  132. m_userData.PushLast(reinterpret_cast<asPWORD>(data));
  133. RELEASEEXCLUSIVE(m_engine->engineRWLock);
  134. return 0;
  135. }
  136. // interface
  137. void *asCModule::GetUserData(asPWORD type) const
  138. {
  139. // There may be multiple threads reading, but when
  140. // setting the user data nobody must be reading.
  141. ACQUIRESHARED(m_engine->engineRWLock);
  142. for( asUINT n = 0; n < m_userData.GetLength(); n += 2 )
  143. {
  144. if( m_userData[n] == type )
  145. {
  146. void *ud = reinterpret_cast<void*>(m_userData[n+1]);
  147. RELEASESHARED(m_engine->engineRWLock);
  148. return ud;
  149. }
  150. }
  151. RELEASESHARED(m_engine->engineRWLock);
  152. return 0;
  153. }
  154. // interface
  155. asIScriptEngine *asCModule::GetEngine() const
  156. {
  157. return m_engine;
  158. }
  159. // interface
  160. void asCModule::SetName(const char *in_name)
  161. {
  162. m_name = in_name;
  163. }
  164. // interface
  165. const char *asCModule::GetName() const
  166. {
  167. return m_name.AddressOf();
  168. }
  169. // interface
  170. const char *asCModule::GetDefaultNamespace() const
  171. {
  172. return m_defaultNamespace->name.AddressOf();
  173. }
  174. // interface
  175. int asCModule::SetDefaultNamespace(const char *nameSpace)
  176. {
  177. // TODO: cleanup: This function is similar to asCScriptEngine::SetDefaultNamespace. Can we reuse the code?
  178. if( nameSpace == 0 )
  179. return asINVALID_ARG;
  180. asCString ns = nameSpace;
  181. if( ns != "" )
  182. {
  183. // Make sure the namespace is composed of alternating identifier and ::
  184. size_t pos = 0;
  185. bool expectIdentifier = true;
  186. size_t len;
  187. eTokenType t = ttIdentifier;
  188. for( ; pos < ns.GetLength(); pos += len )
  189. {
  190. t = m_engine->tok.GetToken(ns.AddressOf() + pos, ns.GetLength() - pos, &len);
  191. if( (expectIdentifier && t != ttIdentifier) || (!expectIdentifier && t != ttScope) )
  192. return asINVALID_DECLARATION;
  193. expectIdentifier = !expectIdentifier;
  194. }
  195. // If the namespace ends with :: then strip it off
  196. if( t == ttScope )
  197. ns.SetLength(ns.GetLength()-2);
  198. }
  199. m_defaultNamespace = m_engine->AddNameSpace(ns.AddressOf());
  200. return 0;
  201. }
  202. // interface
  203. int asCModule::AddScriptSection(const char *in_name, const char *in_code, size_t in_codeLength, int in_lineOffset)
  204. {
  205. #ifdef AS_NO_COMPILER
  206. UNUSED_VAR(in_name);
  207. UNUSED_VAR(in_code);
  208. UNUSED_VAR(in_codeLength);
  209. UNUSED_VAR(in_lineOffset);
  210. return asNOT_SUPPORTED;
  211. #else
  212. if( !m_builder )
  213. {
  214. m_builder = asNEW(asCBuilder)(m_engine, this);
  215. if( m_builder == 0 )
  216. return asOUT_OF_MEMORY;
  217. }
  218. return m_builder->AddCode(in_name, in_code, (int)in_codeLength, in_lineOffset, (int)m_engine->GetScriptSectionNameIndex(in_name ? in_name : ""), m_engine->ep.copyScriptSections);
  219. #endif
  220. }
  221. // internal
  222. void asCModule::JITCompile()
  223. {
  224. asIJITCompiler *jit = m_engine->GetJITCompiler();
  225. if( !jit )
  226. return;
  227. for (unsigned int i = 0; i < m_scriptFunctions.GetLength(); i++)
  228. m_scriptFunctions[i]->JITCompile();
  229. }
  230. // interface
  231. int asCModule::Build()
  232. {
  233. #ifdef AS_NO_COMPILER
  234. return asNOT_SUPPORTED;
  235. #else
  236. TimeIt("asCModule::Build");
  237. // Don't allow the module to be rebuilt if there are still
  238. // external references that will need the previous code
  239. // TODO: interface: The asIScriptModule must have a method for querying if the module is used
  240. if( HasExternalReferences(false) )
  241. {
  242. m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE);
  243. return asMODULE_IS_IN_USE;
  244. }
  245. // Only one thread may build at one time
  246. // TODO: It should be possible to have multiple threads perform compilations
  247. int r = m_engine->RequestBuild();
  248. if( r < 0 )
  249. return r;
  250. m_engine->PrepareEngine();
  251. if( m_engine->configFailed )
  252. {
  253. m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  254. m_engine->BuildCompleted();
  255. return asINVALID_CONFIGURATION;
  256. }
  257. InternalReset();
  258. if( !m_builder )
  259. {
  260. m_engine->BuildCompleted();
  261. return asSUCCESS;
  262. }
  263. // Compile the script
  264. r = m_builder->Build();
  265. asDELETE(m_builder,asCBuilder);
  266. m_builder = 0;
  267. if( r < 0 )
  268. {
  269. // Reset module again
  270. InternalReset();
  271. m_engine->BuildCompleted();
  272. return r;
  273. }
  274. JITCompile();
  275. m_engine->PrepareEngine();
  276. #ifdef AS_DEBUG
  277. // Verify that there are no unwanted gaps in the scriptFunctions array.
  278. for( asUINT n = 1; n < m_engine->scriptFunctions.GetLength(); n++ )
  279. {
  280. int id = n;
  281. if( m_engine->scriptFunctions[n] == 0 && !m_engine->freeScriptFunctionIds.Exists(id) )
  282. asASSERT( false );
  283. }
  284. #endif
  285. m_engine->BuildCompleted();
  286. // Initialize global variables
  287. if( r >= 0 && m_engine->ep.initGlobalVarsAfterBuild )
  288. r = ResetGlobalVars(0);
  289. return r;
  290. #endif
  291. }
  292. // interface
  293. int asCModule::ResetGlobalVars(asIScriptContext *ctx)
  294. {
  295. if( m_isGlobalVarInitialized )
  296. CallExit();
  297. return CallInit(ctx);
  298. }
  299. // interface
  300. asIScriptFunction *asCModule::GetFunctionByIndex(asUINT index) const
  301. {
  302. return const_cast<asCScriptFunction*>(m_globalFunctions.Get(index));
  303. }
  304. // internal
  305. int asCModule::CallInit(asIScriptContext *myCtx)
  306. {
  307. if( m_isGlobalVarInitialized )
  308. return asERROR;
  309. // Each global variable needs to be cleared individually
  310. asCSymbolTableIterator<asCGlobalProperty> it = m_scriptGlobals.List();
  311. while( it )
  312. {
  313. asCGlobalProperty *desc = *it;
  314. memset(desc->GetAddressOfValue(), 0, sizeof(asDWORD)*desc->type.GetSizeOnStackDWords());
  315. it++;
  316. }
  317. // Call the init function for each of the global variables
  318. asIScriptContext *ctx = myCtx;
  319. int r = asEXECUTION_FINISHED;
  320. it = m_scriptGlobals.List();
  321. while( it && r == asEXECUTION_FINISHED )
  322. {
  323. asCGlobalProperty *desc = *it;
  324. it++;
  325. if( desc->GetInitFunc() )
  326. {
  327. if( ctx == 0 )
  328. {
  329. ctx = m_engine->RequestContext();
  330. if( ctx == 0 )
  331. break;
  332. }
  333. r = InitGlobalProp(desc, ctx);
  334. }
  335. }
  336. if( ctx && !myCtx )
  337. {
  338. m_engine->ReturnContext(ctx);
  339. ctx = 0;
  340. }
  341. // Even if the initialization failed we need to set the
  342. // flag that the variables have been initialized, otherwise
  343. // the module won't free those variables that really were
  344. // initialized.
  345. m_isGlobalVarInitialized = true;
  346. if( r != asEXECUTION_FINISHED )
  347. return asINIT_GLOBAL_VARS_FAILED;
  348. return asSUCCESS;
  349. }
  350. // internal
  351. // This function assumes the memory for the global property is already cleared
  352. int asCModule::InitGlobalProp(asCGlobalProperty *prop, asIScriptContext *myCtx)
  353. {
  354. // Call the init function for each of the global variables
  355. asIScriptContext *ctx = myCtx;
  356. int r = asEXECUTION_FINISHED;
  357. if( prop->GetInitFunc() )
  358. {
  359. if( ctx == 0 )
  360. {
  361. ctx = m_engine->RequestContext();
  362. if( ctx == 0 )
  363. return asERROR;
  364. }
  365. r = ctx->Prepare(prop->GetInitFunc());
  366. if( r >= 0 )
  367. {
  368. r = ctx->Execute();
  369. if( r != asEXECUTION_FINISHED )
  370. {
  371. asCString msg;
  372. msg.Format(TXT_FAILED_TO_INITIALIZE_s, prop->name.AddressOf());
  373. asCScriptFunction *func = prop->GetInitFunc();
  374. m_engine->WriteMessage(func->scriptData->scriptSectionIdx >= 0 ? m_engine->scriptSectionNames[func->scriptData->scriptSectionIdx]->AddressOf() : "",
  375. func->GetLineNumber(0, 0) & 0xFFFFF,
  376. func->GetLineNumber(0, 0) >> 20,
  377. asMSGTYPE_ERROR,
  378. msg.AddressOf());
  379. if( r == asEXECUTION_EXCEPTION )
  380. {
  381. const asIScriptFunction *function = ctx->GetExceptionFunction();
  382. msg.Format(TXT_EXCEPTION_s_IN_s, ctx->GetExceptionString(), function->GetDeclaration());
  383. m_engine->WriteMessage(function->GetScriptSectionName(),
  384. ctx->GetExceptionLineNumber(),
  385. 0,
  386. asMSGTYPE_INFORMATION,
  387. msg.AddressOf());
  388. }
  389. }
  390. }
  391. }
  392. if( ctx && !myCtx )
  393. {
  394. m_engine->ReturnContext(ctx);
  395. ctx = 0;
  396. }
  397. // Even if the initialization failed we need to set the
  398. // flag that the variables have been initialized, otherwise
  399. // the module won't free those variables that really were
  400. // initialized.
  401. m_isGlobalVarInitialized = true;
  402. if( r != asEXECUTION_FINISHED )
  403. return asINIT_GLOBAL_VARS_FAILED;
  404. return asSUCCESS;
  405. }
  406. // internal
  407. void asCModule::UninitializeGlobalProp(asCGlobalProperty *prop)
  408. {
  409. if (prop == 0)
  410. return;
  411. if (prop->type.IsObject())
  412. {
  413. void **obj = (void**)prop->GetAddressOfValue();
  414. if (*obj)
  415. {
  416. asCObjectType *ot = CastToObjectType(prop->type.GetTypeInfo());
  417. if (ot->flags & asOBJ_REF)
  418. {
  419. asASSERT((ot->flags & asOBJ_NOCOUNT) || ot->beh.release);
  420. if (ot->beh.release)
  421. m_engine->CallObjectMethod(*obj, ot->beh.release);
  422. }
  423. else
  424. {
  425. if (ot->beh.destruct)
  426. m_engine->CallObjectMethod(*obj, ot->beh.destruct);
  427. m_engine->CallFree(*obj);
  428. }
  429. // Set the address to 0 as someone might try to access the variable afterwards
  430. *obj = 0;
  431. }
  432. }
  433. else if (prop->type.IsFuncdef())
  434. {
  435. asCScriptFunction **func = (asCScriptFunction**)prop->GetAddressOfValue();
  436. if (*func)
  437. {
  438. (*func)->Release();
  439. *func = 0;
  440. }
  441. }
  442. }
  443. // internal
  444. void asCModule::CallExit()
  445. {
  446. if( !m_isGlobalVarInitialized ) return;
  447. asCSymbolTableIterator<asCGlobalProperty> it = m_scriptGlobals.List();
  448. while( it )
  449. {
  450. UninitializeGlobalProp(*it);
  451. it++;
  452. }
  453. m_isGlobalVarInitialized = false;
  454. }
  455. // internal
  456. bool asCModule::HasExternalReferences(bool shuttingDown)
  457. {
  458. // Check all entities in the module for any external references.
  459. // If there are any external references the module cannot be deleted yet.
  460. asCSymbolTableIterator<asCGlobalProperty> it = m_scriptGlobals.List();
  461. while (it)
  462. {
  463. asCGlobalProperty *desc = *it;
  464. if (desc->GetInitFunc() && desc->GetInitFunc()->externalRefCount.get())
  465. {
  466. if( !shuttingDown )
  467. return true;
  468. else
  469. {
  470. asCString msg;
  471. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, m_name.AddressOf());
  472. m_engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  473. // TODO: Use a better error message
  474. asCString tmpName = "init " + desc->name;
  475. msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, tmpName.AddressOf(), desc->GetInitFunc()->GetFuncType());
  476. m_engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  477. }
  478. }
  479. it++;
  480. }
  481. for (asUINT n = 0; n < m_scriptFunctions.GetLength(); n++)
  482. {
  483. asCScriptFunction *func = m_scriptFunctions[n];
  484. if (func && func->externalRefCount.get())
  485. {
  486. // If the func is shared and can be moved to another module then this is not a reason to keep the module alive
  487. if (func->IsShared() && m_engine->FindNewOwnerForSharedFunc(func, this) != this)
  488. continue;
  489. if (!shuttingDown)
  490. return true;
  491. else
  492. {
  493. asCString msg;
  494. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, m_name.AddressOf());
  495. m_engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  496. msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, m_scriptFunctions[n]->GetName(), m_scriptFunctions[n]->GetFuncType());
  497. m_engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  498. }
  499. }
  500. }
  501. for (asUINT n = 0; n < m_classTypes.GetLength(); n++)
  502. {
  503. asCObjectType *obj = m_classTypes[n];
  504. if (obj && obj->externalRefCount.get())
  505. {
  506. // If the obj is shared and can be moved to another module then this is not a reason to keep the module alive
  507. if (obj->IsShared() && m_engine->FindNewOwnerForSharedType(obj, this) != this)
  508. continue;
  509. if (!shuttingDown)
  510. return true;
  511. else
  512. {
  513. asCString msg;
  514. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, m_name.AddressOf());
  515. m_engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  516. msg.Format(TXT_PREV_TYPE_IS_NAMED_s, m_classTypes[n]->GetName());
  517. m_engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  518. }
  519. }
  520. }
  521. for (asUINT n = 0; n < m_funcDefs.GetLength(); n++)
  522. {
  523. asCFuncdefType *func = m_funcDefs[n];
  524. if (func && func->externalRefCount.get())
  525. {
  526. // If the funcdef is shared and can be moved to another module then this is not a reason to keep the module alive
  527. if (func->IsShared() && m_engine->FindNewOwnerForSharedType(func, this) != this)
  528. continue;
  529. if (!shuttingDown)
  530. return true;
  531. else
  532. {
  533. asCString msg;
  534. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, m_name.AddressOf());
  535. m_engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  536. msg.Format(TXT_PREV_FUNC_IS_NAMED_s_TYPE_IS_d, m_funcDefs[n]->GetName(), m_funcDefs[n]->funcdef->GetFuncType());
  537. m_engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  538. }
  539. }
  540. }
  541. for (asUINT n = 0; n < m_templateInstances.GetLength(); n++)
  542. {
  543. asCObjectType *obj = m_templateInstances[n];
  544. if (obj && obj->externalRefCount.get())
  545. {
  546. // If the template can be moved to another module then this is not a reason to keep the module alive
  547. if (obj->IsShared() && m_engine->FindNewOwnerForSharedType(obj, this) != this)
  548. continue;
  549. if (!shuttingDown)
  550. return true;
  551. else
  552. {
  553. asCString msg;
  554. msg.Format(TXT_EXTRNL_REF_TO_MODULE_s, m_name.AddressOf());
  555. m_engine->WriteMessage("", 0, 0, asMSGTYPE_WARNING, msg.AddressOf());
  556. msg.Format(TXT_PREV_TYPE_IS_NAMED_s, m_templateInstances[n]->GetName());
  557. m_engine->WriteMessage("", 0, 0, asMSGTYPE_INFORMATION, msg.AddressOf());
  558. }
  559. }
  560. }
  561. return false;
  562. }
  563. // internal
  564. void asCModule::InternalReset()
  565. {
  566. CallExit();
  567. asUINT n;
  568. // Remove all global functions
  569. m_globalFunctions.Clear();
  570. // Destroy the internals of the global properties here, but do not yet remove them from the
  571. // engine, because functions need the engine's varAddressMap to get to the property. If the
  572. // property is removed already, it may leak as the refCount doesn't reach 0.
  573. asCSymbolTableIterator<asCGlobalProperty> globIt = m_scriptGlobals.List();
  574. while( globIt )
  575. {
  576. (*globIt)->DestroyInternal();
  577. globIt++;
  578. }
  579. UnbindAllImportedFunctions();
  580. // Free bind information
  581. for( n = 0; n < m_bindInformations.GetLength(); n++ )
  582. {
  583. if( m_bindInformations[n] )
  584. {
  585. m_bindInformations[n]->importedFunctionSignature->ReleaseInternal();
  586. asDELETE(m_bindInformations[n], sBindInfo);
  587. }
  588. }
  589. m_bindInformations.SetLength(0);
  590. // Free declared types, including classes, typedefs, and enums
  591. for( n = 0; n < m_templateInstances.GetLength(); n++ )
  592. {
  593. asCObjectType *type = m_templateInstances[n];
  594. if( m_engine->FindNewOwnerForSharedType(type, this) != this )
  595. {
  596. // The type is owned by another module, just release our reference
  597. type->ReleaseInternal();
  598. continue;
  599. }
  600. // Orphan the template instance
  601. type->module = 0;
  602. // No other module is holding the template type
  603. m_engine->RemoveTemplateInstanceType(type);
  604. type->ReleaseInternal();
  605. }
  606. m_templateInstances.SetLength(0);
  607. for( n = 0; n < m_classTypes.GetLength(); n++ )
  608. {
  609. asCObjectType *type = m_classTypes[n];
  610. if( type->IsShared() )
  611. {
  612. // The type is shared, so transfer ownership to another module that also uses it
  613. if( m_engine->FindNewOwnerForSharedType(type, this) != this )
  614. {
  615. // The type is owned by another module, just release our reference
  616. type->ReleaseInternal();
  617. continue;
  618. }
  619. }
  620. // The type should be destroyed now
  621. type->DestroyInternal();
  622. // Remove the type from the engine
  623. if( type->IsShared() )
  624. {
  625. m_engine->sharedScriptTypes.RemoveValue(type);
  626. type->ReleaseInternal();
  627. }
  628. // Release it from the module
  629. type->module = 0;
  630. type->ReleaseInternal();
  631. }
  632. m_classTypes.SetLength(0);
  633. for( n = 0; n < m_enumTypes.GetLength(); n++ )
  634. {
  635. asCEnumType *type = m_enumTypes[n];
  636. if( type->IsShared() )
  637. {
  638. // The type is shared, so transfer ownership to another module that also uses it
  639. if( m_engine->FindNewOwnerForSharedType(type, this) != this )
  640. {
  641. // The type is owned by another module, just release our reference
  642. type->ReleaseInternal();
  643. continue;
  644. }
  645. }
  646. // Remove the type from the engine
  647. if( type->IsShared() )
  648. {
  649. m_engine->sharedScriptTypes.RemoveValue(type);
  650. type->ReleaseInternal();
  651. }
  652. // Release it from the module
  653. type->module = 0;
  654. type->ReleaseInternal();
  655. }
  656. m_enumTypes.SetLength(0);
  657. for( n = 0; n < m_typeDefs.GetLength(); n++ )
  658. {
  659. asCTypedefType *type = m_typeDefs[n];
  660. // The type should be destroyed now
  661. type->DestroyInternal();
  662. // Release it from the module
  663. type->module = 0;
  664. type->ReleaseInternal();
  665. }
  666. m_typeDefs.SetLength(0);
  667. // Free funcdefs
  668. for( n = 0; n < m_funcDefs.GetLength(); n++ )
  669. {
  670. asCFuncdefType *func = m_funcDefs[n];
  671. asASSERT(func);
  672. if( func->funcdef && func->funcdef->IsShared() )
  673. {
  674. // The funcdef is shared, so transfer ownership to another module that also uses it
  675. if( m_engine->FindNewOwnerForSharedType(func, this) != this )
  676. {
  677. // The funcdef is owned by another module, just release our reference
  678. func->ReleaseInternal();
  679. continue;
  680. }
  681. }
  682. func->DestroyInternal();
  683. m_engine->RemoveFuncdef(func);
  684. func->module = 0;
  685. func->ReleaseInternal();
  686. }
  687. m_funcDefs.SetLength(0);
  688. // Then release the functions
  689. for( n = 0; n < m_scriptFunctions.GetLength(); n++ )
  690. {
  691. asCScriptFunction *func = m_scriptFunctions[n];
  692. if( func->IsShared() )
  693. {
  694. // The func is shared, so transfer ownership to another module that also uses it
  695. if( m_engine->FindNewOwnerForSharedFunc(func, this) != this )
  696. {
  697. // The func is owned by another module, just release our reference
  698. func->ReleaseInternal();
  699. continue;
  700. }
  701. }
  702. func->DestroyInternal();
  703. func->module = 0;
  704. func->ReleaseInternal();
  705. }
  706. m_scriptFunctions.SetLength(0);
  707. // Now remove and release the global properties as there are no more references to them
  708. globIt = m_scriptGlobals.List();
  709. while( globIt )
  710. {
  711. m_engine->RemoveGlobalProperty(*globIt);
  712. asASSERT( (*globIt)->refCount.get() == 1 );
  713. (*globIt)->Release();
  714. globIt++;
  715. }
  716. m_scriptGlobals.Clear();
  717. // Clear the type lookup
  718. // The references were already released as the types were removed from the respective arrays
  719. m_typeLookup.EraseAll();
  720. asASSERT( IsEmpty() );
  721. }
  722. // interface
  723. asIScriptFunction *asCModule::GetFunctionByName(const char *in_name) const
  724. {
  725. asCString name;
  726. asSNameSpace *ns = 0;
  727. if( m_engine->DetermineNameAndNamespace(in_name, m_defaultNamespace, name, ns) < 0 )
  728. return 0;
  729. // Search recursively in the given namespace, moving up to parent namespace until the function is found
  730. while( ns )
  731. {
  732. const asCArray<unsigned int> &idxs = m_globalFunctions.GetIndexes(ns, name);
  733. if( idxs.GetLength() != 1 )
  734. return 0;
  735. const asIScriptFunction *func = m_globalFunctions.Get(idxs[0]);
  736. if( func )
  737. return const_cast<asIScriptFunction*>(func);
  738. // Recursively search parent namespaces
  739. ns = m_engine->GetParentNameSpace(ns);
  740. }
  741. return 0;
  742. }
  743. // interface
  744. asUINT asCModule::GetImportedFunctionCount() const
  745. {
  746. return (asUINT)m_bindInformations.GetLength();
  747. }
  748. // interface
  749. int asCModule::GetImportedFunctionIndexByDecl(const char *decl) const
  750. {
  751. asCBuilder bld(m_engine, const_cast<asCModule*>(this));
  752. // Don't write parser errors to the message callback
  753. bld.silent = true;
  754. asCScriptFunction func(m_engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  755. bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, m_defaultNamespace);
  756. // TODO: optimize: Improve linear search
  757. // Search script functions for matching interface
  758. int id = -1;
  759. for( asUINT n = 0; n < m_bindInformations.GetLength(); ++n )
  760. {
  761. if( func.name == m_bindInformations[n]->importedFunctionSignature->name &&
  762. func.returnType == m_bindInformations[n]->importedFunctionSignature->returnType &&
  763. func.parameterTypes.GetLength() == m_bindInformations[n]->importedFunctionSignature->parameterTypes.GetLength() )
  764. {
  765. bool match = true;
  766. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  767. {
  768. if( func.parameterTypes[p] != m_bindInformations[n]->importedFunctionSignature->parameterTypes[p] )
  769. {
  770. match = false;
  771. break;
  772. }
  773. }
  774. if( match )
  775. {
  776. if( id == -1 )
  777. id = n;
  778. else
  779. return asMULTIPLE_FUNCTIONS;
  780. }
  781. }
  782. }
  783. if( id == -1 ) return asNO_FUNCTION;
  784. return id;
  785. }
  786. // interface
  787. asUINT asCModule::GetFunctionCount() const
  788. {
  789. return (asUINT)m_globalFunctions.GetSize();
  790. }
  791. // interface
  792. asIScriptFunction *asCModule::GetFunctionByDecl(const char *decl) const
  793. {
  794. asCBuilder bld(m_engine, const_cast<asCModule*>(this));
  795. // Don't write parser errors to the message callback
  796. bld.silent = true;
  797. asCScriptFunction func(m_engine, const_cast<asCModule*>(this), asFUNC_DUMMY);
  798. int r = bld.ParseFunctionDeclaration(0, decl, &func, false, 0, 0, m_defaultNamespace);
  799. if( r < 0 )
  800. {
  801. // Invalid declaration
  802. // TODO: Write error to message stream
  803. return 0;
  804. }
  805. // Use the defaultNamespace implicitly unless an explicit namespace has been provided
  806. asSNameSpace *ns = func.nameSpace == m_engine->nameSpaces[0] ? m_defaultNamespace : func.nameSpace;
  807. // Search script functions for matching interface
  808. while( ns )
  809. {
  810. asIScriptFunction *f = 0;
  811. const asCArray<unsigned int> &idxs = m_globalFunctions.GetIndexes(ns, func.name);
  812. for( unsigned int n = 0; n < idxs.GetLength(); n++ )
  813. {
  814. const asCScriptFunction *funcPtr = m_globalFunctions.Get(idxs[n]);
  815. if( funcPtr->objectType == 0 &&
  816. func.returnType == funcPtr->returnType &&
  817. func.parameterTypes.GetLength() == funcPtr->parameterTypes.GetLength()
  818. )
  819. {
  820. bool match = true;
  821. for( asUINT p = 0; p < func.parameterTypes.GetLength(); ++p )
  822. {
  823. if( func.parameterTypes[p] != funcPtr->parameterTypes[p] )
  824. {
  825. match = false;
  826. break;
  827. }
  828. }
  829. if( match )
  830. {
  831. if( f == 0 )
  832. f = const_cast<asCScriptFunction*>(funcPtr);
  833. else
  834. // Multiple functions
  835. return 0;
  836. }
  837. }
  838. }
  839. if( f )
  840. return f;
  841. else
  842. {
  843. // Search for matching functions in the parent namespace
  844. ns = m_engine->GetParentNameSpace(ns);
  845. }
  846. }
  847. return 0;
  848. }
  849. // interface
  850. asUINT asCModule::GetGlobalVarCount() const
  851. {
  852. return (asUINT)m_scriptGlobals.GetSize();
  853. }
  854. // interface
  855. int asCModule::GetGlobalVarIndexByName(const char *in_name) const
  856. {
  857. asCString name;
  858. asSNameSpace *ns = 0;
  859. if( m_engine->DetermineNameAndNamespace(in_name, m_defaultNamespace, name, ns) < 0 )
  860. return asINVALID_ARG;
  861. // Find the global var id
  862. while( ns )
  863. {
  864. int id = m_scriptGlobals.GetFirstIndex(ns, name);
  865. if( id >= 0 ) return id;
  866. // Recursively search parent namespaces
  867. ns = m_engine->GetParentNameSpace(ns);
  868. }
  869. return asNO_GLOBAL_VAR;
  870. }
  871. // interface
  872. int asCModule::RemoveGlobalVar(asUINT index)
  873. {
  874. asCGlobalProperty *prop = m_scriptGlobals.Get(index);
  875. if( !prop )
  876. return asINVALID_ARG;
  877. // If the global variables have already been initialized
  878. // then uninitialize the variable before it is removed
  879. if (m_isGlobalVarInitialized)
  880. UninitializeGlobalProp(prop);
  881. // Destroy the internal of the global variable (removes the initialization function)
  882. prop->DestroyInternal();
  883. // Check if the module is the only one referring to the property, if so remove it from the engine too
  884. // If the property is not removed now, it will be removed later when the module is discarded
  885. if( prop->refCount.get() == 2 )
  886. m_engine->RemoveGlobalProperty(prop);
  887. // Remove the global variable from the module
  888. m_scriptGlobals.Erase(index);
  889. prop->Release();
  890. return 0;
  891. }
  892. // interface
  893. int asCModule::GetGlobalVarIndexByDecl(const char *decl) const
  894. {
  895. asCBuilder bld(m_engine, const_cast<asCModule*>(this));
  896. // Don't write parser errors to the message callback
  897. bld.silent = true;
  898. asCString declName;
  899. asSNameSpace *nameSpace;
  900. asCDataType dt;
  901. int r = bld.ParseVariableDeclaration(decl, m_defaultNamespace, declName, nameSpace, dt);
  902. if( r < 0 )
  903. return r;
  904. // Search global variables for a match
  905. while( nameSpace )
  906. {
  907. int id = m_scriptGlobals.GetFirstIndex(nameSpace, declName, asCCompGlobPropType(dt));
  908. if( id != -1 )
  909. return id;
  910. // Recursively search parent namespace
  911. nameSpace = m_engine->GetParentNameSpace(nameSpace);
  912. }
  913. return asNO_GLOBAL_VAR;
  914. }
  915. // interface
  916. void *asCModule::GetAddressOfGlobalVar(asUINT index)
  917. {
  918. asCGlobalProperty *prop = m_scriptGlobals.Get(index);
  919. if( !prop )
  920. return 0;
  921. // For object variables it's necessary to dereference the pointer to get the address of the value
  922. if( prop->type.IsObject() &&
  923. !prop->type.IsObjectHandle() )
  924. return *(void**)(prop->GetAddressOfValue());
  925. return (void*)(prop->GetAddressOfValue());
  926. }
  927. // interface
  928. const char *asCModule::GetGlobalVarDeclaration(asUINT index, bool includeNamespace) const
  929. {
  930. const asCGlobalProperty *prop = m_scriptGlobals.Get(index);
  931. if (!prop) return 0;
  932. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  933. *tempString = prop->type.Format(m_defaultNamespace);
  934. *tempString += " ";
  935. if( includeNamespace && prop->nameSpace->name != "" )
  936. *tempString += prop->nameSpace->name + "::";
  937. *tempString += prop->name;
  938. return tempString->AddressOf();
  939. }
  940. // interface
  941. int asCModule::GetGlobalVar(asUINT index, const char **out_name, const char **out_nameSpace, int *out_typeId, bool *out_isConst) const
  942. {
  943. const asCGlobalProperty *prop = m_scriptGlobals.Get(index);
  944. if (!prop) return asINVALID_ARG;
  945. if( out_name )
  946. *out_name = prop->name.AddressOf();
  947. if( out_nameSpace )
  948. *out_nameSpace = prop->nameSpace->name.AddressOf();
  949. if( out_typeId )
  950. *out_typeId = m_engine->GetTypeIdFromDataType(prop->type);
  951. if( out_isConst )
  952. *out_isConst = prop->type.IsReadOnly();
  953. return asSUCCESS;
  954. }
  955. // interface
  956. asUINT asCModule::GetObjectTypeCount() const
  957. {
  958. return (asUINT)m_classTypes.GetLength();
  959. }
  960. // interface
  961. asITypeInfo *asCModule::GetObjectTypeByIndex(asUINT index) const
  962. {
  963. if( index >= m_classTypes.GetLength() )
  964. return 0;
  965. return m_classTypes[index];
  966. }
  967. // interface
  968. asITypeInfo *asCModule::GetTypeInfoByName(const char *in_name) const
  969. {
  970. asCString name;
  971. asSNameSpace *ns = 0;
  972. if( m_engine->DetermineNameAndNamespace(in_name, m_defaultNamespace, name, ns) < 0 )
  973. return 0;
  974. while (ns)
  975. {
  976. asITypeInfo* info = GetType(name, ns);
  977. if(info)
  978. {
  979. return info;
  980. }
  981. // Recursively search parent namespace
  982. ns = m_engine->GetParentNameSpace(ns);
  983. }
  984. return 0;
  985. }
  986. // interface
  987. int asCModule::GetTypeIdByDecl(const char *decl) const
  988. {
  989. asCDataType dt;
  990. // This const cast is safe since we know the engine won't be modified
  991. asCBuilder bld(m_engine, const_cast<asCModule*>(this));
  992. // Don't write parser errors to the message callback
  993. bld.silent = true;
  994. int r = bld.ParseDataType(decl, &dt, m_defaultNamespace);
  995. if( r < 0 )
  996. return asINVALID_TYPE;
  997. return m_engine->GetTypeIdFromDataType(dt);
  998. }
  999. // interface
  1000. asITypeInfo *asCModule::GetTypeInfoByDecl(const char *decl) const
  1001. {
  1002. asCDataType dt;
  1003. // This const cast is safe since we know the engine won't be modified
  1004. asCBuilder bld(m_engine, const_cast<asCModule*>(this));
  1005. // Don't write parser errors to the message callback
  1006. bld.silent = true;
  1007. int r = bld.ParseDataType(decl, &dt, m_defaultNamespace);
  1008. if (r < 0)
  1009. return 0;
  1010. return dt.GetTypeInfo();
  1011. }
  1012. // interface
  1013. asUINT asCModule::GetEnumCount() const
  1014. {
  1015. return m_enumTypes.GetLength();
  1016. }
  1017. // interface
  1018. asITypeInfo *asCModule::GetEnumByIndex(asUINT index) const
  1019. {
  1020. if( index >= m_enumTypes.GetLength() )
  1021. return 0;
  1022. return m_enumTypes[index];
  1023. }
  1024. // interface
  1025. asUINT asCModule::GetTypedefCount() const
  1026. {
  1027. return (asUINT)m_typeDefs.GetLength();
  1028. }
  1029. // interface
  1030. asITypeInfo *asCModule::GetTypedefByIndex(asUINT index) const
  1031. {
  1032. if( index >= m_typeDefs.GetLength() )
  1033. return 0;
  1034. return m_typeDefs[index];
  1035. }
  1036. // internal
  1037. int asCModule::GetNextImportedFunctionId()
  1038. {
  1039. // TODO: multithread: This will break if one thread if freeing a module, while another is being compiled
  1040. if( m_engine->freeImportedFunctionIdxs.GetLength() )
  1041. return FUNC_IMPORTED | (asUINT)m_engine->freeImportedFunctionIdxs[m_engine->freeImportedFunctionIdxs.GetLength()-1];
  1042. return FUNC_IMPORTED | (asUINT)m_engine->importedFunctions.GetLength();
  1043. }
  1044. #ifndef AS_NO_COMPILER
  1045. // internal
  1046. int asCModule::AddScriptFunction(int sectionIdx, int declaredAt, int id, const asCString &funcName, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asCString> &paramNames, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, bool isInterface, asCObjectType *objType, bool isGlobalFunction, asSFunctionTraits funcTraits, asSNameSpace *ns)
  1047. {
  1048. asASSERT(id >= 0);
  1049. // Store the function information
  1050. asCScriptFunction *func = asNEW(asCScriptFunction)(m_engine, this, isInterface ? asFUNC_INTERFACE : asFUNC_SCRIPT);
  1051. if( func == 0 )
  1052. {
  1053. // Free the default args
  1054. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  1055. if( defaultArgs[n] )
  1056. asDELETE(defaultArgs[n], asCString);
  1057. return asOUT_OF_MEMORY;
  1058. }
  1059. if( ns == 0 )
  1060. ns = m_engine->nameSpaces[0];
  1061. // All methods of shared objects are also shared
  1062. if( objType && objType->IsShared() )
  1063. funcTraits.SetTrait(asTRAIT_SHARED, true);
  1064. func->name = funcName;
  1065. func->nameSpace = ns;
  1066. func->id = id;
  1067. func->returnType = returnType;
  1068. if( func->funcType == asFUNC_SCRIPT )
  1069. {
  1070. func->scriptData->scriptSectionIdx = sectionIdx;
  1071. func->scriptData->declaredAt = declaredAt;
  1072. }
  1073. func->parameterTypes = params;
  1074. func->parameterNames = paramNames;
  1075. func->inOutFlags = inOutFlags;
  1076. func->defaultArgs = defaultArgs;
  1077. func->objectType = objType;
  1078. if( objType )
  1079. objType->AddRefInternal();
  1080. func->traits = funcTraits;
  1081. asASSERT( params.GetLength() == inOutFlags.GetLength() && params.GetLength() == defaultArgs.GetLength() );
  1082. // Verify that we are not assigning either the final or override specifier(s) if we are registering a non-member function
  1083. asASSERT( !(!objType && funcTraits.GetTrait(asTRAIT_FINAL)) );
  1084. asASSERT( !(!objType && funcTraits.GetTrait(asTRAIT_OVERRIDE)) );
  1085. // The internal ref count was already set by the constructor
  1086. m_scriptFunctions.PushLast(func);
  1087. m_engine->AddScriptFunction(func);
  1088. // Compute the signature id
  1089. if( objType )
  1090. func->ComputeSignatureId();
  1091. // Add reference
  1092. if( isGlobalFunction )
  1093. m_globalFunctions.Put(func);
  1094. return 0;
  1095. }
  1096. // internal
  1097. int asCModule::AddScriptFunction(asCScriptFunction *func)
  1098. {
  1099. m_scriptFunctions.PushLast(func);
  1100. func->AddRefInternal();
  1101. m_engine->AddScriptFunction(func);
  1102. // If the function that is being added is an already compiled shared function
  1103. // then it is necessary to look for anonymous functions that may be declared
  1104. // within it and add those as well
  1105. if( func->IsShared() && func->funcType == asFUNC_SCRIPT )
  1106. {
  1107. // Loop through the byte code and check all the
  1108. // asBC_FuncPtr instructions for anonymous functions
  1109. asDWORD *bc = func->scriptData->byteCode.AddressOf();
  1110. asUINT bcLength = (asUINT)func->scriptData->byteCode.GetLength();
  1111. for( asUINT n = 0; n < bcLength; )
  1112. {
  1113. int c = *(asBYTE*)&bc[n];
  1114. if( c == asBC_FuncPtr )
  1115. {
  1116. asCScriptFunction *f = reinterpret_cast<asCScriptFunction*>(asBC_PTRARG(&bc[n]));
  1117. // Anonymous functions start with $
  1118. // There are never two equal anonymous functions so it is not necessary to look for duplicates
  1119. if( f && f->name[0] == '$' )
  1120. {
  1121. AddScriptFunction(f);
  1122. m_globalFunctions.Put(f);
  1123. }
  1124. }
  1125. n += asBCTypeSize[asBCInfo[c].type];
  1126. }
  1127. }
  1128. return 0;
  1129. }
  1130. // internal
  1131. int asCModule::AddImportedFunction(int id, const asCString &funcName, const asCDataType &returnType, const asCArray<asCDataType> &params, const asCArray<asETypeModifiers> &inOutFlags, const asCArray<asCString *> &defaultArgs, asSFunctionTraits funcTraits, asSNameSpace *ns, const asCString &moduleName)
  1132. {
  1133. asASSERT(id >= 0);
  1134. // Store the function information
  1135. asCScriptFunction *func = asNEW(asCScriptFunction)(m_engine, this, asFUNC_IMPORTED);
  1136. if( func == 0 )
  1137. {
  1138. // Free the default args
  1139. for( asUINT n = 0; n < defaultArgs.GetLength(); n++ )
  1140. if( defaultArgs[n] )
  1141. asDELETE(defaultArgs[n], asCString);
  1142. return asOUT_OF_MEMORY;
  1143. }
  1144. func->name = funcName;
  1145. func->id = id;
  1146. func->returnType = returnType;
  1147. func->nameSpace = ns;
  1148. func->parameterTypes = params;
  1149. func->inOutFlags = inOutFlags;
  1150. func->defaultArgs = defaultArgs;
  1151. func->objectType = 0;
  1152. func->traits = funcTraits;
  1153. sBindInfo *info = asNEW(sBindInfo);
  1154. if( info == 0 )
  1155. {
  1156. asDELETE(func, asCScriptFunction);
  1157. return asOUT_OF_MEMORY;
  1158. }
  1159. info->importedFunctionSignature = func;
  1160. info->boundFunctionId = -1;
  1161. info->importFromModule = moduleName;
  1162. m_bindInformations.PushLast(info);
  1163. // Add the info to the array in the engine
  1164. if( m_engine->freeImportedFunctionIdxs.GetLength() )
  1165. m_engine->importedFunctions[m_engine->freeImportedFunctionIdxs.PopLast()] = info;
  1166. else
  1167. m_engine->importedFunctions.PushLast(info);
  1168. return 0;
  1169. }
  1170. #endif
  1171. // internal
  1172. asCScriptFunction *asCModule::GetImportedFunction(int index) const
  1173. {
  1174. return m_bindInformations[index]->importedFunctionSignature;
  1175. }
  1176. // interface
  1177. int asCModule::BindImportedFunction(asUINT index, asIScriptFunction *func)
  1178. {
  1179. // First unbind the old function
  1180. int r = UnbindImportedFunction(index);
  1181. if( r < 0 ) return r;
  1182. // Must verify that the interfaces are equal
  1183. asCScriptFunction *dst = GetImportedFunction(index);
  1184. if( dst == 0 ) return asNO_FUNCTION;
  1185. if( func == 0 )
  1186. return asINVALID_ARG;
  1187. asCScriptFunction *src = m_engine->GetScriptFunction(func->GetId());
  1188. if( src == 0 )
  1189. return asNO_FUNCTION;
  1190. // Verify return type
  1191. if( dst->returnType != src->returnType )
  1192. return asINVALID_INTERFACE;
  1193. if( dst->parameterTypes.GetLength() != src->parameterTypes.GetLength() )
  1194. return asINVALID_INTERFACE;
  1195. for( asUINT n = 0; n < dst->parameterTypes.GetLength(); ++n )
  1196. {
  1197. if( dst->parameterTypes[n] != src->parameterTypes[n] )
  1198. return asINVALID_INTERFACE;
  1199. }
  1200. m_bindInformations[index]->boundFunctionId = src->GetId();
  1201. src->AddRefInternal();
  1202. return asSUCCESS;
  1203. }
  1204. // interface
  1205. int asCModule::UnbindImportedFunction(asUINT index)
  1206. {
  1207. if( index >= m_bindInformations.GetLength() )
  1208. return asINVALID_ARG;
  1209. // Remove reference to old module
  1210. if( m_bindInformations[index] )
  1211. {
  1212. int oldFuncID = m_bindInformations[index]->boundFunctionId;
  1213. if( oldFuncID != -1 )
  1214. {
  1215. m_bindInformations[index]->boundFunctionId = -1;
  1216. m_engine->scriptFunctions[oldFuncID]->ReleaseInternal();
  1217. }
  1218. }
  1219. return asSUCCESS;
  1220. }
  1221. // interface
  1222. const char *asCModule::GetImportedFunctionDeclaration(asUINT index) const
  1223. {
  1224. asCScriptFunction *func = GetImportedFunction(index);
  1225. if( func == 0 ) return 0;
  1226. asCString *tempString = &asCThreadManager::GetLocalData()->string;
  1227. // TODO: Allow the application to decide if the parameter name should be included or not (requires change in the interface)
  1228. *tempString = func->GetDeclarationStr(true, true, false);
  1229. return tempString->AddressOf();
  1230. }
  1231. // interface
  1232. const char *asCModule::GetImportedFunctionSourceModule(asUINT index) const
  1233. {
  1234. if( index >= m_bindInformations.GetLength() )
  1235. return 0;
  1236. return m_bindInformations[index]->importFromModule.AddressOf();
  1237. }
  1238. // inteface
  1239. int asCModule::BindAllImportedFunctions()
  1240. {
  1241. bool notAllFunctionsWereBound = false;
  1242. // Bind imported functions
  1243. int c = GetImportedFunctionCount();
  1244. for( int n = 0; n < c; ++n )
  1245. {
  1246. asCScriptFunction *importFunc = GetImportedFunction(n);
  1247. if( importFunc == 0 ) return asERROR;
  1248. asCString str = importFunc->GetDeclarationStr(false, true);
  1249. // Get module name from where the function should be imported
  1250. const char *moduleName = GetImportedFunctionSourceModule(n);
  1251. if( moduleName == 0 ) return asERROR;
  1252. asCModule *srcMod = m_engine->GetModule(moduleName, false);
  1253. asIScriptFunction *func = 0;
  1254. if( srcMod )
  1255. func = srcMod->GetFunctionByDecl(str.AddressOf());
  1256. if( func == 0 )
  1257. notAllFunctionsWereBound = true;
  1258. else
  1259. {
  1260. if( BindImportedFunction(n, func) < 0 )
  1261. notAllFunctionsWereBound = true;
  1262. }
  1263. }
  1264. if( notAllFunctionsWereBound )
  1265. return asCANT_BIND_ALL_FUNCTIONS;
  1266. return asSUCCESS;
  1267. }
  1268. // interface
  1269. int asCModule::UnbindAllImportedFunctions()
  1270. {
  1271. asUINT c = GetImportedFunctionCount();
  1272. for( asUINT n = 0; n < c; ++n )
  1273. UnbindImportedFunction(n);
  1274. return asSUCCESS;
  1275. }
  1276. // internal
  1277. void asCModule::AddClassType(asCObjectType* type)
  1278. {
  1279. m_classTypes.PushLast(type);
  1280. m_typeLookup.Insert(asSNameSpaceNamePair(type->nameSpace, type->name), type);
  1281. }
  1282. // internal
  1283. void asCModule::AddEnumType(asCEnumType* type)
  1284. {
  1285. m_enumTypes.PushLast(type);
  1286. m_typeLookup.Insert(asSNameSpaceNamePair(type->nameSpace, type->name), type);
  1287. }
  1288. // internal
  1289. void asCModule::AddTypeDef(asCTypedefType* type)
  1290. {
  1291. m_typeDefs.PushLast(type);
  1292. m_typeLookup.Insert(asSNameSpaceNamePair(type->nameSpace, type->name), type);
  1293. }
  1294. // internal
  1295. void asCModule::AddFuncDef(asCFuncdefType* type)
  1296. {
  1297. m_funcDefs.PushLast(type);
  1298. m_typeLookup.Insert(asSNameSpaceNamePair(type->nameSpace, type->name), type);
  1299. }
  1300. // internal
  1301. void asCModule::ReplaceFuncDef(asCFuncdefType* type, asCFuncdefType* newType)
  1302. {
  1303. int i = m_funcDefs.IndexOf(type);
  1304. if( i >= 0 )
  1305. {
  1306. m_funcDefs[i] = newType;
  1307. // Replace it in the lookup map too
  1308. asSMapNode<asSNameSpaceNamePair, asCTypeInfo*>* result = 0;
  1309. if(m_typeLookup.MoveTo(&result, asSNameSpaceNamePair(type->nameSpace, type->name)))
  1310. {
  1311. asASSERT( result->value == type );
  1312. result->value = newType;
  1313. }
  1314. }
  1315. }
  1316. // internal
  1317. asCTypeInfo *asCModule::GetType(const asCString &type, asSNameSpace *ns) const
  1318. {
  1319. asSMapNode<asSNameSpaceNamePair, asCTypeInfo*>* result = 0;
  1320. if(m_typeLookup.MoveTo(&result, asSNameSpaceNamePair(ns, type)))
  1321. {
  1322. return result->value;
  1323. }
  1324. return 0;
  1325. }
  1326. // internal
  1327. asCObjectType *asCModule::GetObjectType(const char *type, asSNameSpace *ns) const
  1328. {
  1329. asSMapNode<asSNameSpaceNamePair, asCTypeInfo*>* result = 0;
  1330. if(m_typeLookup.MoveTo(&result, asSNameSpaceNamePair(ns, type)))
  1331. {
  1332. return CastToObjectType(result->value);
  1333. }
  1334. return 0;
  1335. }
  1336. // internal
  1337. asCGlobalProperty *asCModule::AllocateGlobalProperty(const char *propName, const asCDataType &dt, asSNameSpace *ns)
  1338. {
  1339. asCGlobalProperty *prop = m_engine->AllocateGlobalProperty();
  1340. prop->name = propName;
  1341. prop->nameSpace = ns;
  1342. // Allocate the memory for this property based on its type
  1343. prop->type = dt;
  1344. prop->AllocateMemory();
  1345. // Make an entry in the address to variable map
  1346. m_engine->varAddressMap.Insert(prop->GetAddressOfValue(), prop);
  1347. // Store the variable in the module scope
  1348. m_scriptGlobals.Put(prop);
  1349. prop->AddRef();
  1350. return prop;
  1351. }
  1352. // internal
  1353. bool asCModule::IsEmpty() const
  1354. {
  1355. if( m_scriptFunctions.GetLength() ) return false;
  1356. if( m_globalFunctions.GetSize() ) return false;
  1357. if( m_bindInformations.GetLength() ) return false;
  1358. if( m_scriptGlobals.GetSize() ) return false;
  1359. if( m_classTypes.GetLength() ) return false;
  1360. if( m_enumTypes.GetLength() ) return false;
  1361. if( m_typeDefs.GetLength() ) return false;
  1362. if( m_funcDefs.GetLength() ) return false;
  1363. return true;
  1364. }
  1365. // interface
  1366. int asCModule::SaveByteCode(asIBinaryStream *out, bool stripDebugInfo) const
  1367. {
  1368. #ifdef AS_NO_COMPILER
  1369. UNUSED_VAR(out);
  1370. UNUSED_VAR(stripDebugInfo);
  1371. return asNOT_SUPPORTED;
  1372. #else
  1373. if( out == 0 ) return asINVALID_ARG;
  1374. // Make sure there is actually something to save
  1375. if( IsEmpty() )
  1376. return asERROR;
  1377. asCWriter write(const_cast<asCModule*>(this), out, m_engine, stripDebugInfo);
  1378. return write.Write();
  1379. #endif
  1380. }
  1381. // interface
  1382. int asCModule::LoadByteCode(asIBinaryStream *in, bool *wasDebugInfoStripped)
  1383. {
  1384. if( in == 0 ) return asINVALID_ARG;
  1385. // Don't allow the module to be rebuilt if there are still
  1386. // external references that will need the previous code
  1387. if( HasExternalReferences(false) )
  1388. {
  1389. m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_MODULE_IS_IN_USE);
  1390. return asMODULE_IS_IN_USE;
  1391. }
  1392. // Only permit loading bytecode if no other thread is currently compiling
  1393. // TODO: It should be possible to have multiple threads perform compilations
  1394. int r = m_engine->RequestBuild();
  1395. if( r < 0 )
  1396. return r;
  1397. asCReader read(this, in, m_engine);
  1398. r = read.Read(wasDebugInfoStripped);
  1399. if (r < 0)
  1400. {
  1401. m_engine->BuildCompleted();
  1402. return r;
  1403. }
  1404. JITCompile();
  1405. #ifdef AS_DEBUG
  1406. // Verify that there are no unwanted gaps in the scriptFunctions array.
  1407. for( asUINT n = 1; n < m_engine->scriptFunctions.GetLength(); n++ )
  1408. {
  1409. int id = n;
  1410. if( m_engine->scriptFunctions[n] == 0 && !m_engine->freeScriptFunctionIds.Exists(id) )
  1411. asASSERT( false );
  1412. }
  1413. #endif
  1414. m_engine->BuildCompleted();
  1415. return r;
  1416. }
  1417. // interface
  1418. int asCModule::CompileGlobalVar(const char *sectionName, const char *code, int lineOffset)
  1419. {
  1420. #ifdef AS_NO_COMPILER
  1421. UNUSED_VAR(sectionName);
  1422. UNUSED_VAR(code);
  1423. UNUSED_VAR(lineOffset);
  1424. return asNOT_SUPPORTED;
  1425. #else
  1426. // Validate arguments
  1427. if( code == 0 )
  1428. return asINVALID_ARG;
  1429. // Only one thread may build at one time
  1430. // TODO: It should be possible to have multiple threads perform compilations
  1431. int r = m_engine->RequestBuild();
  1432. if( r < 0 )
  1433. return r;
  1434. // Prepare the engine
  1435. m_engine->PrepareEngine();
  1436. if( m_engine->configFailed )
  1437. {
  1438. m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  1439. m_engine->BuildCompleted();
  1440. return asINVALID_CONFIGURATION;
  1441. }
  1442. // Compile the global variable and add it to the module scope
  1443. asCBuilder varBuilder(m_engine, this);
  1444. asCString str = code;
  1445. r = varBuilder.CompileGlobalVar(sectionName, str.AddressOf(), lineOffset);
  1446. m_engine->BuildCompleted();
  1447. // Initialize the variable
  1448. if( r >= 0 )
  1449. {
  1450. // Clear the memory
  1451. asCGlobalProperty *prop = m_scriptGlobals.GetLast();
  1452. if( prop )
  1453. {
  1454. memset(prop->GetAddressOfValue(), 0, sizeof(asDWORD)*prop->type.GetSizeOnStackDWords());
  1455. }
  1456. if( prop && m_engine->ep.initGlobalVarsAfterBuild )
  1457. {
  1458. // Flag that there are initialized global variables
  1459. m_isGlobalVarInitialized = true;
  1460. r = InitGlobalProp(prop, 0);
  1461. }
  1462. }
  1463. return r;
  1464. #endif
  1465. }
  1466. // interface
  1467. int asCModule::CompileFunction(const char* sectionName, const char* code, int lineOffset, asDWORD compileFlags, asIScriptFunction** outFunc)
  1468. {
  1469. // Make sure the outFunc is null if the function fails, so the
  1470. // application doesn't attempt to release a non-existent function
  1471. if (outFunc)
  1472. *outFunc = 0;
  1473. #ifdef AS_NO_COMPILER
  1474. UNUSED_VAR(sectionName);
  1475. UNUSED_VAR(code);
  1476. UNUSED_VAR(lineOffset);
  1477. UNUSED_VAR(compileFlags);
  1478. return asNOT_SUPPORTED;
  1479. #else
  1480. // Validate arguments
  1481. if (code == 0 ||
  1482. (compileFlags != 0 && compileFlags != asCOMP_ADD_TO_MODULE))
  1483. return asINVALID_ARG;
  1484. // Only one thread may build at one time
  1485. // TODO: It should be possible to have multiple threads perform compilations
  1486. int r = m_engine->RequestBuild();
  1487. if (r < 0)
  1488. return r;
  1489. // Prepare the engine
  1490. m_engine->PrepareEngine();
  1491. if (m_engine->configFailed)
  1492. {
  1493. m_engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_INVALID_CONFIGURATION);
  1494. m_engine->BuildCompleted();
  1495. return asINVALID_CONFIGURATION;
  1496. }
  1497. // Compile the single function
  1498. asCBuilder funcBuilder(m_engine, this);
  1499. asCString str = code;
  1500. asCScriptFunction* func = 0;
  1501. r = funcBuilder.CompileFunction(sectionName, str.AddressOf(), lineOffset, compileFlags, &func);
  1502. if (r >= 0)
  1503. {
  1504. // Invoke the JIT compiler if it has been set
  1505. asIJITCompiler* jit = m_engine->GetJITCompiler();
  1506. if (jit)
  1507. {
  1508. func->JITCompile();
  1509. }
  1510. }
  1511. m_engine->BuildCompleted();
  1512. if( r >= 0 && outFunc && func )
  1513. {
  1514. // Return the function to the caller and add an external reference
  1515. *outFunc = func;
  1516. func->AddRef();
  1517. }
  1518. // Release our reference to the function
  1519. if( func )
  1520. func->ReleaseInternal();
  1521. return r;
  1522. #endif
  1523. }
  1524. // interface
  1525. int asCModule::RemoveFunction(asIScriptFunction *func)
  1526. {
  1527. // Find the global function
  1528. asCScriptFunction *f = static_cast<asCScriptFunction*>(func);
  1529. int idx = m_globalFunctions.GetIndex(f);
  1530. if( idx >= 0 )
  1531. {
  1532. m_globalFunctions.Erase(idx);
  1533. m_scriptFunctions.RemoveValue(f);
  1534. f->ReleaseInternal();
  1535. return 0;
  1536. }
  1537. return asNO_FUNCTION;
  1538. }
  1539. #ifndef AS_NO_COMPILER
  1540. // internal
  1541. int asCModule::AddFuncDef(const asCString &funcName, asSNameSpace *ns, asCObjectType *parent)
  1542. {
  1543. // namespace and parent are mutually exclusive
  1544. asASSERT((ns == 0 && parent) || (ns && parent == 0));
  1545. asCScriptFunction *func = asNEW(asCScriptFunction)(m_engine, 0, asFUNC_FUNCDEF);
  1546. if (func == 0)
  1547. return asOUT_OF_MEMORY;
  1548. func->name = funcName;
  1549. func->nameSpace = ns;
  1550. func->module = this;
  1551. asCFuncdefType *fdt = asNEW(asCFuncdefType)(m_engine, func);
  1552. AddFuncDef(fdt); // The constructor set the refcount to 1
  1553. m_engine->funcDefs.PushLast(fdt); // doesn't increase refcount
  1554. func->id = m_engine->GetNextScriptFunctionId();
  1555. m_engine->AddScriptFunction(func);
  1556. if (parent)
  1557. {
  1558. parent->childFuncDefs.PushLast(fdt);
  1559. fdt->parentClass = parent;
  1560. }
  1561. return (int)m_funcDefs.GetLength()-1;
  1562. }
  1563. #endif
  1564. // interface
  1565. asDWORD asCModule::SetAccessMask(asDWORD mask)
  1566. {
  1567. asDWORD old = m_accessMask;
  1568. m_accessMask = mask;
  1569. return old;
  1570. }
  1571. END_AS_NAMESPACE