as_context.cpp 106 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279128012811282128312841285128612871288128912901291129212931294129512961297129812991300130113021303130413051306130713081309131013111312131313141315131613171318131913201321132213231324132513261327132813291330133113321333133413351336133713381339134013411342134313441345134613471348134913501351135213531354135513561357135813591360136113621363136413651366136713681369137013711372137313741375137613771378137913801381138213831384138513861387138813891390139113921393139413951396139713981399140014011402140314041405140614071408140914101411141214131414141514161417141814191420142114221423142414251426142714281429143014311432143314341435143614371438143914401441144214431444144514461447144814491450145114521453145414551456145714581459146014611462146314641465146614671468146914701471147214731474147514761477147814791480148114821483148414851486148714881489149014911492149314941495149614971498149915001501150215031504150515061507150815091510151115121513151415151516151715181519152015211522152315241525152615271528152915301531153215331534153515361537153815391540154115421543154415451546154715481549155015511552155315541555155615571558155915601561156215631564156515661567156815691570157115721573157415751576157715781579158015811582158315841585158615871588158915901591159215931594159515961597159815991600160116021603160416051606160716081609161016111612161316141615161616171618161916201621162216231624162516261627162816291630163116321633163416351636163716381639164016411642164316441645164616471648164916501651165216531654165516561657165816591660166116621663166416651666166716681669167016711672167316741675167616771678167916801681168216831684168516861687168816891690169116921693169416951696169716981699170017011702170317041705170617071708170917101711171217131714171517161717171817191720172117221723172417251726172717281729173017311732173317341735173617371738173917401741174217431744174517461747174817491750175117521753175417551756175717581759176017611762176317641765176617671768176917701771177217731774177517761777177817791780178117821783178417851786178717881789179017911792179317941795179617971798179918001801180218031804180518061807180818091810181118121813181418151816181718181819182018211822182318241825182618271828182918301831183218331834183518361837183818391840184118421843184418451846184718481849185018511852185318541855185618571858185918601861186218631864186518661867186818691870187118721873187418751876187718781879188018811882188318841885188618871888188918901891189218931894189518961897189818991900190119021903190419051906190719081909191019111912191319141915191619171918191919201921192219231924192519261927192819291930193119321933193419351936193719381939194019411942194319441945194619471948194919501951195219531954195519561957195819591960196119621963196419651966196719681969197019711972197319741975197619771978197919801981198219831984198519861987198819891990199119921993199419951996199719981999200020012002200320042005200620072008200920102011201220132014201520162017201820192020202120222023202420252026202720282029203020312032203320342035203620372038203920402041204220432044204520462047204820492050205120522053205420552056205720582059206020612062206320642065206620672068206920702071207220732074207520762077207820792080208120822083208420852086208720882089209020912092209320942095209620972098209921002101210221032104210521062107210821092110211121122113211421152116211721182119212021212122212321242125212621272128212921302131213221332134213521362137213821392140214121422143214421452146214721482149215021512152215321542155215621572158215921602161216221632164216521662167216821692170217121722173217421752176217721782179218021812182218321842185218621872188218921902191219221932194219521962197219821992200220122022203220422052206220722082209221022112212221322142215221622172218221922202221222222232224222522262227222822292230223122322233223422352236223722382239224022412242224322442245224622472248224922502251225222532254225522562257225822592260226122622263226422652266226722682269227022712272227322742275227622772278227922802281228222832284228522862287228822892290229122922293229422952296229722982299230023012302230323042305230623072308230923102311231223132314231523162317231823192320232123222323232423252326232723282329233023312332233323342335233623372338233923402341234223432344234523462347234823492350235123522353235423552356235723582359236023612362236323642365236623672368236923702371237223732374237523762377237823792380238123822383238423852386238723882389239023912392239323942395239623972398239924002401240224032404240524062407240824092410241124122413241424152416241724182419242024212422242324242425242624272428242924302431243224332434243524362437243824392440244124422443244424452446244724482449245024512452245324542455245624572458245924602461246224632464246524662467246824692470247124722473247424752476247724782479248024812482248324842485248624872488248924902491249224932494249524962497249824992500250125022503250425052506250725082509251025112512251325142515251625172518251925202521252225232524252525262527252825292530253125322533253425352536253725382539254025412542254325442545254625472548254925502551255225532554255525562557255825592560256125622563256425652566256725682569257025712572257325742575257625772578257925802581258225832584258525862587258825892590259125922593259425952596259725982599260026012602260326042605260626072608260926102611261226132614261526162617261826192620262126222623262426252626262726282629263026312632263326342635263626372638263926402641264226432644264526462647264826492650265126522653265426552656265726582659266026612662266326642665266626672668266926702671267226732674267526762677267826792680268126822683268426852686268726882689269026912692269326942695269626972698269927002701270227032704270527062707270827092710271127122713271427152716271727182719272027212722272327242725272627272728272927302731273227332734273527362737273827392740274127422743274427452746274727482749275027512752275327542755275627572758275927602761276227632764276527662767276827692770277127722773277427752776277727782779278027812782278327842785278627872788278927902791279227932794279527962797279827992800280128022803280428052806280728082809281028112812281328142815281628172818281928202821282228232824282528262827282828292830283128322833283428352836283728382839284028412842284328442845284628472848284928502851285228532854285528562857285828592860286128622863286428652866286728682869287028712872287328742875287628772878287928802881288228832884288528862887288828892890289128922893289428952896289728982899290029012902290329042905290629072908290929102911291229132914291529162917291829192920292129222923292429252926292729282929293029312932293329342935293629372938293929402941294229432944294529462947294829492950295129522953295429552956295729582959296029612962296329642965296629672968296929702971297229732974297529762977297829792980298129822983298429852986298729882989299029912992299329942995299629972998299930003001300230033004300530063007300830093010301130123013301430153016301730183019302030213022302330243025302630273028302930303031303230333034303530363037303830393040304130423043304430453046304730483049305030513052305330543055305630573058305930603061306230633064306530663067306830693070307130723073307430753076307730783079308030813082308330843085308630873088308930903091309230933094309530963097309830993100310131023103310431053106310731083109311031113112311331143115311631173118311931203121312231233124312531263127312831293130313131323133313431353136313731383139314031413142314331443145314631473148314931503151315231533154315531563157315831593160316131623163316431653166316731683169317031713172317331743175317631773178317931803181318231833184318531863187318831893190319131923193319431953196319731983199320032013202320332043205320632073208320932103211321232133214321532163217321832193220322132223223322432253226322732283229323032313232323332343235323632373238323932403241324232433244324532463247324832493250325132523253325432553256325732583259326032613262326332643265326632673268326932703271327232733274327532763277327832793280328132823283328432853286328732883289329032913292329332943295329632973298329933003301330233033304330533063307330833093310331133123313331433153316331733183319332033213322332333243325332633273328332933303331333233333334333533363337333833393340334133423343334433453346334733483349335033513352335333543355335633573358335933603361336233633364336533663367336833693370337133723373337433753376337733783379338033813382338333843385338633873388338933903391339233933394339533963397339833993400340134023403340434053406340734083409341034113412341334143415341634173418341934203421342234233424342534263427342834293430343134323433343434353436343734383439344034413442344334443445344634473448344934503451345234533454345534563457345834593460346134623463346434653466346734683469347034713472347334743475347634773478347934803481348234833484348534863487348834893490349134923493349434953496349734983499350035013502350335043505350635073508350935103511351235133514351535163517351835193520352135223523352435253526352735283529353035313532353335343535353635373538353935403541354235433544354535463547354835493550355135523553355435553556355735583559356035613562356335643565356635673568356935703571357235733574357535763577357835793580358135823583358435853586358735883589359035913592359335943595359635973598359936003601360236033604360536063607360836093610361136123613361436153616361736183619362036213622362336243625362636273628362936303631363236333634363536363637363836393640364136423643364436453646364736483649365036513652365336543655365636573658365936603661366236633664366536663667366836693670367136723673367436753676367736783679368036813682368336843685368636873688368936903691369236933694369536963697369836993700370137023703370437053706370737083709371037113712371337143715371637173718371937203721372237233724372537263727372837293730373137323733373437353736373737383739374037413742374337443745374637473748374937503751375237533754375537563757375837593760376137623763376437653766376737683769377037713772377337743775377637773778377937803781378237833784378537863787378837893790379137923793379437953796379737983799380038013802380338043805380638073808380938103811381238133814381538163817381838193820382138223823382438253826382738283829383038313832383338343835383638373838383938403841384238433844384538463847384838493850385138523853385438553856385738583859386038613862386338643865386638673868386938703871387238733874387538763877387838793880388138823883388438853886388738883889389038913892389338943895389638973898389939003901390239033904390539063907390839093910391139123913391439153916391739183919392039213922392339243925392639273928392939303931393239333934393539363937393839393940394139423943394439453946394739483949395039513952395339543955395639573958395939603961396239633964396539663967396839693970397139723973397439753976397739783979398039813982398339843985398639873988398939903991399239933994399539963997399839994000400140024003400440054006400740084009401040114012401340144015401640174018401940204021402240234024402540264027402840294030403140324033403440354036403740384039404040414042404340444045404640474048404940504051405240534054405540564057405840594060406140624063406440654066406740684069
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2010 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. // Modified by Lasse Öörni for Urho3D
  24. //
  25. // as_context.cpp
  26. //
  27. // This class handles the execution of the byte code
  28. //
  29. #include <math.h> // fmodf()
  30. #include "as_config.h"
  31. #include "as_context.h"
  32. #include "as_scriptengine.h"
  33. #include "as_tokendef.h"
  34. #include "as_texts.h"
  35. #include "as_callfunc.h"
  36. #include "as_generic.h"
  37. #include "as_debug.h" // mkdir()
  38. #include "as_bytecode.h"
  39. #include "as_scriptobject.h"
  40. #ifdef _MSC_VER
  41. #pragma warning(disable:4702) // unreachable code
  42. #endif
  43. BEGIN_AS_NAMESPACE
  44. // We need at least 2 DWORDs reserved for exception handling
  45. // We need at least 1 DWORD reserved for calling system functions
  46. const int RESERVE_STACK = 2*AS_PTR_SIZE;
  47. // For each script function call we push 5 DWORDs on the call stack
  48. const int CALLSTACK_FRAME_SIZE = 5;
  49. #ifdef AS_DEBUG
  50. // Instruction statistics
  51. int instrCount[256];
  52. int instrCount2[256][256];
  53. int lastBC;
  54. class asCDebugStats
  55. {
  56. public:
  57. asCDebugStats()
  58. {
  59. memset(instrCount, 0, sizeof(instrCount));
  60. }
  61. ~asCDebugStats()
  62. {
  63. /*
  64. // This code writes out some statistics for the VM.
  65. // It's useful for determining what needs to be optimized.
  66. _mkdir("AS_DEBUG");
  67. FILE *f = fopen("AS_DEBUG/total.txt", "at");
  68. if( f )
  69. {
  70. // Output instruction statistics
  71. fprintf(f, "\nTotal count\n");
  72. int n;
  73. for( n = 0; n < BC_MAXBYTECODE; n++ )
  74. {
  75. if( bcName[n].name && instrCount[n] > 0 )
  76. fprintf(f, "%-10.10s : %.0f\n", bcName[n].name, instrCount[n]);
  77. }
  78. fprintf(f, "\nNever executed\n");
  79. for( n = 0; n < BC_MAXBYTECODE; n++ )
  80. {
  81. if( bcName[n].name && instrCount[n] == 0 )
  82. fprintf(f, "%-10.10s\n", bcName[n].name);
  83. }
  84. fclose(f);
  85. }
  86. */
  87. }
  88. double instrCount[256];
  89. } stats;
  90. #endif
  91. AS_API asIScriptContext *asGetActiveContext()
  92. {
  93. // Urho3D: modified to allow querying for a context without having the engine instantiated
  94. if (!threadManager)
  95. return 0;
  96. asCThreadLocalData *tld = threadManager->GetLocalData();
  97. if( tld->activeContexts.GetLength() == 0 )
  98. return 0;
  99. return tld->activeContexts[tld->activeContexts.GetLength()-1];
  100. }
  101. void asPushActiveContext(asIScriptContext *ctx)
  102. {
  103. asASSERT(threadManager);
  104. asCThreadLocalData *tld = threadManager->GetLocalData();
  105. tld->activeContexts.PushLast(ctx);
  106. }
  107. void asPopActiveContext(asIScriptContext *ctx)
  108. {
  109. asASSERT(threadManager);
  110. asCThreadLocalData *tld = threadManager->GetLocalData();
  111. asASSERT(tld->activeContexts.GetLength() > 0);
  112. asASSERT(tld->activeContexts[tld->activeContexts.GetLength()-1] == ctx);
  113. UNUSED_VAR(ctx);
  114. tld->activeContexts.PopLast();
  115. }
  116. asCContext::asCContext(asCScriptEngine *engine, bool holdRef)
  117. {
  118. #ifdef AS_DEBUG
  119. memset(instrCount, 0, sizeof(instrCount));
  120. memset(instrCount2, 0, sizeof(instrCount2));
  121. lastBC = 255;
  122. #endif
  123. holdEngineRef = holdRef;
  124. if( holdRef )
  125. engine->AddRef();
  126. this->engine = engine;
  127. status = asEXECUTION_UNINITIALIZED;
  128. stackBlockSize = 0;
  129. refCount.set(1);
  130. inExceptionHandler = false;
  131. isStackMemoryNotAllocated = false;
  132. currentFunction = 0;
  133. regs.objectRegister = 0;
  134. initialFunction = 0;
  135. lineCallback = false;
  136. exceptionCallback = false;
  137. regs.doProcessSuspend = false;
  138. doSuspend = false;
  139. userData = 0;
  140. }
  141. asCContext::~asCContext()
  142. {
  143. DetachEngine();
  144. }
  145. int asCContext::AddRef() const
  146. {
  147. return refCount.atomicInc();
  148. }
  149. int asCContext::Release() const
  150. {
  151. int r = refCount.atomicDec();
  152. if( r == 0 )
  153. {
  154. asDELETE(const_cast<asCContext*>(this),asCContext);
  155. return 0;
  156. }
  157. return r;
  158. }
  159. void asCContext::DetachEngine()
  160. {
  161. if( engine == 0 ) return;
  162. // Abort any execution
  163. Abort();
  164. // Free all resources
  165. Unprepare();
  166. // Clean the user data
  167. if( userData && engine->cleanContextFunc )
  168. engine->cleanContextFunc(this);
  169. // Clear engine pointer
  170. if( holdEngineRef )
  171. engine->Release();
  172. engine = 0;
  173. }
  174. asIScriptEngine *asCContext::GetEngine() const
  175. {
  176. return engine;
  177. }
  178. void *asCContext::SetUserData(void *data)
  179. {
  180. void *oldData = userData;
  181. userData = data;
  182. return oldData;
  183. }
  184. void *asCContext::GetUserData() const
  185. {
  186. return userData;
  187. }
  188. int asCContext::Prepare(int funcID)
  189. {
  190. if( status == asEXECUTION_ACTIVE || status == asEXECUTION_SUSPENDED )
  191. return asCONTEXT_ACTIVE;
  192. // Clean the stack if not done before
  193. if( status != asEXECUTION_FINISHED && status != asEXECUTION_UNINITIALIZED )
  194. CleanStack();
  195. // Release the returned object (if any)
  196. CleanReturnObject();
  197. if( funcID == -1 )
  198. {
  199. // Use the previously prepared function
  200. if( initialFunction == 0 )
  201. return asNO_FUNCTION;
  202. currentFunction = initialFunction;
  203. }
  204. else if( initialFunction && initialFunction->id == funcID )
  205. {
  206. currentFunction = initialFunction;
  207. }
  208. else
  209. {
  210. // Check engine pointer
  211. asASSERT( engine );
  212. if( initialFunction )
  213. initialFunction->Release();
  214. initialFunction = engine->GetScriptFunction(funcID);
  215. if( initialFunction == 0 )
  216. return asNO_FUNCTION;
  217. initialFunction->AddRef();
  218. currentFunction = initialFunction;
  219. // Determine the minimum stack size needed
  220. // TODO: optimize: GetSpaceNeededForArguments() should be precomputed
  221. int stackSize = currentFunction->GetSpaceNeededForArguments() + currentFunction->stackNeeded + RESERVE_STACK;
  222. stackSize = stackSize > engine->initialContextStackSize ? stackSize : engine->initialContextStackSize;
  223. if( stackSize > stackBlockSize )
  224. {
  225. for( asUINT n = 0; n < stackBlocks.GetLength(); n++ )
  226. if( stackBlocks[n] )
  227. {
  228. asDELETEARRAY(stackBlocks[n]);
  229. }
  230. stackBlocks.SetLength(0);
  231. stackBlockSize = stackSize;
  232. asDWORD *stack = asNEWARRAY(asDWORD,stackBlockSize);
  233. stackBlocks.PushLast(stack);
  234. }
  235. // Reserve space for the arguments and return value
  236. returnValueSize = currentFunction->GetSpaceNeededForReturnValue();
  237. // TODO: optimize: GetSpaceNeededForArguments() should be precomputed
  238. argumentsSize = currentFunction->GetSpaceNeededForArguments() + (currentFunction->objectType ? AS_PTR_SIZE : 0);
  239. }
  240. // Reset state
  241. // Most of the time the previous state will be asEXECUTION_FINISHED, in which case the values are already initialized
  242. if( status != asEXECUTION_FINISHED )
  243. {
  244. exceptionLine = -1;
  245. exceptionFunction = 0;
  246. isCallingSystemFunction = false;
  247. doAbort = false;
  248. doSuspend = false;
  249. regs.doProcessSuspend = lineCallback;
  250. externalSuspendRequest = false;
  251. stackIndex = 0;
  252. }
  253. status = asEXECUTION_PREPARED;
  254. // Reserve space for the arguments and return value
  255. regs.stackFramePointer = stackBlocks[0] + stackBlockSize - argumentsSize;
  256. regs.stackPointer = regs.stackFramePointer;
  257. // Set arguments to 0
  258. memset(regs.stackPointer, 0, 4*argumentsSize);
  259. if( currentFunction->funcType == asFUNC_SCRIPT )
  260. {
  261. regs.programPointer = currentFunction->byteCode.AddressOf();
  262. // Set all object variables to 0
  263. for( asUINT n = 0; n < currentFunction->objVariablePos.GetLength(); n++ )
  264. {
  265. if( !currentFunction->objVariableIsOnHeap[n] ) continue;
  266. int pos = currentFunction->objVariablePos[n];
  267. *(size_t*)&regs.stackFramePointer[-pos] = 0;
  268. }
  269. }
  270. else
  271. regs.programPointer = 0;
  272. return asSUCCESS;
  273. }
  274. // Free all resources
  275. int asCContext::Unprepare()
  276. {
  277. if( status == asEXECUTION_ACTIVE || status == asEXECUTION_SUSPENDED )
  278. return asCONTEXT_ACTIVE;
  279. // Only clean the stack if the context was prepared but not executed until the end
  280. if( status != asEXECUTION_UNINITIALIZED &&
  281. status != asEXECUTION_FINISHED )
  282. CleanStack();
  283. // Release the returned object (if any)
  284. CleanReturnObject();
  285. // Release the initial function
  286. if( initialFunction )
  287. initialFunction->Release();
  288. // Clear function pointers
  289. initialFunction = 0;
  290. currentFunction = 0;
  291. exceptionFunction = 0;
  292. regs.programPointer = 0;
  293. // Reset status
  294. status = asEXECUTION_UNINITIALIZED;
  295. // Deallocate the stack blocks
  296. for( asUINT n = 0; n < stackBlocks.GetLength(); n++ )
  297. {
  298. if( stackBlocks[n] )
  299. {
  300. asDELETEARRAY(stackBlocks[n]);
  301. }
  302. }
  303. stackBlocks.SetLength(0);
  304. stackBlockSize = 0;
  305. regs.stackFramePointer = 0;
  306. regs.stackPointer = 0;
  307. stackIndex = 0;
  308. return 0;
  309. }
  310. asBYTE asCContext::GetReturnByte()
  311. {
  312. if( status != asEXECUTION_FINISHED ) return 0;
  313. asCDataType *dt = &initialFunction->returnType;
  314. if( dt->IsObject() || dt->IsReference() ) return 0;
  315. return *(asBYTE*)&regs.valueRegister;
  316. }
  317. asWORD asCContext::GetReturnWord()
  318. {
  319. if( status != asEXECUTION_FINISHED ) return 0;
  320. asCDataType *dt = &initialFunction->returnType;
  321. if( dt->IsObject() || dt->IsReference() ) return 0;
  322. return *(asWORD*)&regs.valueRegister;
  323. }
  324. asDWORD asCContext::GetReturnDWord()
  325. {
  326. if( status != asEXECUTION_FINISHED ) return 0;
  327. asCDataType *dt = &initialFunction->returnType;
  328. if( dt->IsObject() || dt->IsReference() ) return 0;
  329. return *(asDWORD*)&regs.valueRegister;
  330. }
  331. asQWORD asCContext::GetReturnQWord()
  332. {
  333. if( status != asEXECUTION_FINISHED ) return 0;
  334. asCDataType *dt = &initialFunction->returnType;
  335. if( dt->IsObject() || dt->IsReference() ) return 0;
  336. return regs.valueRegister;
  337. }
  338. float asCContext::GetReturnFloat()
  339. {
  340. if( status != asEXECUTION_FINISHED ) return 0;
  341. asCDataType *dt = &initialFunction->returnType;
  342. if( dt->IsObject() || dt->IsReference() ) return 0;
  343. return *(float*)&regs.valueRegister;
  344. }
  345. double asCContext::GetReturnDouble()
  346. {
  347. if( status != asEXECUTION_FINISHED ) return 0;
  348. asCDataType *dt = &initialFunction->returnType;
  349. if( dt->IsObject() || dt->IsReference() ) return 0;
  350. return *(double*)&regs.valueRegister;
  351. }
  352. void *asCContext::GetReturnAddress()
  353. {
  354. if( status != asEXECUTION_FINISHED ) return 0;
  355. asCDataType *dt = &initialFunction->returnType;
  356. if( dt->IsReference() )
  357. return *(void**)&regs.valueRegister;
  358. else if( dt->IsObject() )
  359. return regs.objectRegister;
  360. return 0;
  361. }
  362. void *asCContext::GetReturnObject()
  363. {
  364. if( status != asEXECUTION_FINISHED ) return 0;
  365. asCDataType *dt = &initialFunction->returnType;
  366. if( !dt->IsObject() ) return 0;
  367. if( dt->IsReference() )
  368. return *(void**)(size_t)regs.valueRegister;
  369. else
  370. return regs.objectRegister;
  371. }
  372. void *asCContext::GetAddressOfReturnValue()
  373. {
  374. if( status != asEXECUTION_FINISHED ) return 0;
  375. asCDataType *dt = &initialFunction->returnType;
  376. // An object is stored in the objectRegister
  377. if( !dt->IsReference() && dt->IsObject() )
  378. {
  379. // Need to dereference objects
  380. if( !dt->IsObjectHandle() )
  381. return *(void**)&regs.objectRegister;
  382. return &regs.objectRegister;
  383. }
  384. // Primitives and references are stored in valueRegister
  385. return &regs.valueRegister;
  386. }
  387. int asCContext::SetObject(void *obj)
  388. {
  389. if( status != asEXECUTION_PREPARED )
  390. return asCONTEXT_NOT_PREPARED;
  391. if( !initialFunction->objectType )
  392. {
  393. status = asEXECUTION_ERROR;
  394. return asERROR;
  395. }
  396. *(size_t*)&regs.stackFramePointer[0] = (size_t)obj;
  397. return 0;
  398. }
  399. int asCContext::SetArgByte(asUINT arg, asBYTE value)
  400. {
  401. if( status != asEXECUTION_PREPARED )
  402. return asCONTEXT_NOT_PREPARED;
  403. if( arg >= (unsigned)initialFunction->parameterTypes.GetLength() )
  404. {
  405. status = asEXECUTION_ERROR;
  406. return asINVALID_ARG;
  407. }
  408. // Verify the type of the argument
  409. asCDataType *dt = &initialFunction->parameterTypes[arg];
  410. if( dt->IsObject() || dt->IsReference() )
  411. {
  412. status = asEXECUTION_ERROR;
  413. return asINVALID_TYPE;
  414. }
  415. if( dt->GetSizeInMemoryBytes() != 1 )
  416. {
  417. status = asEXECUTION_ERROR;
  418. return asINVALID_TYPE;
  419. }
  420. // Determine the position of the argument
  421. int offset = 0;
  422. if( initialFunction->objectType )
  423. offset += AS_PTR_SIZE;
  424. for( asUINT n = 0; n < arg; n++ )
  425. offset += initialFunction->parameterTypes[n].GetSizeOnStackDWords();
  426. // Set the value
  427. *(asBYTE*)&regs.stackFramePointer[offset] = value;
  428. return 0;
  429. }
  430. int asCContext::SetArgWord(asUINT arg, asWORD value)
  431. {
  432. if( status != asEXECUTION_PREPARED )
  433. return asCONTEXT_NOT_PREPARED;
  434. if( arg >= (unsigned)initialFunction->parameterTypes.GetLength() )
  435. {
  436. status = asEXECUTION_ERROR;
  437. return asINVALID_ARG;
  438. }
  439. // Verify the type of the argument
  440. asCDataType *dt = &initialFunction->parameterTypes[arg];
  441. if( dt->IsObject() || dt->IsReference() )
  442. {
  443. status = asEXECUTION_ERROR;
  444. return asINVALID_TYPE;
  445. }
  446. if( dt->GetSizeInMemoryBytes() != 2 )
  447. {
  448. status = asEXECUTION_ERROR;
  449. return asINVALID_TYPE;
  450. }
  451. // Determine the position of the argument
  452. int offset = 0;
  453. if( initialFunction->objectType )
  454. offset += AS_PTR_SIZE;
  455. for( asUINT n = 0; n < arg; n++ )
  456. offset += initialFunction->parameterTypes[n].GetSizeOnStackDWords();
  457. // Set the value
  458. *(asWORD*)&regs.stackFramePointer[offset] = value;
  459. return 0;
  460. }
  461. int asCContext::SetArgDWord(asUINT arg, asDWORD value)
  462. {
  463. if( status != asEXECUTION_PREPARED )
  464. return asCONTEXT_NOT_PREPARED;
  465. if( arg >= (unsigned)initialFunction->parameterTypes.GetLength() )
  466. {
  467. status = asEXECUTION_ERROR;
  468. return asINVALID_ARG;
  469. }
  470. // Verify the type of the argument
  471. asCDataType *dt = &initialFunction->parameterTypes[arg];
  472. if( dt->IsObject() || dt->IsReference() )
  473. {
  474. status = asEXECUTION_ERROR;
  475. return asINVALID_TYPE;
  476. }
  477. if( dt->GetSizeInMemoryBytes() != 4 )
  478. {
  479. status = asEXECUTION_ERROR;
  480. return asINVALID_TYPE;
  481. }
  482. // Determine the position of the argument
  483. int offset = 0;
  484. if( initialFunction->objectType )
  485. offset += AS_PTR_SIZE;
  486. for( asUINT n = 0; n < arg; n++ )
  487. offset += initialFunction->parameterTypes[n].GetSizeOnStackDWords();
  488. // Set the value
  489. *(asDWORD*)&regs.stackFramePointer[offset] = value;
  490. return 0;
  491. }
  492. int asCContext::SetArgQWord(asUINT arg, asQWORD value)
  493. {
  494. if( status != asEXECUTION_PREPARED )
  495. return asCONTEXT_NOT_PREPARED;
  496. if( arg >= (unsigned)initialFunction->parameterTypes.GetLength() )
  497. {
  498. status = asEXECUTION_ERROR;
  499. return asINVALID_ARG;
  500. }
  501. // Verify the type of the argument
  502. asCDataType *dt = &initialFunction->parameterTypes[arg];
  503. if( dt->IsObject() || dt->IsReference() )
  504. {
  505. status = asEXECUTION_ERROR;
  506. return asINVALID_TYPE;
  507. }
  508. if( dt->GetSizeOnStackDWords() != 2 )
  509. {
  510. status = asEXECUTION_ERROR;
  511. return asINVALID_TYPE;
  512. }
  513. // Determine the position of the argument
  514. int offset = 0;
  515. if( initialFunction->objectType )
  516. offset += AS_PTR_SIZE;
  517. for( asUINT n = 0; n < arg; n++ )
  518. offset += initialFunction->parameterTypes[n].GetSizeOnStackDWords();
  519. // Set the value
  520. *(asQWORD*)(&regs.stackFramePointer[offset]) = value;
  521. return 0;
  522. }
  523. int asCContext::SetArgFloat(asUINT arg, float value)
  524. {
  525. if( status != asEXECUTION_PREPARED )
  526. return asCONTEXT_NOT_PREPARED;
  527. if( arg >= (unsigned)initialFunction->parameterTypes.GetLength() )
  528. {
  529. status = asEXECUTION_ERROR;
  530. return asINVALID_ARG;
  531. }
  532. // Verify the type of the argument
  533. asCDataType *dt = &initialFunction->parameterTypes[arg];
  534. if( dt->IsObject() || dt->IsReference() )
  535. {
  536. status = asEXECUTION_ERROR;
  537. return asINVALID_TYPE;
  538. }
  539. if( dt->GetSizeOnStackDWords() != 1 )
  540. {
  541. status = asEXECUTION_ERROR;
  542. return asINVALID_TYPE;
  543. }
  544. // Determine the position of the argument
  545. int offset = 0;
  546. if( initialFunction->objectType )
  547. offset += AS_PTR_SIZE;
  548. for( asUINT n = 0; n < arg; n++ )
  549. offset += initialFunction->parameterTypes[n].GetSizeOnStackDWords();
  550. // Set the value
  551. *(float*)(&regs.stackFramePointer[offset]) = value;
  552. return 0;
  553. }
  554. int asCContext::SetArgDouble(asUINT arg, double value)
  555. {
  556. if( status != asEXECUTION_PREPARED )
  557. return asCONTEXT_NOT_PREPARED;
  558. if( arg >= (unsigned)initialFunction->parameterTypes.GetLength() )
  559. {
  560. status = asEXECUTION_ERROR;
  561. return asINVALID_ARG;
  562. }
  563. // Verify the type of the argument
  564. asCDataType *dt = &initialFunction->parameterTypes[arg];
  565. if( dt->IsObject() || dt->IsReference() )
  566. {
  567. status = asEXECUTION_ERROR;
  568. return asINVALID_TYPE;
  569. }
  570. if( dt->GetSizeOnStackDWords() != 2 )
  571. {
  572. status = asEXECUTION_ERROR;
  573. return asINVALID_TYPE;
  574. }
  575. // Determine the position of the argument
  576. int offset = 0;
  577. if( initialFunction->objectType )
  578. offset += AS_PTR_SIZE;
  579. for( asUINT n = 0; n < arg; n++ )
  580. offset += initialFunction->parameterTypes[n].GetSizeOnStackDWords();
  581. // Set the value
  582. *(double*)(&regs.stackFramePointer[offset]) = value;
  583. return 0;
  584. }
  585. int asCContext::SetArgAddress(asUINT arg, void *value)
  586. {
  587. if( status != asEXECUTION_PREPARED )
  588. return asCONTEXT_NOT_PREPARED;
  589. if( arg >= (unsigned)initialFunction->parameterTypes.GetLength() )
  590. {
  591. status = asEXECUTION_ERROR;
  592. return asINVALID_ARG;
  593. }
  594. // Verify the type of the argument
  595. asCDataType *dt = &initialFunction->parameterTypes[arg];
  596. if( !dt->IsReference() && !dt->IsObjectHandle() )
  597. {
  598. status = asEXECUTION_ERROR;
  599. return asINVALID_TYPE;
  600. }
  601. // Determine the position of the argument
  602. int offset = 0;
  603. if( initialFunction->objectType )
  604. offset += AS_PTR_SIZE;
  605. for( asUINT n = 0; n < arg; n++ )
  606. offset += initialFunction->parameterTypes[n].GetSizeOnStackDWords();
  607. // Set the value
  608. *(size_t*)(&regs.stackFramePointer[offset]) = (size_t)value;
  609. return 0;
  610. }
  611. int asCContext::SetArgObject(asUINT arg, void *obj)
  612. {
  613. if( status != asEXECUTION_PREPARED )
  614. return asCONTEXT_NOT_PREPARED;
  615. if( arg >= (unsigned)initialFunction->parameterTypes.GetLength() )
  616. {
  617. status = asEXECUTION_ERROR;
  618. return asINVALID_ARG;
  619. }
  620. // Verify the type of the argument
  621. asCDataType *dt = &initialFunction->parameterTypes[arg];
  622. if( !dt->IsObject() )
  623. {
  624. status = asEXECUTION_ERROR;
  625. return asINVALID_TYPE;
  626. }
  627. // If the object should be sent by value we must make a copy of it
  628. if( !dt->IsReference() )
  629. {
  630. if( dt->IsObjectHandle() )
  631. {
  632. // Increase the reference counter
  633. asSTypeBehaviour *beh = &dt->GetObjectType()->beh;
  634. if( obj && beh->addref )
  635. engine->CallObjectMethod(obj, beh->addref);
  636. }
  637. else
  638. {
  639. obj = engine->CreateScriptObjectCopy(obj, engine->GetTypeIdFromDataType(*dt));
  640. }
  641. }
  642. // Determine the position of the argument
  643. int offset = 0;
  644. if( initialFunction->objectType )
  645. offset += AS_PTR_SIZE;
  646. for( asUINT n = 0; n < arg; n++ )
  647. offset += initialFunction->parameterTypes[n].GetSizeOnStackDWords();
  648. // Set the value
  649. *(size_t*)(&regs.stackFramePointer[offset]) = (size_t)obj;
  650. return 0;
  651. }
  652. // TODO: Instead of GetAddressOfArg, maybe we need a SetArgValue(int arg, void *value, bool takeOwnership) instead.
  653. // interface
  654. void *asCContext::GetAddressOfArg(asUINT arg)
  655. {
  656. if( status != asEXECUTION_PREPARED )
  657. return 0;
  658. if( arg >= (unsigned)initialFunction->parameterTypes.GetLength() )
  659. return 0;
  660. // Determine the position of the argument
  661. int offset = 0;
  662. if( initialFunction->objectType )
  663. offset += AS_PTR_SIZE;
  664. for( asUINT n = 0; n < arg; n++ )
  665. offset += initialFunction->parameterTypes[n].GetSizeOnStackDWords();
  666. // We should return the address of the location where the argument value will be placed
  667. // All registered types are always sent by reference, even if
  668. // the function is declared to receive the argument by value.
  669. return &regs.stackFramePointer[offset];
  670. }
  671. int asCContext::Abort()
  672. {
  673. // TODO: multithread: Make thread safe
  674. if( engine == 0 ) return asERROR;
  675. if( status == asEXECUTION_SUSPENDED )
  676. status = asEXECUTION_ABORTED;
  677. doSuspend = true;
  678. regs.doProcessSuspend = true;
  679. externalSuspendRequest = true;
  680. doAbort = true;
  681. return 0;
  682. }
  683. // interface
  684. int asCContext::Suspend()
  685. {
  686. // This function just sets some internal flags and is safe
  687. // to call from a secondary thread, even if the library has
  688. // been built without multi-thread support.
  689. if( engine == 0 ) return asERROR;
  690. doSuspend = true;
  691. externalSuspendRequest = true;
  692. regs.doProcessSuspend = true;
  693. return 0;
  694. }
  695. // interface
  696. int asCContext::Execute()
  697. {
  698. asASSERT( engine != 0 );
  699. if( status != asEXECUTION_SUSPENDED && status != asEXECUTION_PREPARED )
  700. return asERROR;
  701. status = asEXECUTION_ACTIVE;
  702. asPushActiveContext((asIScriptContext *)this);
  703. if( regs.programPointer == 0 )
  704. {
  705. if( currentFunction->funcType == asFUNC_VIRTUAL ||
  706. currentFunction->funcType == asFUNC_INTERFACE )
  707. {
  708. // The currentFunction is a virtual method
  709. // Determine the true function from the object
  710. asCScriptObject *obj = *(asCScriptObject**)(size_t*)regs.stackFramePointer;
  711. if( obj == 0 )
  712. {
  713. SetInternalException(TXT_NULL_POINTER_ACCESS);
  714. }
  715. else
  716. {
  717. asCObjectType *objType = obj->objType;
  718. asCScriptFunction *realFunc = 0;
  719. if( currentFunction->funcType == asFUNC_VIRTUAL )
  720. {
  721. if( objType->virtualFunctionTable.GetLength() > (asUINT)currentFunction->vfTableIdx )
  722. {
  723. realFunc = objType->virtualFunctionTable[currentFunction->vfTableIdx];
  724. }
  725. }
  726. else
  727. {
  728. // Search the object type for a function that matches the interface function
  729. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  730. {
  731. asCScriptFunction *f2 = engine->scriptFunctions[objType->methods[n]];
  732. if( f2->signatureId == currentFunction->signatureId )
  733. {
  734. if( f2->funcType == asFUNC_VIRTUAL )
  735. realFunc = objType->virtualFunctionTable[f2->vfTableIdx];
  736. else
  737. realFunc = f2;
  738. break;
  739. }
  740. }
  741. }
  742. if( realFunc )
  743. {
  744. if( realFunc->signatureId != currentFunction->signatureId )
  745. {
  746. SetInternalException(TXT_NULL_POINTER_ACCESS);
  747. }
  748. else
  749. {
  750. currentFunction = realFunc;
  751. regs.programPointer = currentFunction->byteCode.AddressOf();
  752. // Set the local objects to 0
  753. for( asUINT n = 0; n < currentFunction->objVariablePos.GetLength(); n++ )
  754. {
  755. int pos = currentFunction->objVariablePos[n];
  756. *(size_t*)&regs.stackFramePointer[-pos] = 0;
  757. }
  758. }
  759. }
  760. }
  761. }
  762. else if( currentFunction->funcType == asFUNC_SYSTEM )
  763. {
  764. // The current function is an application registered function
  765. // Call the function directly
  766. CallSystemFunction(currentFunction->id, this, 0);
  767. // Was the call successful?
  768. if( status == asEXECUTION_ACTIVE )
  769. {
  770. status = asEXECUTION_FINISHED;
  771. }
  772. }
  773. else
  774. {
  775. // This shouldn't happen
  776. asASSERT(false);
  777. }
  778. }
  779. while( status == asEXECUTION_ACTIVE )
  780. ExecuteNext();
  781. doSuspend = false;
  782. regs.doProcessSuspend = lineCallback;
  783. asPopActiveContext((asIScriptContext *)this);
  784. #ifdef AS_DEBUG
  785. /*
  786. // Output instruction statistics
  787. // This is useful for determining what needs to be optimized.
  788. _mkdir("AS_DEBUG");
  789. FILE *f = fopen("AS_DEBUG/stats.txt", "at");
  790. fprintf(f, "\n");
  791. asQWORD total = 0;
  792. int n;
  793. for( n = 0; n < 256; n++ )
  794. {
  795. if( bcName[n].name && instrCount[n] )
  796. fprintf(f, "%-10.10s : %d\n", bcName[n].name, instrCount[n]);
  797. total += instrCount[n];
  798. }
  799. fprintf(f, "\ntotal : %I64d\n", total);
  800. fprintf(f, "\n");
  801. for( n = 0; n < 256; n++ )
  802. {
  803. if( bcName[n].name )
  804. {
  805. for( int m = 0; m < 256; m++ )
  806. {
  807. if( instrCount2[n][m] )
  808. fprintf(f, "%-10.10s, %-10.10s : %d\n", bcName[n].name, bcName[m].name, instrCount2[n][m]);
  809. }
  810. }
  811. }
  812. fclose(f);
  813. */
  814. #endif
  815. if( status == asEXECUTION_FINISHED )
  816. {
  817. regs.objectType = initialFunction->returnType.GetObjectType();
  818. return asEXECUTION_FINISHED;
  819. }
  820. if( doAbort )
  821. {
  822. doAbort = false;
  823. status = asEXECUTION_ABORTED;
  824. return asEXECUTION_ABORTED;
  825. }
  826. if( status == asEXECUTION_SUSPENDED )
  827. return asEXECUTION_SUSPENDED;
  828. if( status == asEXECUTION_EXCEPTION )
  829. return asEXECUTION_EXCEPTION;
  830. return asERROR;
  831. }
  832. void asCContext::PushCallState()
  833. {
  834. callStack.SetLength(callStack.GetLength() + CALLSTACK_FRAME_SIZE);
  835. // Separating the loads and stores limits data cache trash, and with a smart compiler
  836. // could turn into SIMD style loading/storing if available.
  837. // The compiler can't do this itself due to potential pointer aliasing between the pointers,
  838. // ie writing to tmp could overwrite the data contained in registers.stackFramePointer for example
  839. // for all the compiler knows. So introducing the local variable s, which is never referred to by
  840. // its address we avoid this issue.
  841. size_t s[5];
  842. s[0] = (size_t)regs.stackFramePointer;
  843. s[1] = (size_t)currentFunction;
  844. s[2] = (size_t)regs.programPointer;
  845. s[3] = (size_t)regs.stackPointer;
  846. s[4] = stackIndex;
  847. size_t *tmp = callStack.AddressOf() + callStack.GetLength() - CALLSTACK_FRAME_SIZE;
  848. tmp[0] = s[0];
  849. tmp[1] = s[1];
  850. tmp[2] = s[2];
  851. tmp[3] = s[3];
  852. tmp[4] = s[4];
  853. }
  854. void asCContext::PopCallState()
  855. {
  856. // See comments in PushCallState about pointer aliasing and data cache trashing
  857. size_t *tmp = callStack.AddressOf() + callStack.GetLength() - CALLSTACK_FRAME_SIZE;
  858. size_t s[5];
  859. s[0] = tmp[0];
  860. s[1] = tmp[1];
  861. s[2] = tmp[2];
  862. s[3] = tmp[3];
  863. s[4] = tmp[4];
  864. regs.stackFramePointer = (asDWORD*)s[0];
  865. currentFunction = (asCScriptFunction*)s[1];
  866. regs.programPointer = (asDWORD*)s[2];
  867. regs.stackPointer = (asDWORD*)s[3];
  868. stackIndex = (int)s[4];
  869. callStack.SetLength(callStack.GetLength() - CALLSTACK_FRAME_SIZE);
  870. }
  871. // interface
  872. asUINT asCContext::GetCallstackSize()
  873. {
  874. // The current function is accessed at stackLevel 0
  875. return asUINT(1 + callStack.GetLength() / CALLSTACK_FRAME_SIZE);
  876. }
  877. // interface
  878. asIScriptFunction *asCContext::GetFunction(asUINT stackLevel)
  879. {
  880. if( stackLevel >= GetCallstackSize() ) return 0;
  881. if( stackLevel == 0 ) return currentFunction;
  882. size_t *s = callStack.AddressOf() + (GetCallstackSize() - stackLevel - 1)*CALLSTACK_FRAME_SIZE;
  883. asCScriptFunction *func = (asCScriptFunction*)s[1];
  884. return func;
  885. }
  886. // interface
  887. int asCContext::GetLineNumber(asUINT stackLevel, int *column, const char **sectionName)
  888. {
  889. if( stackLevel >= GetCallstackSize() ) return asINVALID_ARG;
  890. asCScriptFunction *func;
  891. asDWORD *bytePos;
  892. if( stackLevel == 0 )
  893. {
  894. func = currentFunction;
  895. bytePos = regs.programPointer;
  896. }
  897. else
  898. {
  899. size_t *s = callStack.AddressOf() + (GetCallstackSize()-stackLevel-1)*CALLSTACK_FRAME_SIZE;
  900. func = (asCScriptFunction*)s[1];
  901. bytePos = (asDWORD*)s[2];
  902. }
  903. asDWORD line = func->GetLineNumber(int(bytePos - func->byteCode.AddressOf()));
  904. if( column ) *column = (line >> 20);
  905. if( sectionName ) *sectionName = func->GetScriptSectionName();
  906. return (line & 0xFFFFF);
  907. }
  908. void asCContext::CallScriptFunction(asCScriptFunction *func)
  909. {
  910. // Push the framepointer, function id and programCounter on the stack
  911. PushCallState();
  912. currentFunction = func;
  913. regs.programPointer = currentFunction->byteCode.AddressOf();
  914. // Verify if there is enough room in the stack block. Allocate new block if not
  915. if( regs.stackPointer - (func->stackNeeded + RESERVE_STACK) < stackBlocks[stackIndex] )
  916. {
  917. asDWORD *oldStackPointer = regs.stackPointer;
  918. // The size of each stack block is determined by the following formula:
  919. // size = stackBlockSize << index
  920. while( regs.stackPointer - (func->stackNeeded + RESERVE_STACK) < stackBlocks[stackIndex] )
  921. {
  922. // Make sure we don't allocate more space than allowed
  923. if( engine->ep.maximumContextStackSize )
  924. {
  925. // This test will only stop growth once it has already crossed the limit
  926. if( stackBlockSize * ((1 << (stackIndex+1)) - 1) > engine->ep.maximumContextStackSize )
  927. {
  928. isStackMemoryNotAllocated = true;
  929. // Set the stackFramePointer, even though the stackPointer wasn't updated
  930. regs.stackFramePointer = regs.stackPointer;
  931. // TODO: Make sure the exception handler doesn't try to free objects that have not been initialized
  932. SetInternalException(TXT_STACK_OVERFLOW);
  933. return;
  934. }
  935. }
  936. stackIndex++;
  937. if( (int)stackBlocks.GetLength() == stackIndex )
  938. {
  939. asDWORD *stack = asNEWARRAY(asDWORD,(stackBlockSize << stackIndex));
  940. stackBlocks.PushLast(stack);
  941. }
  942. regs.stackPointer = stackBlocks[stackIndex] + (stackBlockSize<<stackIndex) - func->GetSpaceNeededForArguments() - (func->objectType ? AS_PTR_SIZE : 0);
  943. }
  944. // Copy the function arguments to the new stack space
  945. int numDwords = func->GetSpaceNeededForArguments() + (func->objectType ? AS_PTR_SIZE : 0);
  946. memcpy(regs.stackPointer, oldStackPointer, sizeof(asDWORD)*numDwords);
  947. }
  948. // Update framepointer and programCounter
  949. regs.stackFramePointer = regs.stackPointer;
  950. // TODO: optimize: This can be avoided handling this as is done for value types in the exception handler
  951. // Set all object variables to 0
  952. for( asUINT n = 0; n < currentFunction->objVariablePos.GetLength(); n++ )
  953. {
  954. if( !currentFunction->objVariableIsOnHeap[n] ) continue;
  955. int pos = currentFunction->objVariablePos[n];
  956. *(size_t*)&regs.stackFramePointer[-pos] = 0;
  957. }
  958. }
  959. void asCContext::CallInterfaceMethod(asCScriptFunction *func)
  960. {
  961. // Resolve the interface method using the current script type
  962. asCScriptObject *obj = *(asCScriptObject**)(size_t*)regs.stackPointer;
  963. if( obj == 0 )
  964. {
  965. SetInternalException(TXT_NULL_POINTER_ACCESS);
  966. return;
  967. }
  968. asCObjectType *objType = obj->objType;
  969. // TODO: optimize: The object type should have a list of only those methods that
  970. // implement interface methods. This list should be ordered by
  971. // the signatureId so that a binary search can be made, instead
  972. // of a linear search.
  973. //
  974. // When this is done, we must also make sure the signatureId of a
  975. // function never changes, e.g. when if the signature functions are
  976. // released.
  977. // Search the object type for a function that matches the interface function
  978. asCScriptFunction *realFunc = 0;
  979. if( func->funcType == asFUNC_INTERFACE )
  980. {
  981. for( asUINT n = 0; n < objType->methods.GetLength(); n++ )
  982. {
  983. asCScriptFunction *f2 = engine->scriptFunctions[objType->methods[n]];
  984. if( f2->signatureId == func->signatureId )
  985. {
  986. if( f2->funcType == asFUNC_VIRTUAL )
  987. realFunc = objType->virtualFunctionTable[f2->vfTableIdx];
  988. else
  989. realFunc = f2;
  990. break;
  991. }
  992. }
  993. if( realFunc == 0 )
  994. {
  995. SetInternalException(TXT_NULL_POINTER_ACCESS);
  996. return;
  997. }
  998. }
  999. else // if( func->funcType == asFUNC_VIRTUAL )
  1000. {
  1001. realFunc = objType->virtualFunctionTable[func->vfTableIdx];
  1002. }
  1003. // Then call the true script function
  1004. CallScriptFunction(realFunc);
  1005. }
  1006. void asCContext::ExecuteNext()
  1007. {
  1008. asDWORD *l_bc = regs.programPointer;
  1009. asDWORD *l_sp = regs.stackPointer;
  1010. asDWORD *l_fp = regs.stackFramePointer;
  1011. for(;;)
  1012. {
  1013. #ifdef AS_DEBUG
  1014. ++stats.instrCount[*(asBYTE*)l_bc];
  1015. ++instrCount[*(asBYTE*)l_bc];
  1016. ++instrCount2[lastBC][*(asBYTE*)l_bc];
  1017. lastBC = *(asBYTE*)l_bc;
  1018. // Used to verify that the size of the instructions are correct
  1019. asDWORD *old = l_bc;
  1020. #endif
  1021. // Remember to keep the cases in order and without
  1022. // gaps, because that will make the switch faster.
  1023. // It will be faster since only one lookup will be
  1024. // made to find the correct jump destination. If not
  1025. // in order, the switch will make two lookups.
  1026. switch( *(asBYTE*)l_bc )
  1027. {
  1028. //--------------
  1029. // memory access functions
  1030. // Decrease the stack pointer with n dwords (stack grows downward)
  1031. case asBC_POP:
  1032. l_sp += asBC_WORDARG0(l_bc);
  1033. l_bc++;
  1034. break;
  1035. // Increase the stack pointer with n dwords
  1036. case asBC_PUSH:
  1037. l_sp -= asBC_WORDARG0(l_bc);
  1038. l_bc++;
  1039. break;
  1040. // Push a dword value on the stack
  1041. case asBC_PshC4:
  1042. --l_sp;
  1043. *l_sp = asBC_DWORDARG(l_bc);
  1044. l_bc += 2;
  1045. break;
  1046. // Push the dword value of a variable on the stack
  1047. case asBC_PshV4:
  1048. --l_sp;
  1049. *l_sp = *(l_fp - asBC_SWORDARG0(l_bc));
  1050. l_bc++;
  1051. break;
  1052. // Push the address of a variable on the stack
  1053. case asBC_PSF:
  1054. l_sp -= AS_PTR_SIZE;
  1055. *(asPTRWORD*)l_sp = (asPTRWORD)size_t(l_fp - asBC_SWORDARG0(l_bc));
  1056. l_bc++;
  1057. break;
  1058. // Swap the top 2 dwords on the stack
  1059. case asBC_SWAP4:
  1060. {
  1061. asDWORD d = (asDWORD)*l_sp;
  1062. *l_sp = *(l_sp+1);
  1063. *(asDWORD*)(l_sp+1) = d;
  1064. l_bc++;
  1065. }
  1066. break;
  1067. // Do a boolean not operation, modifying the value of the variable
  1068. case asBC_NOT:
  1069. #if AS_SIZEOF_BOOL == 1
  1070. {
  1071. // Set the value to true if it is equal to 0
  1072. // We need to use volatile here to tell the compiler it cannot
  1073. // change the order of read and write operations on the pointer.
  1074. volatile asBYTE *ptr = (asBYTE*)(l_fp - asBC_SWORDARG0(l_bc));
  1075. asBYTE val = (ptr[0] == 0) ? VALUE_OF_BOOLEAN_TRUE : 0;
  1076. ptr[0] = val; // The result is stored in the lower byte
  1077. ptr[1] = 0; // Make sure the rest of the DWORD is 0
  1078. ptr[2] = 0;
  1079. ptr[3] = 0;
  1080. }
  1081. #else
  1082. *(l_fp - asBC_SWORDARG0(l_bc)) = (*(l_fp - asBC_SWORDARG0(l_bc)) == 0 ? VALUE_OF_BOOLEAN_TRUE : 0);
  1083. #endif
  1084. l_bc++;
  1085. break;
  1086. // Push the dword value of a global variable on the stack
  1087. case asBC_PshG4:
  1088. --l_sp;
  1089. *l_sp = *(asDWORD*)(size_t)asBC_PTRARG(l_bc);
  1090. l_bc += 1 + AS_PTR_SIZE;
  1091. break;
  1092. // Load the address of a global variable in the register, then
  1093. // copy the value of the global variable into a local variable
  1094. case asBC_LdGRdR4:
  1095. *(void**)&regs.valueRegister = (void*)(size_t)asBC_PTRARG(l_bc);
  1096. *(l_fp - asBC_SWORDARG0(l_bc)) = **(asDWORD**)&regs.valueRegister;
  1097. l_bc += 1+AS_PTR_SIZE;
  1098. break;
  1099. //----------------
  1100. // path control instructions
  1101. // Begin execution of a script function
  1102. case asBC_CALL:
  1103. {
  1104. int i = asBC_INTARG(l_bc);
  1105. l_bc += 2;
  1106. asASSERT( i >= 0 );
  1107. asASSERT( (i & FUNC_IMPORTED) == 0 );
  1108. // Need to move the values back to the context
  1109. regs.programPointer = l_bc;
  1110. regs.stackPointer = l_sp;
  1111. regs.stackFramePointer = l_fp;
  1112. CallScriptFunction(engine->scriptFunctions[i]);
  1113. // Extract the values from the context again
  1114. l_bc = regs.programPointer;
  1115. l_sp = regs.stackPointer;
  1116. l_fp = regs.stackFramePointer;
  1117. // If status isn't active anymore then we must stop
  1118. if( status != asEXECUTION_ACTIVE )
  1119. return;
  1120. }
  1121. break;
  1122. // Return to the caller, and remove the arguments from the stack
  1123. case asBC_RET:
  1124. {
  1125. if( callStack.GetLength() == 0 )
  1126. {
  1127. status = asEXECUTION_FINISHED;
  1128. return;
  1129. }
  1130. asWORD w = asBC_WORDARG0(l_bc);
  1131. // Read the old framepointer, functionid, and programCounter from the call stack
  1132. PopCallState();
  1133. // Extract the values from the context again
  1134. l_bc = regs.programPointer;
  1135. l_sp = regs.stackPointer;
  1136. l_fp = regs.stackFramePointer;
  1137. // Pop arguments from stack
  1138. l_sp += w;
  1139. }
  1140. break;
  1141. // Jump to a relative position
  1142. case asBC_JMP:
  1143. l_bc += 2 + asBC_INTARG(l_bc);
  1144. break;
  1145. //----------------
  1146. // Conditional jumps
  1147. // Jump to a relative position if the value in the register is 0
  1148. case asBC_JZ:
  1149. if( *(int*)&regs.valueRegister == 0 )
  1150. l_bc += asBC_INTARG(l_bc) + 2;
  1151. else
  1152. l_bc += 2;
  1153. break;
  1154. // Jump to a relative position if the value in the register is not 0
  1155. case asBC_JNZ:
  1156. if( *(int*)&regs.valueRegister != 0 )
  1157. l_bc += asBC_INTARG(l_bc) + 2;
  1158. else
  1159. l_bc += 2;
  1160. break;
  1161. // Jump to a relative position if the value in the register is negative
  1162. case asBC_JS:
  1163. if( *(int*)&regs.valueRegister < 0 )
  1164. l_bc += asBC_INTARG(l_bc) + 2;
  1165. else
  1166. l_bc += 2;
  1167. break;
  1168. // Jump to a relative position if the value in the register it not negative
  1169. case asBC_JNS:
  1170. if( *(int*)&regs.valueRegister >= 0 )
  1171. l_bc += asBC_INTARG(l_bc) + 2;
  1172. else
  1173. l_bc += 2;
  1174. break;
  1175. // Jump to a relative position if the value in the register is greater than 0
  1176. case asBC_JP:
  1177. if( *(int*)&regs.valueRegister > 0 )
  1178. l_bc += asBC_INTARG(l_bc) + 2;
  1179. else
  1180. l_bc += 2;
  1181. break;
  1182. // Jump to a relative position if the value in the register is not greater than 0
  1183. case asBC_JNP:
  1184. if( *(int*)&regs.valueRegister <= 0 )
  1185. l_bc += asBC_INTARG(l_bc) + 2;
  1186. else
  1187. l_bc += 2;
  1188. break;
  1189. //--------------------
  1190. // test instructions
  1191. // If the value in the register is 0, then set the register to 1, else to 0
  1192. case asBC_TZ:
  1193. #if AS_SIZEOF_BOOL == 1
  1194. {
  1195. // Set the value to true if it is equal to 0
  1196. // We need to use volatile here to tell the compiler it cannot
  1197. // change the order of read and write operations on valueRegister.
  1198. volatile int *regPtr = (int*)&regs.valueRegister;
  1199. volatile asBYTE *regBptr = (asBYTE*)&regs.valueRegister;
  1200. asBYTE val = (regPtr[0] == 0) ? VALUE_OF_BOOLEAN_TRUE : 0;
  1201. regBptr[0] = val; // The result is stored in the lower byte
  1202. regBptr[1] = 0; // Make sure the rest of the register is 0
  1203. regBptr[2] = 0;
  1204. regBptr[3] = 0;
  1205. regBptr[4] = 0;
  1206. regBptr[5] = 0;
  1207. regBptr[6] = 0;
  1208. regBptr[7] = 0;
  1209. }
  1210. #else
  1211. *(int*)&regs.valueRegister = (*(int*)&regs.valueRegister == 0 ? VALUE_OF_BOOLEAN_TRUE : 0);
  1212. #endif
  1213. l_bc++;
  1214. break;
  1215. // If the value in the register is not 0, then set the register to 1, else to 0
  1216. case asBC_TNZ:
  1217. #if AS_SIZEOF_BOOL == 1
  1218. {
  1219. // Set the value to true if it is not equal to 0
  1220. // We need to use volatile here to tell the compiler it cannot
  1221. // change the order of read and write operations on valueRegister.
  1222. volatile int *regPtr = (int*)&regs.valueRegister;
  1223. volatile asBYTE *regBptr = (asBYTE*)&regs.valueRegister;
  1224. asBYTE val = (regPtr[0] == 0) ? 0 : VALUE_OF_BOOLEAN_TRUE;
  1225. regBptr[0] = val; // The result is stored in the lower byte
  1226. regBptr[1] = 0; // Make sure the rest of the register is 0
  1227. regBptr[2] = 0;
  1228. regBptr[3] = 0;
  1229. regBptr[4] = 0;
  1230. regBptr[5] = 0;
  1231. regBptr[6] = 0;
  1232. regBptr[7] = 0;
  1233. }
  1234. #else
  1235. *(int*)&regs.valueRegister = (*(int*)&regs.valueRegister == 0 ? 0 : VALUE_OF_BOOLEAN_TRUE);
  1236. #endif
  1237. l_bc++;
  1238. break;
  1239. // If the value in the register is negative, then set the register to 1, else to 0
  1240. case asBC_TS:
  1241. #if AS_SIZEOF_BOOL == 1
  1242. {
  1243. // Set the value to true if it is less than 0
  1244. // We need to use volatile here to tell the compiler it cannot
  1245. // change the order of read and write operations on valueRegister.
  1246. volatile int *regPtr = (int*)&regs.valueRegister;
  1247. volatile asBYTE *regBptr = (asBYTE*)&regs.valueRegister;
  1248. asBYTE val = (regPtr[0] < 0) ? VALUE_OF_BOOLEAN_TRUE : 0;
  1249. regBptr[0] = val; // The result is stored in the lower byte
  1250. regBptr[1] = 0; // Make sure the rest of the register is 0
  1251. regBptr[2] = 0;
  1252. regBptr[3] = 0;
  1253. regBptr[4] = 0;
  1254. regBptr[5] = 0;
  1255. regBptr[6] = 0;
  1256. regBptr[7] = 0;
  1257. }
  1258. #else
  1259. *(int*)&regs.valueRegister = (*(int*)&regs.valueRegister < 0 ? VALUE_OF_BOOLEAN_TRUE : 0);
  1260. #endif
  1261. l_bc++;
  1262. break;
  1263. // If the value in the register is not negative, then set the register to 1, else to 0
  1264. case asBC_TNS:
  1265. #if AS_SIZEOF_BOOL == 1
  1266. {
  1267. // Set the value to true if it is not less than 0
  1268. // We need to use volatile here to tell the compiler it cannot
  1269. // change the order of read and write operations on valueRegister.
  1270. volatile int *regPtr = (int*)&regs.valueRegister;
  1271. volatile asBYTE *regBptr = (asBYTE*)&regs.valueRegister;
  1272. asBYTE val = (regPtr[0] >= 0) ? VALUE_OF_BOOLEAN_TRUE : 0;
  1273. regBptr[0] = val; // The result is stored in the lower byte
  1274. regBptr[1] = 0; // Make sure the rest of the register is 0
  1275. regBptr[2] = 0;
  1276. regBptr[3] = 0;
  1277. regBptr[4] = 0;
  1278. regBptr[5] = 0;
  1279. regBptr[6] = 0;
  1280. regBptr[7] = 0;
  1281. }
  1282. #else
  1283. *(int*)&regs.valueRegister = (*(int*)&regs.valueRegister < 0 ? 0 : VALUE_OF_BOOLEAN_TRUE);
  1284. #endif
  1285. l_bc++;
  1286. break;
  1287. // If the value in the register is greater than 0, then set the register to 1, else to 0
  1288. case asBC_TP:
  1289. #if AS_SIZEOF_BOOL == 1
  1290. {
  1291. // Set the value to true if it is greater than 0
  1292. // We need to use volatile here to tell the compiler it cannot
  1293. // change the order of read and write operations on valueRegister.
  1294. volatile int *regPtr = (int*)&regs.valueRegister;
  1295. volatile asBYTE *regBptr = (asBYTE*)&regs.valueRegister;
  1296. asBYTE val = (regPtr[0] > 0) ? VALUE_OF_BOOLEAN_TRUE : 0;
  1297. regBptr[0] = val; // The result is stored in the lower byte
  1298. regBptr[1] = 0; // Make sure the rest of the register is 0
  1299. regBptr[2] = 0;
  1300. regBptr[3] = 0;
  1301. regBptr[4] = 0;
  1302. regBptr[5] = 0;
  1303. regBptr[6] = 0;
  1304. regBptr[7] = 0;
  1305. }
  1306. #else
  1307. *(int*)&regs.valueRegister = (*(int*)&regs.valueRegister > 0 ? VALUE_OF_BOOLEAN_TRUE : 0);
  1308. #endif
  1309. l_bc++;
  1310. break;
  1311. // If the value in the register is not greater than 0, then set the register to 1, else to 0
  1312. case asBC_TNP:
  1313. #if AS_SIZEOF_BOOL == 1
  1314. {
  1315. // Set the value to true if it is not greater than 0
  1316. // We need to use volatile here to tell the compiler it cannot
  1317. // change the order of read and write operations on valueRegister.
  1318. volatile int *regPtr = (int*)&regs.valueRegister;
  1319. volatile asBYTE *regBptr = (asBYTE*)&regs.valueRegister;
  1320. asBYTE val = (regPtr[0] <= 0) ? VALUE_OF_BOOLEAN_TRUE : 0;
  1321. regBptr[0] = val; // The result is stored in the lower byte
  1322. regBptr[1] = 0; // Make sure the rest of the register is 0
  1323. regBptr[2] = 0;
  1324. regBptr[3] = 0;
  1325. regBptr[4] = 0;
  1326. regBptr[5] = 0;
  1327. regBptr[6] = 0;
  1328. regBptr[7] = 0;
  1329. }
  1330. #else
  1331. *(int*)&regs.valueRegister = (*(int*)&regs.valueRegister > 0 ? 0 : VALUE_OF_BOOLEAN_TRUE);
  1332. #endif
  1333. l_bc++;
  1334. break;
  1335. //--------------------
  1336. // negate value
  1337. // Negate the integer value in the variable
  1338. case asBC_NEGi:
  1339. *(l_fp - asBC_SWORDARG0(l_bc)) = asDWORD(-int(*(l_fp - asBC_SWORDARG0(l_bc))));
  1340. l_bc++;
  1341. break;
  1342. // Negate the float value in the variable
  1343. case asBC_NEGf:
  1344. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = -*(float*)(l_fp - asBC_SWORDARG0(l_bc));
  1345. l_bc++;
  1346. break;
  1347. // Negate the double value in the variable
  1348. case asBC_NEGd:
  1349. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = -*(double*)(l_fp - asBC_SWORDARG0(l_bc));
  1350. l_bc++;
  1351. break;
  1352. //-------------------------
  1353. // Increment value pointed to by address in register
  1354. // Increment the short value pointed to by the register
  1355. case asBC_INCi16:
  1356. (**(short**)&regs.valueRegister)++;
  1357. l_bc++;
  1358. break;
  1359. // Increment the byte value pointed to by the register
  1360. case asBC_INCi8:
  1361. (**(char**)&regs.valueRegister)++;
  1362. l_bc++;
  1363. break;
  1364. // Decrement the short value pointed to by the register
  1365. case asBC_DECi16:
  1366. (**(short**)&regs.valueRegister)--;
  1367. l_bc++;
  1368. break;
  1369. // Decrement the byte value pointed to by the register
  1370. case asBC_DECi8:
  1371. (**(char**)&regs.valueRegister)--;
  1372. l_bc++;
  1373. break;
  1374. // Increment the integer value pointed to by the register
  1375. case asBC_INCi:
  1376. ++(**(int**)&regs.valueRegister);
  1377. l_bc++;
  1378. break;
  1379. // Decrement the integer value pointed to by the register
  1380. case asBC_DECi:
  1381. --(**(int**)&regs.valueRegister);
  1382. l_bc++;
  1383. break;
  1384. // Increment the float value pointed to by the register
  1385. case asBC_INCf:
  1386. ++(**(float**)&regs.valueRegister);
  1387. l_bc++;
  1388. break;
  1389. // Decrement the float value pointed to by the register
  1390. case asBC_DECf:
  1391. --(**(float**)&regs.valueRegister);
  1392. l_bc++;
  1393. break;
  1394. // Increment the double value pointed to by the register
  1395. case asBC_INCd:
  1396. ++(**(double**)&regs.valueRegister);
  1397. l_bc++;
  1398. break;
  1399. // Decrement the double value pointed to by the register
  1400. case asBC_DECd:
  1401. --(**(double**)&regs.valueRegister);
  1402. l_bc++;
  1403. break;
  1404. // Increment the local integer variable
  1405. case asBC_IncVi:
  1406. (*(int*)(l_fp - asBC_SWORDARG0(l_bc)))++;
  1407. l_bc++;
  1408. break;
  1409. // Decrement the local integer variable
  1410. case asBC_DecVi:
  1411. (*(int*)(l_fp - asBC_SWORDARG0(l_bc)))--;
  1412. l_bc++;
  1413. break;
  1414. //--------------------
  1415. // bits instructions
  1416. // Do a bitwise not on the value in the variable
  1417. case asBC_BNOT:
  1418. *(l_fp - asBC_SWORDARG0(l_bc)) = ~*(l_fp - asBC_SWORDARG0(l_bc));
  1419. l_bc++;
  1420. break;
  1421. // Do a bitwise and of two variables and store the result in a third variable
  1422. case asBC_BAND:
  1423. *(l_fp - asBC_SWORDARG0(l_bc)) = *(l_fp - asBC_SWORDARG1(l_bc)) & *(l_fp - asBC_SWORDARG2(l_bc));
  1424. l_bc += 2;
  1425. break;
  1426. // Do a bitwise or of two variables and store the result in a third variable
  1427. case asBC_BOR:
  1428. *(l_fp - asBC_SWORDARG0(l_bc)) = *(l_fp - asBC_SWORDARG1(l_bc)) | *(l_fp - asBC_SWORDARG2(l_bc));
  1429. l_bc += 2;
  1430. break;
  1431. // Do a bitwise xor of two variables and store the result in a third variable
  1432. case asBC_BXOR:
  1433. *(l_fp - asBC_SWORDARG0(l_bc)) = *(l_fp - asBC_SWORDARG1(l_bc)) ^ *(l_fp - asBC_SWORDARG2(l_bc));
  1434. l_bc += 2;
  1435. break;
  1436. // Do a logical shift left of two variables and store the result in a third variable
  1437. case asBC_BSLL:
  1438. *(l_fp - asBC_SWORDARG0(l_bc)) = *(l_fp - asBC_SWORDARG1(l_bc)) << *(l_fp - asBC_SWORDARG2(l_bc));
  1439. l_bc += 2;
  1440. break;
  1441. // Do a logical shift right of two variables and store the result in a third variable
  1442. case asBC_BSRL:
  1443. *(l_fp - asBC_SWORDARG0(l_bc)) = *(l_fp - asBC_SWORDARG1(l_bc)) >> *(l_fp - asBC_SWORDARG2(l_bc));
  1444. l_bc += 2;
  1445. break;
  1446. // Do an arithmetic shift right of two variables and store the result in a third variable
  1447. case asBC_BSRA:
  1448. *(l_fp - asBC_SWORDARG0(l_bc)) = int(*(l_fp - asBC_SWORDARG1(l_bc))) >> *(l_fp - asBC_SWORDARG2(l_bc));
  1449. l_bc += 2;
  1450. break;
  1451. case asBC_COPY:
  1452. {
  1453. void *d = (void*)*(size_t*)l_sp; l_sp += AS_PTR_SIZE;
  1454. void *s = (void*)*(size_t*)l_sp;
  1455. if( s == 0 || d == 0 )
  1456. {
  1457. // Need to move the values back to the context
  1458. regs.programPointer = l_bc;
  1459. regs.stackPointer = l_sp;
  1460. regs.stackFramePointer = l_fp;
  1461. // Raise exception
  1462. SetInternalException(TXT_NULL_POINTER_ACCESS);
  1463. return;
  1464. }
  1465. memcpy(d, s, asBC_WORDARG0(l_bc)*4);
  1466. // replace the pointer on the stack with the lvalue
  1467. *(size_t**)l_sp = (size_t*)d;
  1468. }
  1469. l_bc += 2;
  1470. break;
  1471. case asBC_PshC8:
  1472. l_sp -= 2;
  1473. *(asQWORD*)l_sp = asBC_QWORDARG(l_bc);
  1474. l_bc += 3;
  1475. break;
  1476. case asBC_RDS8:
  1477. #ifndef AS_64BIT_PTR
  1478. *(asQWORD*)(l_sp-1) = *(asQWORD*)*(size_t*)l_sp;
  1479. --l_sp;
  1480. #else
  1481. *(asQWORD*)l_sp = *(asQWORD*)*(size_t*)l_sp;
  1482. #endif
  1483. l_bc++;
  1484. break;
  1485. case asBC_SWAP8:
  1486. {
  1487. asQWORD q = *(asQWORD*)l_sp;
  1488. *(asQWORD*)l_sp = *(asQWORD*)(l_sp+2);
  1489. *(asQWORD*)(l_sp+2) = q;
  1490. l_bc++;
  1491. }
  1492. break;
  1493. //----------------------------
  1494. // Comparisons
  1495. case asBC_CMPd:
  1496. {
  1497. double dbl = *(double*)(l_fp - asBC_SWORDARG0(l_bc)) - *(double*)(l_fp - asBC_SWORDARG1(l_bc));
  1498. if( dbl == 0 ) *(int*)&regs.valueRegister = 0;
  1499. else if( dbl < 0 ) *(int*)&regs.valueRegister = -1;
  1500. else *(int*)&regs.valueRegister = 1;
  1501. l_bc += 2;
  1502. }
  1503. break;
  1504. case asBC_CMPu:
  1505. {
  1506. asDWORD d = *(asDWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  1507. asDWORD d2 = *(asDWORD*)(l_fp - asBC_SWORDARG1(l_bc));
  1508. if( d == d2 ) *(int*)&regs.valueRegister = 0;
  1509. else if( d < d2 ) *(int*)&regs.valueRegister = -1;
  1510. else *(int*)&regs.valueRegister = 1;
  1511. l_bc += 2;
  1512. }
  1513. break;
  1514. case asBC_CMPf:
  1515. {
  1516. float f = *(float*)(l_fp - asBC_SWORDARG0(l_bc)) - *(float*)(l_fp - asBC_SWORDARG1(l_bc));
  1517. if( f == 0 ) *(int*)&regs.valueRegister = 0;
  1518. else if( f < 0 ) *(int*)&regs.valueRegister = -1;
  1519. else *(int*)&regs.valueRegister = 1;
  1520. l_bc += 2;
  1521. }
  1522. break;
  1523. case asBC_CMPi:
  1524. {
  1525. int i = *(int*)(l_fp - asBC_SWORDARG0(l_bc)) - *(int*)(l_fp - asBC_SWORDARG1(l_bc));
  1526. if( i == 0 ) *(int*)&regs.valueRegister = 0;
  1527. else if( i < 0 ) *(int*)&regs.valueRegister = -1;
  1528. else *(int*)&regs.valueRegister = 1;
  1529. l_bc += 2;
  1530. }
  1531. break;
  1532. //----------------------------
  1533. // Comparisons with constant value
  1534. case asBC_CMPIi:
  1535. {
  1536. int i = *(int*)(l_fp - asBC_SWORDARG0(l_bc)) - asBC_INTARG(l_bc);
  1537. if( i == 0 ) *(int*)&regs.valueRegister = 0;
  1538. else if( i < 0 ) *(int*)&regs.valueRegister = -1;
  1539. else *(int*)&regs.valueRegister = 1;
  1540. l_bc += 2;
  1541. }
  1542. break;
  1543. case asBC_CMPIf:
  1544. {
  1545. float f = *(float*)(l_fp - asBC_SWORDARG0(l_bc)) - asBC_FLOATARG(l_bc);
  1546. if( f == 0 ) *(int*)&regs.valueRegister = 0;
  1547. else if( f < 0 ) *(int*)&regs.valueRegister = -1;
  1548. else *(int*)&regs.valueRegister = 1;
  1549. l_bc += 2;
  1550. }
  1551. break;
  1552. case asBC_CMPIu:
  1553. {
  1554. asDWORD d1 = *(asDWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  1555. asDWORD d2 = asBC_DWORDARG(l_bc);
  1556. if( d1 == d2 ) *(int*)&regs.valueRegister = 0;
  1557. else if( d1 < d2 ) *(int*)&regs.valueRegister = -1;
  1558. else *(int*)&regs.valueRegister = 1;
  1559. l_bc += 2;
  1560. }
  1561. break;
  1562. case asBC_JMPP:
  1563. l_bc += 1 + (*(int*)(l_fp - asBC_SWORDARG0(l_bc)))*2;
  1564. break;
  1565. case asBC_PopRPtr:
  1566. *(asPTRWORD*)&regs.valueRegister = *(asPTRWORD*)l_sp;
  1567. l_sp += AS_PTR_SIZE;
  1568. l_bc++;
  1569. break;
  1570. case asBC_PshRPtr:
  1571. l_sp -= AS_PTR_SIZE;
  1572. *(asPTRWORD*)l_sp = *(asPTRWORD*)&regs.valueRegister;
  1573. l_bc++;
  1574. break;
  1575. case asBC_STR:
  1576. {
  1577. // Get the string id from the argument
  1578. asWORD w = asBC_WORDARG0(l_bc);
  1579. // Push the string pointer on the stack
  1580. const asCString &b = engine->GetConstantString(w);
  1581. l_sp -= AS_PTR_SIZE;
  1582. *(asPTRWORD*)l_sp = (asPTRWORD)(size_t)b.AddressOf();
  1583. // Push the string length on the stack
  1584. --l_sp;
  1585. *l_sp = (asDWORD)b.GetLength();
  1586. l_bc++;
  1587. }
  1588. break;
  1589. case asBC_CALLSYS:
  1590. {
  1591. // Get function ID from the argument
  1592. int i = asBC_INTARG(l_bc);
  1593. // Need to move the values back to the context as the called functions
  1594. // may use the debug interface to inspect the registers
  1595. regs.programPointer = l_bc;
  1596. regs.stackPointer = l_sp;
  1597. regs.stackFramePointer = l_fp;
  1598. l_sp += CallSystemFunction(i, this, 0);
  1599. // Update the program position after the call so that line number is correct
  1600. l_bc += 2;
  1601. if( regs.doProcessSuspend )
  1602. {
  1603. // Should the execution be suspended?
  1604. if( doSuspend )
  1605. {
  1606. regs.programPointer = l_bc;
  1607. regs.stackPointer = l_sp;
  1608. regs.stackFramePointer = l_fp;
  1609. status = asEXECUTION_SUSPENDED;
  1610. return;
  1611. }
  1612. // An exception might have been raised
  1613. if( status != asEXECUTION_ACTIVE )
  1614. {
  1615. regs.programPointer = l_bc;
  1616. regs.stackPointer = l_sp;
  1617. regs.stackFramePointer = l_fp;
  1618. return;
  1619. }
  1620. }
  1621. }
  1622. break;
  1623. case asBC_CALLBND:
  1624. {
  1625. // Get the function ID from the stack
  1626. int i = asBC_INTARG(l_bc);
  1627. l_bc += 2;
  1628. asASSERT( i >= 0 );
  1629. asASSERT( i & FUNC_IMPORTED );
  1630. // Need to move the values back to the context
  1631. regs.programPointer = l_bc;
  1632. regs.stackPointer = l_sp;
  1633. regs.stackFramePointer = l_fp;
  1634. int funcID = engine->importedFunctions[i&0xFFFF]->boundFunctionId;
  1635. if( funcID == -1 )
  1636. {
  1637. SetInternalException(TXT_UNBOUND_FUNCTION);
  1638. return;
  1639. }
  1640. else
  1641. {
  1642. asCScriptFunction *func = engine->GetScriptFunction(funcID);
  1643. CallScriptFunction(func);
  1644. }
  1645. // Extract the values from the context again
  1646. l_bc = regs.programPointer;
  1647. l_sp = regs.stackPointer;
  1648. l_fp = regs.stackFramePointer;
  1649. // If status isn't active anymore then we must stop
  1650. if( status != asEXECUTION_ACTIVE )
  1651. return;
  1652. }
  1653. break;
  1654. case asBC_SUSPEND:
  1655. if( regs.doProcessSuspend )
  1656. {
  1657. if( lineCallback )
  1658. {
  1659. regs.programPointer = l_bc;
  1660. regs.stackPointer = l_sp;
  1661. regs.stackFramePointer = l_fp;
  1662. CallLineCallback();
  1663. }
  1664. if( doSuspend )
  1665. {
  1666. l_bc++;
  1667. // Need to move the values back to the context
  1668. regs.programPointer = l_bc;
  1669. regs.stackPointer = l_sp;
  1670. regs.stackFramePointer = l_fp;
  1671. status = asEXECUTION_SUSPENDED;
  1672. return;
  1673. }
  1674. }
  1675. l_bc++;
  1676. break;
  1677. case asBC_ALLOC:
  1678. {
  1679. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(l_bc);
  1680. int func = asBC_INTARG(l_bc+AS_PTR_SIZE);
  1681. if( objType->flags & asOBJ_SCRIPT_OBJECT )
  1682. {
  1683. // Pre-allocate the memory
  1684. asDWORD *mem = (asDWORD*)engine->CallAlloc(objType);
  1685. // Pre-initialize the memory by calling the constructor for asCScriptObject
  1686. ScriptObject_Construct(objType, (asCScriptObject*)mem);
  1687. // Call the constructor to initalize the memory
  1688. asCScriptFunction *f = engine->scriptFunctions[func];
  1689. asDWORD **a = (asDWORD**)*(size_t*)(l_sp + f->GetSpaceNeededForArguments());
  1690. if( a ) *a = mem;
  1691. // Push the object pointer on the stack
  1692. l_sp -= AS_PTR_SIZE;
  1693. *(size_t*)l_sp = (size_t)mem;
  1694. l_bc += 2+AS_PTR_SIZE;
  1695. // Need to move the values back to the context
  1696. regs.programPointer = l_bc;
  1697. regs.stackPointer = l_sp;
  1698. regs.stackFramePointer = l_fp;
  1699. CallScriptFunction(f);
  1700. // Extract the values from the context again
  1701. l_bc = regs.programPointer;
  1702. l_sp = regs.stackPointer;
  1703. l_fp = regs.stackFramePointer;
  1704. // If status isn't active anymore then we must stop
  1705. if( status != asEXECUTION_ACTIVE )
  1706. return;
  1707. }
  1708. else
  1709. {
  1710. // Pre-allocate the memory
  1711. asDWORD *mem = (asDWORD*)engine->CallAlloc(objType);
  1712. if( func )
  1713. {
  1714. // Need to move the values back to the context as the called functions
  1715. // may use the debug interface to inspect the registers
  1716. regs.programPointer = l_bc;
  1717. regs.stackPointer = l_sp;
  1718. regs.stackFramePointer = l_fp;
  1719. l_sp += CallSystemFunction(func, this, mem);
  1720. }
  1721. // Pop the variable address from the stack
  1722. asDWORD **a = (asDWORD**)*(size_t*)l_sp;
  1723. l_sp += AS_PTR_SIZE;
  1724. if( a ) *a = mem;
  1725. l_bc += 2+AS_PTR_SIZE;
  1726. if( regs.doProcessSuspend )
  1727. {
  1728. // Should the execution be suspended?
  1729. if( doSuspend )
  1730. {
  1731. regs.programPointer = l_bc;
  1732. regs.stackPointer = l_sp;
  1733. regs.stackFramePointer = l_fp;
  1734. status = asEXECUTION_SUSPENDED;
  1735. return;
  1736. }
  1737. // An exception might have been raised
  1738. if( status != asEXECUTION_ACTIVE )
  1739. {
  1740. regs.programPointer = l_bc;
  1741. regs.stackPointer = l_sp;
  1742. regs.stackFramePointer = l_fp;
  1743. engine->CallFree(mem);
  1744. *a = 0;
  1745. return;
  1746. }
  1747. }
  1748. }
  1749. }
  1750. break;
  1751. case asBC_FREE:
  1752. {
  1753. // Get the variable that holds the object handle/reference
  1754. asPTRWORD *a = (asPTRWORD*)size_t(l_fp - asBC_SWORDARG0(l_bc));
  1755. if( *a )
  1756. {
  1757. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(l_bc);
  1758. asSTypeBehaviour *beh = &objType->beh;
  1759. // Need to move the values back to the context as the called functions
  1760. // may use the debug interface to inspect the registers
  1761. regs.programPointer = l_bc;
  1762. regs.stackPointer = l_sp;
  1763. regs.stackFramePointer = l_fp;
  1764. if( beh->release )
  1765. {
  1766. engine->CallObjectMethod((void*)(size_t)*a, beh->release);
  1767. }
  1768. else
  1769. {
  1770. if( beh->destruct )
  1771. {
  1772. engine->CallObjectMethod((void*)(size_t)*a, beh->destruct);
  1773. }
  1774. engine->CallFree((void*)(size_t)*a);
  1775. }
  1776. // Clear the variable
  1777. *a = 0;
  1778. }
  1779. }
  1780. l_bc += 1+AS_PTR_SIZE;
  1781. break;
  1782. case asBC_LOADOBJ:
  1783. {
  1784. // Move the object pointer from the object variable into the object register
  1785. void **a = (void**)(l_fp - asBC_SWORDARG0(l_bc));
  1786. regs.objectType = 0;
  1787. regs.objectRegister = *a;
  1788. *a = 0;
  1789. }
  1790. l_bc++;
  1791. break;
  1792. case asBC_STOREOBJ:
  1793. // Move the object pointer from the object register to the object variable
  1794. *(size_t*)(l_fp - asBC_SWORDARG0(l_bc)) = size_t(regs.objectRegister);
  1795. regs.objectRegister = 0;
  1796. l_bc++;
  1797. break;
  1798. case asBC_GETOBJ:
  1799. {
  1800. // Read variable index from location on stack
  1801. size_t *a = (size_t*)(l_sp + asBC_WORDARG0(l_bc));
  1802. asDWORD offset = *(asDWORD*)a;
  1803. // Move pointer from variable to the same location on the stack
  1804. size_t *v = (size_t*)(l_fp - offset);
  1805. *a = *v;
  1806. // Clear variable
  1807. *v = 0;
  1808. }
  1809. l_bc++;
  1810. break;
  1811. case asBC_REFCPY:
  1812. {
  1813. asCObjectType *objType = (asCObjectType*)(size_t)asBC_PTRARG(l_bc);
  1814. asSTypeBehaviour *beh = &objType->beh;
  1815. // Pop address of destination pointer from the stack
  1816. void **d = (void**)*(size_t*)l_sp;
  1817. l_sp += AS_PTR_SIZE;
  1818. // Read wanted pointer from the stack
  1819. void *s = (void*)*(size_t*)l_sp;
  1820. // Need to move the values back to the context as the called functions
  1821. // may use the debug interface to inspect the registers
  1822. regs.programPointer = l_bc;
  1823. regs.stackPointer = l_sp;
  1824. regs.stackFramePointer = l_fp;
  1825. // Release previous object held by destination pointer
  1826. if( *d != 0 )
  1827. engine->CallObjectMethod(*d, beh->release);
  1828. // Increase ref counter of wanted object
  1829. if( s != 0 )
  1830. engine->CallObjectMethod(s, beh->addref);
  1831. // Set the new object in the destination
  1832. *d = s;
  1833. }
  1834. l_bc += 1+AS_PTR_SIZE;
  1835. break;
  1836. case asBC_CHKREF:
  1837. {
  1838. // Verify if the pointer on the stack is null
  1839. // This is used when validating a pointer that an operator will work on
  1840. size_t a = *(size_t*)l_sp;
  1841. if( a == 0 )
  1842. {
  1843. regs.programPointer = l_bc;
  1844. regs.stackPointer = l_sp;
  1845. regs.stackFramePointer = l_fp;
  1846. SetInternalException(TXT_NULL_POINTER_ACCESS);
  1847. return;
  1848. }
  1849. }
  1850. l_bc++;
  1851. break;
  1852. case asBC_GETOBJREF:
  1853. {
  1854. // Get the location on the stack where the reference will be placed
  1855. size_t *a = (size_t*)(l_sp + asBC_WORDARG0(l_bc));
  1856. // Replace the variable index with the object handle held in the variable
  1857. *(size_t**)a = *(size_t**)(l_fp - *a);
  1858. }
  1859. l_bc++;
  1860. break;
  1861. case asBC_GETREF:
  1862. {
  1863. // Get the location on the stack where the reference will be placed
  1864. size_t *a = (size_t*)(l_sp + asBC_WORDARG0(l_bc));
  1865. // Replace the variable index with the address of the variable
  1866. *(size_t**)a = (size_t*)(l_fp - (int)*a);
  1867. }
  1868. l_bc++;
  1869. break;
  1870. case asBC_SWAP48:
  1871. {
  1872. asDWORD d = *(asDWORD*)l_sp;
  1873. asQWORD q = *(asQWORD*)(l_sp+1);
  1874. *(asQWORD*)l_sp = q;
  1875. *(asDWORD*)(l_sp+2) = d;
  1876. l_bc++;
  1877. }
  1878. break;
  1879. case asBC_SWAP84:
  1880. {
  1881. asQWORD q = *(asQWORD*)l_sp;
  1882. asDWORD d = *(asDWORD*)(l_sp+2);
  1883. *(asDWORD*)l_sp = d;
  1884. *(asQWORD*)(l_sp+1) = q;
  1885. l_bc++;
  1886. }
  1887. break;
  1888. case asBC_OBJTYPE:
  1889. // Push the object type on the stack
  1890. l_sp -= AS_PTR_SIZE;
  1891. *(asPTRWORD*)l_sp = asBC_PTRARG(l_bc);
  1892. l_bc += 1+AS_PTR_SIZE;
  1893. break;
  1894. case asBC_TYPEID:
  1895. // Equivalent to PshC4, but kept as separate instruction for bytecode serialization
  1896. --l_sp;
  1897. *l_sp = asBC_DWORDARG(l_bc);
  1898. l_bc += 2;
  1899. break;
  1900. case asBC_SetV4:
  1901. *(l_fp - asBC_SWORDARG0(l_bc)) = asBC_DWORDARG(l_bc);
  1902. l_bc += 2;
  1903. break;
  1904. case asBC_SetV8:
  1905. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = asBC_QWORDARG(l_bc);
  1906. l_bc += 3;
  1907. break;
  1908. case asBC_ADDSi:
  1909. *(size_t*)l_sp = size_t(asPTRWORD(*(size_t*)l_sp) + asBC_SWORDARG0(l_bc));
  1910. l_bc += 2;
  1911. break;
  1912. case asBC_CpyVtoV4:
  1913. *(l_fp - asBC_SWORDARG0(l_bc)) = *(l_fp - asBC_SWORDARG1(l_bc));
  1914. l_bc += 2;
  1915. break;
  1916. case asBC_CpyVtoV8:
  1917. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc));
  1918. l_bc += 2;
  1919. break;
  1920. case asBC_CpyVtoR4:
  1921. *(asDWORD*)&regs.valueRegister = *(asDWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  1922. l_bc++;
  1923. break;
  1924. case asBC_CpyVtoR8:
  1925. *(asQWORD*)&regs.valueRegister = *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  1926. l_bc++;
  1927. break;
  1928. case asBC_CpyVtoG4:
  1929. *(asDWORD*)(size_t)asBC_PTRARG(l_bc) = *(asDWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  1930. l_bc += 1 + AS_PTR_SIZE;
  1931. break;
  1932. case asBC_CpyRtoV4:
  1933. *(asDWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asDWORD*)&regs.valueRegister;
  1934. l_bc++;
  1935. break;
  1936. case asBC_CpyRtoV8:
  1937. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = regs.valueRegister;
  1938. l_bc++;
  1939. break;
  1940. case asBC_CpyGtoV4:
  1941. *(asDWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asDWORD*)(size_t)asBC_PTRARG(l_bc);
  1942. l_bc += 1 + AS_PTR_SIZE;
  1943. break;
  1944. case asBC_WRTV1:
  1945. // The pointer in the register points to a byte, and *(l_fp - offset) too
  1946. **(asBYTE**)&regs.valueRegister = *(asBYTE*)(l_fp - asBC_SWORDARG0(l_bc));
  1947. l_bc++;
  1948. break;
  1949. case asBC_WRTV2:
  1950. // The pointer in the register points to a word, and *(l_fp - offset) too
  1951. **(asWORD**)&regs.valueRegister = *(asWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  1952. l_bc++;
  1953. break;
  1954. case asBC_WRTV4:
  1955. **(asDWORD**)&regs.valueRegister = *(l_fp - asBC_SWORDARG0(l_bc));
  1956. l_bc++;
  1957. break;
  1958. case asBC_WRTV8:
  1959. **(asQWORD**)&regs.valueRegister = *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  1960. l_bc++;
  1961. break;
  1962. case asBC_RDR1:
  1963. {
  1964. // The pointer in the register points to a byte, and *(l_fp - offset) will also point to a byte
  1965. asBYTE *bPtr = (asBYTE*)(l_fp - asBC_SWORDARG0(l_bc));
  1966. bPtr[0] = **(asBYTE**)&regs.valueRegister; // read the byte
  1967. bPtr[1] = 0; // 0 the rest of the DWORD
  1968. bPtr[2] = 0;
  1969. bPtr[3] = 0;
  1970. }
  1971. l_bc++;
  1972. break;
  1973. case asBC_RDR2:
  1974. {
  1975. // The pointer in the register points to a word, and *(l_fp - offset) will also point to a word
  1976. asWORD *wPtr = (asWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  1977. wPtr[0] = **(asWORD**)&regs.valueRegister; // read the word
  1978. wPtr[1] = 0; // 0 the rest of the DWORD
  1979. }
  1980. l_bc++;
  1981. break;
  1982. case asBC_RDR4:
  1983. *(asDWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = **(asDWORD**)&regs.valueRegister;
  1984. l_bc++;
  1985. break;
  1986. case asBC_RDR8:
  1987. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = **(asQWORD**)&regs.valueRegister;
  1988. l_bc++;
  1989. break;
  1990. case asBC_LDG:
  1991. *(asPTRWORD*)&regs.valueRegister = asBC_PTRARG(l_bc);
  1992. l_bc += 1+AS_PTR_SIZE;
  1993. break;
  1994. case asBC_LDV:
  1995. *(asDWORD**)&regs.valueRegister = (l_fp - asBC_SWORDARG0(l_bc));
  1996. l_bc++;
  1997. break;
  1998. case asBC_PGA:
  1999. l_sp -= AS_PTR_SIZE;
  2000. *(asPTRWORD*)l_sp = asBC_PTRARG(l_bc);
  2001. l_bc += 1+AS_PTR_SIZE;
  2002. break;
  2003. case asBC_RDS4:
  2004. #ifndef AS_64BIT_PTR
  2005. *l_sp = *(asDWORD*)*(size_t*)l_sp;
  2006. #else
  2007. {
  2008. asDWORD d = *(asDWORD*)*(size_t*)l_sp;
  2009. l_sp++;
  2010. *l_sp = d;
  2011. }
  2012. #endif
  2013. l_bc++;
  2014. break;
  2015. case asBC_VAR:
  2016. l_sp -= AS_PTR_SIZE;
  2017. *(size_t*)l_sp = (size_t)asBC_SWORDARG0(l_bc);
  2018. l_bc++;
  2019. break;
  2020. //----------------------------
  2021. // Type conversions
  2022. case asBC_iTOf:
  2023. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = float(*(int*)(l_fp - asBC_SWORDARG0(l_bc)));
  2024. l_bc++;
  2025. break;
  2026. case asBC_fTOi:
  2027. *(l_fp - asBC_SWORDARG0(l_bc)) = int(*(float*)(l_fp - asBC_SWORDARG0(l_bc)));
  2028. l_bc++;
  2029. break;
  2030. case asBC_uTOf:
  2031. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = float(*(l_fp - asBC_SWORDARG0(l_bc)));
  2032. l_bc++;
  2033. break;
  2034. case asBC_fTOu:
  2035. // We must cast to int first, because on some compilers the cast of a negative float value to uint result in 0
  2036. *(l_fp - asBC_SWORDARG0(l_bc)) = asUINT(int(*(float*)(l_fp - asBC_SWORDARG0(l_bc))));
  2037. l_bc++;
  2038. break;
  2039. case asBC_sbTOi:
  2040. // *(l_fp - offset) points to a char, and will point to an int afterwards
  2041. *(l_fp - asBC_SWORDARG0(l_bc)) = *(signed char*)(l_fp - asBC_SWORDARG0(l_bc));
  2042. l_bc++;
  2043. break;
  2044. case asBC_swTOi:
  2045. // *(l_fp - offset) points to a short, and will point to an int afterwards
  2046. *(l_fp - asBC_SWORDARG0(l_bc)) = *(short*)(l_fp - asBC_SWORDARG0(l_bc));
  2047. l_bc++;
  2048. break;
  2049. case asBC_ubTOi:
  2050. // (l_fp - offset) points to a byte, and will point to an int afterwards
  2051. *(l_fp - asBC_SWORDARG0(l_bc)) = *(asBYTE*)(l_fp - asBC_SWORDARG0(l_bc));
  2052. l_bc++;
  2053. break;
  2054. case asBC_uwTOi:
  2055. // *(l_fp - offset) points to a word, and will point to an int afterwards
  2056. *(l_fp - asBC_SWORDARG0(l_bc)) = *(asWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  2057. l_bc++;
  2058. break;
  2059. case asBC_dTOi:
  2060. *(l_fp - asBC_SWORDARG0(l_bc)) = int(*(double*)(l_fp - asBC_SWORDARG1(l_bc)));
  2061. l_bc += 2;
  2062. break;
  2063. case asBC_dTOu:
  2064. // We must cast to int first, because on some compilers the cast of a negative float value to uint result in 0
  2065. *(l_fp - asBC_SWORDARG0(l_bc)) = asUINT(int(*(double*)(l_fp - asBC_SWORDARG1(l_bc))));
  2066. l_bc += 2;
  2067. break;
  2068. case asBC_dTOf:
  2069. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = float(*(double*)(l_fp - asBC_SWORDARG1(l_bc)));
  2070. l_bc += 2;
  2071. break;
  2072. case asBC_iTOd:
  2073. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = double(*(int*)(l_fp - asBC_SWORDARG1(l_bc)));
  2074. l_bc += 2;
  2075. break;
  2076. case asBC_uTOd:
  2077. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = double(*(asUINT*)(l_fp - asBC_SWORDARG1(l_bc)));
  2078. l_bc += 2;
  2079. break;
  2080. case asBC_fTOd:
  2081. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = double(*(float*)(l_fp - asBC_SWORDARG1(l_bc)));
  2082. l_bc += 2;
  2083. break;
  2084. //------------------------------
  2085. // Math operations
  2086. case asBC_ADDi:
  2087. *(int*)(l_fp - asBC_SWORDARG0(l_bc)) = *(int*)(l_fp - asBC_SWORDARG1(l_bc)) + *(int*)(l_fp - asBC_SWORDARG2(l_bc));
  2088. l_bc += 2;
  2089. break;
  2090. case asBC_SUBi:
  2091. *(int*)(l_fp - asBC_SWORDARG0(l_bc)) = *(int*)(l_fp - asBC_SWORDARG1(l_bc)) - *(int*)(l_fp - asBC_SWORDARG2(l_bc));
  2092. l_bc += 2;
  2093. break;
  2094. case asBC_MULi:
  2095. *(int*)(l_fp - asBC_SWORDARG0(l_bc)) = *(int*)(l_fp - asBC_SWORDARG1(l_bc)) * *(int*)(l_fp - asBC_SWORDARG2(l_bc));
  2096. l_bc += 2;
  2097. break;
  2098. case asBC_DIVi:
  2099. {
  2100. int divider = *(int*)(l_fp - asBC_SWORDARG2(l_bc));
  2101. if( divider == 0 )
  2102. {
  2103. // Need to move the values back to the context
  2104. regs.programPointer = l_bc;
  2105. regs.stackPointer = l_sp;
  2106. regs.stackFramePointer = l_fp;
  2107. // Raise exception
  2108. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2109. return;
  2110. }
  2111. *(int*)(l_fp - asBC_SWORDARG0(l_bc)) = *(int*)(l_fp - asBC_SWORDARG1(l_bc)) / divider;
  2112. }
  2113. l_bc += 2;
  2114. break;
  2115. case asBC_MODi:
  2116. {
  2117. int divider = *(int*)(l_fp - asBC_SWORDARG2(l_bc));
  2118. if( divider == 0 )
  2119. {
  2120. // Need to move the values back to the context
  2121. regs.programPointer = l_bc;
  2122. regs.stackPointer = l_sp;
  2123. regs.stackFramePointer = l_fp;
  2124. // Raise exception
  2125. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2126. return;
  2127. }
  2128. *(int*)(l_fp - asBC_SWORDARG0(l_bc)) = *(int*)(l_fp - asBC_SWORDARG1(l_bc)) % divider;
  2129. }
  2130. l_bc += 2;
  2131. break;
  2132. case asBC_ADDf:
  2133. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = *(float*)(l_fp - asBC_SWORDARG1(l_bc)) + *(float*)(l_fp - asBC_SWORDARG2(l_bc));
  2134. l_bc += 2;
  2135. break;
  2136. case asBC_SUBf:
  2137. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = *(float*)(l_fp - asBC_SWORDARG1(l_bc)) - *(float*)(l_fp - asBC_SWORDARG2(l_bc));
  2138. l_bc += 2;
  2139. break;
  2140. case asBC_MULf:
  2141. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = *(float*)(l_fp - asBC_SWORDARG1(l_bc)) * *(float*)(l_fp - asBC_SWORDARG2(l_bc));
  2142. l_bc += 2;
  2143. break;
  2144. case asBC_DIVf:
  2145. {
  2146. float divider = *(float*)(l_fp - asBC_SWORDARG2(l_bc));
  2147. if( divider == 0 )
  2148. {
  2149. // Need to move the values back to the context
  2150. regs.programPointer = l_bc;
  2151. regs.stackPointer = l_sp;
  2152. regs.stackFramePointer = l_fp;
  2153. // Raise exception
  2154. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2155. return;
  2156. }
  2157. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = *(float*)(l_fp - asBC_SWORDARG1(l_bc)) / divider;
  2158. }
  2159. l_bc += 2;
  2160. break;
  2161. case asBC_MODf:
  2162. {
  2163. float divider = *(float*)(l_fp - asBC_SWORDARG2(l_bc));
  2164. if( divider == 0 )
  2165. {
  2166. // Need to move the values back to the context
  2167. regs.programPointer = l_bc;
  2168. regs.stackPointer = l_sp;
  2169. regs.stackFramePointer = l_fp;
  2170. // Raise exception
  2171. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2172. return;
  2173. }
  2174. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = fmodf(*(float*)(l_fp - asBC_SWORDARG1(l_bc)), divider);
  2175. }
  2176. l_bc += 2;
  2177. break;
  2178. case asBC_ADDd:
  2179. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = *(double*)(l_fp - asBC_SWORDARG1(l_bc)) + *(double*)(l_fp - asBC_SWORDARG2(l_bc));
  2180. l_bc += 2;
  2181. break;
  2182. case asBC_SUBd:
  2183. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = *(double*)(l_fp - asBC_SWORDARG1(l_bc)) - *(double*)(l_fp - asBC_SWORDARG2(l_bc));
  2184. l_bc += 2;
  2185. break;
  2186. case asBC_MULd:
  2187. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = *(double*)(l_fp - asBC_SWORDARG1(l_bc)) * *(double*)(l_fp - asBC_SWORDARG2(l_bc));
  2188. l_bc += 2;
  2189. break;
  2190. case asBC_DIVd:
  2191. {
  2192. double divider = *(double*)(l_fp - asBC_SWORDARG2(l_bc));
  2193. if( divider == 0 )
  2194. {
  2195. // Need to move the values back to the context
  2196. regs.programPointer = l_bc;
  2197. regs.stackPointer = l_sp;
  2198. regs.stackFramePointer = l_fp;
  2199. // Raise exception
  2200. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2201. return;
  2202. }
  2203. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = *(double*)(l_fp - asBC_SWORDARG1(l_bc)) / divider;
  2204. l_bc += 2;
  2205. }
  2206. break;
  2207. case asBC_MODd:
  2208. {
  2209. double divider = *(double*)(l_fp - asBC_SWORDARG2(l_bc));
  2210. if( divider == 0 )
  2211. {
  2212. // Need to move the values back to the context
  2213. regs.programPointer = l_bc;
  2214. regs.stackPointer = l_sp;
  2215. regs.stackFramePointer = l_fp;
  2216. // Raise exception
  2217. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2218. return;
  2219. }
  2220. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = fmod(*(double*)(l_fp - asBC_SWORDARG1(l_bc)), divider);
  2221. l_bc += 2;
  2222. }
  2223. break;
  2224. //------------------------------
  2225. // Math operations with constant value
  2226. case asBC_ADDIi:
  2227. *(int*)(l_fp - asBC_SWORDARG0(l_bc)) = *(int*)(l_fp - asBC_SWORDARG1(l_bc)) + asBC_INTARG(l_bc+1);
  2228. l_bc += 3;
  2229. break;
  2230. case asBC_SUBIi:
  2231. *(int*)(l_fp - asBC_SWORDARG0(l_bc)) = *(int*)(l_fp - asBC_SWORDARG1(l_bc)) - asBC_INTARG(l_bc+1);
  2232. l_bc += 3;
  2233. break;
  2234. case asBC_MULIi:
  2235. *(int*)(l_fp - asBC_SWORDARG0(l_bc)) = *(int*)(l_fp - asBC_SWORDARG1(l_bc)) * asBC_INTARG(l_bc+1);
  2236. l_bc += 3;
  2237. break;
  2238. case asBC_ADDIf:
  2239. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = *(float*)(l_fp - asBC_SWORDARG1(l_bc)) + asBC_FLOATARG(l_bc+1);
  2240. l_bc += 3;
  2241. break;
  2242. case asBC_SUBIf:
  2243. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = *(float*)(l_fp - asBC_SWORDARG1(l_bc)) - asBC_FLOATARG(l_bc+1);
  2244. l_bc += 3;
  2245. break;
  2246. case asBC_MULIf:
  2247. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = *(float*)(l_fp - asBC_SWORDARG1(l_bc)) * asBC_FLOATARG(l_bc+1);
  2248. l_bc += 3;
  2249. break;
  2250. //-----------------------------------
  2251. case asBC_SetG4:
  2252. *(asDWORD*)(size_t)asBC_PTRARG(l_bc) = asBC_DWORDARG(l_bc+AS_PTR_SIZE);
  2253. l_bc += 2 + AS_PTR_SIZE;
  2254. break;
  2255. case asBC_ChkRefS:
  2256. {
  2257. // Verify if the pointer on the stack refers to a non-null value
  2258. // This is used to validate a reference to a handle
  2259. asDWORD *a = (asDWORD*)*(size_t*)l_sp;
  2260. if( *a == 0 )
  2261. {
  2262. regs.programPointer = l_bc;
  2263. regs.stackPointer = l_sp;
  2264. regs.stackFramePointer = l_fp;
  2265. SetInternalException(TXT_NULL_POINTER_ACCESS);
  2266. return;
  2267. }
  2268. }
  2269. l_bc++;
  2270. break;
  2271. case asBC_ChkNullV:
  2272. {
  2273. // Verify if variable (on the stack) is not null
  2274. asDWORD *a = *(asDWORD**)(l_fp - asBC_SWORDARG0(l_bc));
  2275. if( a == 0 )
  2276. {
  2277. regs.programPointer = l_bc;
  2278. regs.stackPointer = l_sp;
  2279. regs.stackFramePointer = l_fp;
  2280. SetInternalException(TXT_NULL_POINTER_ACCESS);
  2281. return;
  2282. }
  2283. }
  2284. l_bc++;
  2285. break;
  2286. case asBC_CALLINTF:
  2287. {
  2288. int i = asBC_INTARG(l_bc);
  2289. l_bc += 2;
  2290. asASSERT( i >= 0 );
  2291. asASSERT( (i & FUNC_IMPORTED) == 0 );
  2292. // Need to move the values back to the context
  2293. regs.programPointer = l_bc;
  2294. regs.stackPointer = l_sp;
  2295. regs.stackFramePointer = l_fp;
  2296. CallInterfaceMethod(engine->GetScriptFunction(i));
  2297. // Extract the values from the context again
  2298. l_bc = regs.programPointer;
  2299. l_sp = regs.stackPointer;
  2300. l_fp = regs.stackFramePointer;
  2301. // If status isn't active anymore then we must stop
  2302. if( status != asEXECUTION_ACTIVE )
  2303. return;
  2304. }
  2305. break;
  2306. case asBC_iTOb:
  2307. {
  2308. // *(l_fp - offset) points to an int, and will point to a byte afterwards
  2309. // We need to use volatile here to tell the compiler not to rearrange
  2310. // read and write operations during optimizations.
  2311. volatile asDWORD val = *(l_fp - asBC_SWORDARG0(l_bc));
  2312. volatile asBYTE *bPtr = (asBYTE*)(l_fp - asBC_SWORDARG0(l_bc));
  2313. bPtr[0] = (asBYTE)val; // write the byte
  2314. bPtr[1] = 0; // 0 the rest of the DWORD
  2315. bPtr[2] = 0;
  2316. bPtr[3] = 0;
  2317. }
  2318. l_bc++;
  2319. break;
  2320. case asBC_iTOw:
  2321. {
  2322. // *(l_fp - offset) points to an int, and will point to word afterwards
  2323. // We need to use volatile here to tell the compiler not to rearrange
  2324. // read and write operations during optimizations.
  2325. volatile asDWORD val = *(l_fp - asBC_SWORDARG0(l_bc));
  2326. volatile asWORD *wPtr = (asWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  2327. wPtr[0] = (asWORD)val; // write the word
  2328. wPtr[1] = 0; // 0 the rest of the DWORD
  2329. }
  2330. l_bc++;
  2331. break;
  2332. case asBC_SetV1:
  2333. // TODO: This is exactly the same as SetV4. This is a left over from the time
  2334. // when the bytecode instructions were more tightly packed. It can now
  2335. // be removed. When removing it, make sure the value is correctly converted
  2336. // on big-endian CPUs.
  2337. // The byte is already stored correctly in the argument
  2338. *(l_fp - asBC_SWORDARG0(l_bc)) = asBC_DWORDARG(l_bc);
  2339. l_bc += 2;
  2340. break;
  2341. case asBC_SetV2:
  2342. // TODO: This is exactly the same as SetV4. This is a left over from the time
  2343. // when the bytecode instructions were more tightly packed. It can now
  2344. // be removed. When removing it, make sure the value is correctly converted
  2345. // on big-endian CPUs.
  2346. // The word is already stored correctly in the argument
  2347. *(l_fp - asBC_SWORDARG0(l_bc)) = asBC_DWORDARG(l_bc);
  2348. l_bc += 2;
  2349. break;
  2350. case asBC_Cast:
  2351. // Cast the handle at the top of the stack to the type in the argument
  2352. {
  2353. asDWORD **a = (asDWORD**)*(size_t*)l_sp;
  2354. if( a && *a )
  2355. {
  2356. asDWORD typeId = asBC_DWORDARG(l_bc);
  2357. asCScriptObject *obj = (asCScriptObject *)* a;
  2358. asCObjectType *objType = obj->objType;
  2359. asCObjectType *to = engine->GetObjectTypeFromTypeId(typeId);
  2360. // This instruction can only be used with script classes and interfaces
  2361. asASSERT( objType->flags & asOBJ_SCRIPT_OBJECT );
  2362. asASSERT( to->flags & asOBJ_SCRIPT_OBJECT );
  2363. if( objType->Implements(to) || objType->DerivesFrom(to) )
  2364. {
  2365. regs.objectType = 0;
  2366. regs.objectRegister = obj;
  2367. obj->AddRef();
  2368. }
  2369. else
  2370. {
  2371. // The object register should already be null, so there
  2372. // is no need to clear it if the cast is unsuccessful
  2373. asASSERT( regs.objectRegister == 0 );
  2374. }
  2375. }
  2376. l_sp += AS_PTR_SIZE;
  2377. }
  2378. l_bc += 2;
  2379. break;
  2380. case asBC_i64TOi:
  2381. *(l_fp - asBC_SWORDARG0(l_bc)) = int(*(asINT64*)(l_fp - asBC_SWORDARG1(l_bc)));
  2382. l_bc += 2;
  2383. break;
  2384. case asBC_uTOi64:
  2385. *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) = asINT64(*(asUINT*)(l_fp - asBC_SWORDARG1(l_bc)));
  2386. l_bc += 2;
  2387. break;
  2388. case asBC_iTOi64:
  2389. *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) = asINT64(*(int*)(l_fp - asBC_SWORDARG1(l_bc)));
  2390. l_bc += 2;
  2391. break;
  2392. case asBC_fTOi64:
  2393. *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) = asINT64(*(float*)(l_fp - asBC_SWORDARG1(l_bc)));
  2394. l_bc += 2;
  2395. break;
  2396. case asBC_dTOi64:
  2397. *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) = asINT64(*(double*)(l_fp - asBC_SWORDARG0(l_bc)));
  2398. l_bc++;
  2399. break;
  2400. case asBC_fTOu64:
  2401. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = asQWORD(asINT64(*(float*)(l_fp - asBC_SWORDARG1(l_bc))));
  2402. l_bc += 2;
  2403. break;
  2404. case asBC_dTOu64:
  2405. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = asQWORD(asINT64(*(double*)(l_fp - asBC_SWORDARG0(l_bc))));
  2406. l_bc++;
  2407. break;
  2408. case asBC_i64TOf:
  2409. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = float(*(asINT64*)(l_fp - asBC_SWORDARG1(l_bc)));
  2410. l_bc += 2;
  2411. break;
  2412. case asBC_u64TOf:
  2413. #if _MSC_VER <= 1200 // MSVC6
  2414. {
  2415. // MSVC6 doesn't permit UINT64 to double
  2416. asINT64 v = *(asINT64*)(l_fp - asBC_SWORDARG1(l_bc));
  2417. if( v < 0 )
  2418. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = 18446744073709551615.0f+float(v);
  2419. else
  2420. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = float(v);
  2421. }
  2422. #else
  2423. *(float*)(l_fp - asBC_SWORDARG0(l_bc)) = float(*(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)));
  2424. #endif
  2425. l_bc += 2;
  2426. break;
  2427. case asBC_i64TOd:
  2428. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = double(*(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)));
  2429. l_bc++;
  2430. break;
  2431. case asBC_u64TOd:
  2432. #if _MSC_VER <= 1200 // MSVC6
  2433. {
  2434. // MSVC6 doesn't permit UINT64 to double
  2435. asINT64 v = *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc));
  2436. if( v < 0 )
  2437. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = 18446744073709551615.0+double(v);
  2438. else
  2439. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = double(v);
  2440. }
  2441. #else
  2442. *(double*)(l_fp - asBC_SWORDARG0(l_bc)) = double(*(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)));
  2443. #endif
  2444. l_bc++;
  2445. break;
  2446. case asBC_NEGi64:
  2447. *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) = -*(asINT64*)(l_fp - asBC_SWORDARG0(l_bc));
  2448. l_bc++;
  2449. break;
  2450. case asBC_INCi64:
  2451. ++(**(asQWORD**)&regs.valueRegister);
  2452. l_bc++;
  2453. break;
  2454. case asBC_DECi64:
  2455. --(**(asQWORD**)&regs.valueRegister);
  2456. l_bc++;
  2457. break;
  2458. case asBC_BNOT64:
  2459. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = ~*(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  2460. l_bc++;
  2461. break;
  2462. case asBC_ADDi64:
  2463. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)) + *(asQWORD*)(l_fp - asBC_SWORDARG2(l_bc));
  2464. l_bc += 2;
  2465. break;
  2466. case asBC_SUBi64:
  2467. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)) - *(asQWORD*)(l_fp - asBC_SWORDARG2(l_bc));
  2468. l_bc += 2;
  2469. break;
  2470. case asBC_MULi64:
  2471. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)) * *(asQWORD*)(l_fp - asBC_SWORDARG2(l_bc));
  2472. l_bc += 2;
  2473. break;
  2474. case asBC_DIVi64:
  2475. {
  2476. asINT64 divider = *(asINT64*)(l_fp - asBC_SWORDARG2(l_bc));
  2477. if( divider == 0 )
  2478. {
  2479. // Need to move the values back to the context
  2480. regs.programPointer = l_bc;
  2481. regs.stackPointer = l_sp;
  2482. regs.stackFramePointer = l_fp;
  2483. // Raise exception
  2484. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2485. return;
  2486. }
  2487. *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asINT64*)(l_fp - asBC_SWORDARG1(l_bc)) / divider;
  2488. }
  2489. l_bc += 2;
  2490. break;
  2491. case asBC_MODi64:
  2492. {
  2493. asINT64 divider = *(asINT64*)(l_fp - asBC_SWORDARG2(l_bc));
  2494. if( divider == 0 )
  2495. {
  2496. // Need to move the values back to the context
  2497. regs.programPointer = l_bc;
  2498. regs.stackPointer = l_sp;
  2499. regs.stackFramePointer = l_fp;
  2500. // Raise exception
  2501. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2502. return;
  2503. }
  2504. *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asINT64*)(l_fp - asBC_SWORDARG1(l_bc)) % divider;
  2505. }
  2506. l_bc += 2;
  2507. break;
  2508. case asBC_BAND64:
  2509. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)) & *(asQWORD*)(l_fp - asBC_SWORDARG2(l_bc));
  2510. l_bc += 2;
  2511. break;
  2512. case asBC_BOR64:
  2513. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)) | *(asQWORD*)(l_fp - asBC_SWORDARG2(l_bc));
  2514. l_bc += 2;
  2515. break;
  2516. case asBC_BXOR64:
  2517. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)) ^ *(asQWORD*)(l_fp - asBC_SWORDARG2(l_bc));
  2518. l_bc += 2;
  2519. break;
  2520. case asBC_BSLL64:
  2521. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)) << *(l_fp - asBC_SWORDARG2(l_bc));
  2522. l_bc += 2;
  2523. break;
  2524. case asBC_BSRL64:
  2525. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)) >> *(l_fp - asBC_SWORDARG2(l_bc));
  2526. l_bc += 2;
  2527. break;
  2528. case asBC_BSRA64:
  2529. *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asINT64*)(l_fp - asBC_SWORDARG1(l_bc)) >> *(l_fp - asBC_SWORDARG2(l_bc));
  2530. l_bc += 2;
  2531. break;
  2532. case asBC_CMPi64:
  2533. {
  2534. asINT64 i = *(asINT64*)(l_fp - asBC_SWORDARG0(l_bc)) - *(asINT64*)(l_fp - asBC_SWORDARG1(l_bc));
  2535. if( i == 0 ) *(int*)&regs.valueRegister = 0;
  2536. else if( i < 0 ) *(int*)&regs.valueRegister = -1;
  2537. else *(int*)&regs.valueRegister = 1;
  2538. l_bc += 2;
  2539. }
  2540. break;
  2541. case asBC_CMPu64:
  2542. {
  2543. asQWORD d = *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  2544. asQWORD d2 = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc));
  2545. if( d == d2 ) *(int*)&regs.valueRegister = 0;
  2546. else if( d < d2 ) *(int*)&regs.valueRegister = -1;
  2547. else *(int*)&regs.valueRegister = 1;
  2548. l_bc += 2;
  2549. }
  2550. break;
  2551. case asBC_ChkNullS:
  2552. {
  2553. // Verify if the pointer on the stack is null
  2554. // This is used for example when validating handles passed as function arguments
  2555. size_t a = *(size_t*)(l_sp + asBC_WORDARG0(l_bc));
  2556. if( a == 0 )
  2557. {
  2558. regs.programPointer = l_bc;
  2559. regs.stackPointer = l_sp;
  2560. regs.stackFramePointer = l_fp;
  2561. SetInternalException(TXT_NULL_POINTER_ACCESS);
  2562. return;
  2563. }
  2564. }
  2565. l_bc++;
  2566. break;
  2567. case asBC_ClrHi:
  2568. #if AS_SIZEOF_BOOL == 1
  2569. {
  2570. // Clear the upper bytes, so that trash data don't interfere with boolean operations
  2571. // We need to use volatile here to tell the compiler it cannot
  2572. // change the order of read and write operations on the pointer.
  2573. volatile asBYTE *ptr = (asBYTE*)&regs.valueRegister;
  2574. ptr[1] = 0; // The boolean value is stored in the lower byte, so we clear the rest
  2575. ptr[2] = 0;
  2576. ptr[3] = 0;
  2577. }
  2578. #else
  2579. // We don't have anything to do here
  2580. #endif
  2581. l_bc++;
  2582. break;
  2583. case asBC_JitEntry:
  2584. {
  2585. if( currentFunction->jitFunction )
  2586. {
  2587. unsigned int jitOffset = asBC_WORDARG0(l_bc);
  2588. if( jitOffset )
  2589. {
  2590. // Resume JIT operation
  2591. regs.programPointer = l_bc;
  2592. regs.stackPointer = l_sp;
  2593. regs.stackFramePointer = l_fp;
  2594. // TODO: JIT: We should return from this function if the jitFunction tells us to
  2595. (currentFunction->jitFunction)(&regs, jitOffset-1);
  2596. l_bc = regs.programPointer;
  2597. l_sp = regs.stackPointer;
  2598. l_fp = regs.stackFramePointer;
  2599. break;
  2600. }
  2601. }
  2602. // Not a JIT resume point, treat as nop
  2603. l_bc++;
  2604. }
  2605. break;
  2606. case asBC_CallPtr:
  2607. {
  2608. // Get the function pointer from the local variable
  2609. asCScriptFunction *func = *(asCScriptFunction**)(l_fp - asBC_SWORDARG0(l_bc));
  2610. l_bc++;
  2611. // Need to move the values back to the context
  2612. regs.programPointer = l_bc;
  2613. regs.stackPointer = l_sp;
  2614. regs.stackFramePointer = l_fp;
  2615. if( func == 0 )
  2616. {
  2617. // TODO: funcdef: Should we have a different exception string?
  2618. SetInternalException(TXT_UNBOUND_FUNCTION);
  2619. return;
  2620. }
  2621. else
  2622. CallScriptFunction(func);
  2623. // Extract the values from the context again
  2624. l_bc = regs.programPointer;
  2625. l_sp = regs.stackPointer;
  2626. l_fp = regs.stackFramePointer;
  2627. // If status isn't active anymore then we must stop
  2628. if( status != asEXECUTION_ACTIVE )
  2629. return;
  2630. }
  2631. break;
  2632. case asBC_FuncPtr:
  2633. // Push the function pointer on the stack. The pointer is in the argument
  2634. l_sp -= AS_PTR_SIZE;
  2635. *(asPTRWORD*)l_sp = asBC_PTRARG(l_bc);
  2636. l_bc += 1+AS_PTR_SIZE;
  2637. break;
  2638. case asBC_LoadThisR:
  2639. {
  2640. // PshVPtr 0
  2641. asPTRWORD tmp = *(asPTRWORD*)l_fp;
  2642. // ADDSi
  2643. tmp = tmp + asBC_SWORDARG0(l_bc);
  2644. // PopRPtr
  2645. *(asPTRWORD*)&regs.valueRegister = tmp;
  2646. l_bc += 2;
  2647. }
  2648. break;
  2649. // Push the qword value of a variable on the stack
  2650. case asBC_PshV8:
  2651. l_sp -= 2;
  2652. *(asQWORD*)l_sp = *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  2653. l_bc++;
  2654. break;
  2655. case asBC_DIVu:
  2656. {
  2657. asUINT divider = *(asUINT*)(l_fp - asBC_SWORDARG2(l_bc));
  2658. if( divider == 0 )
  2659. {
  2660. // Need to move the values back to the context
  2661. regs.programPointer = l_bc;
  2662. regs.stackPointer = l_sp;
  2663. regs.stackFramePointer = l_fp;
  2664. // Raise exception
  2665. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2666. return;
  2667. }
  2668. *(asUINT*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asUINT*)(l_fp - asBC_SWORDARG1(l_bc)) / divider;
  2669. }
  2670. l_bc += 2;
  2671. break;
  2672. case asBC_MODu:
  2673. {
  2674. asUINT divider = *(asUINT*)(l_fp - asBC_SWORDARG2(l_bc));
  2675. if( divider == 0 )
  2676. {
  2677. // Need to move the values back to the context
  2678. regs.programPointer = l_bc;
  2679. regs.stackPointer = l_sp;
  2680. regs.stackFramePointer = l_fp;
  2681. // Raise exception
  2682. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2683. return;
  2684. }
  2685. *(asUINT*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asUINT*)(l_fp - asBC_SWORDARG1(l_bc)) % divider;
  2686. }
  2687. l_bc += 2;
  2688. break;
  2689. case asBC_DIVu64:
  2690. {
  2691. asQWORD divider = *(asQWORD*)(l_fp - asBC_SWORDARG2(l_bc));
  2692. if( divider == 0 )
  2693. {
  2694. // Need to move the values back to the context
  2695. regs.programPointer = l_bc;
  2696. regs.stackPointer = l_sp;
  2697. regs.stackFramePointer = l_fp;
  2698. // Raise exception
  2699. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2700. return;
  2701. }
  2702. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)) / divider;
  2703. }
  2704. l_bc += 2;
  2705. break;
  2706. case asBC_MODu64:
  2707. {
  2708. asQWORD divider = *(asQWORD*)(l_fp - asBC_SWORDARG2(l_bc));
  2709. if( divider == 0 )
  2710. {
  2711. // Need to move the values back to the context
  2712. regs.programPointer = l_bc;
  2713. regs.stackPointer = l_sp;
  2714. regs.stackFramePointer = l_fp;
  2715. // Raise exception
  2716. SetInternalException(TXT_DIVIDE_BY_ZERO);
  2717. return;
  2718. }
  2719. *(asQWORD*)(l_fp - asBC_SWORDARG0(l_bc)) = *(asQWORD*)(l_fp - asBC_SWORDARG1(l_bc)) % divider;
  2720. }
  2721. l_bc += 2;
  2722. break;
  2723. case asBC_LoadRObjR:
  2724. {
  2725. // PshVPtr x
  2726. asPTRWORD tmp = *(asPTRWORD*)(l_fp - asBC_SWORDARG0(l_bc));
  2727. // ADDSi y
  2728. tmp = tmp + asBC_SWORDARG1(l_bc);
  2729. // PopRPtr
  2730. *(asPTRWORD*)&regs.valueRegister = tmp;
  2731. l_bc += 3;
  2732. }
  2733. break;
  2734. case asBC_LoadVObjR:
  2735. {
  2736. // PSF x
  2737. asPTRWORD tmp = (asPTRWORD)(size_t)(l_fp - asBC_SWORDARG0(l_bc));
  2738. // ADDSi y
  2739. tmp = tmp + asBC_SWORDARG1(l_bc);
  2740. // PopRPtr
  2741. *(asPTRWORD*)&regs.valueRegister = tmp;
  2742. l_bc += 3;
  2743. }
  2744. break;
  2745. // Don't let the optimizer optimize for size,
  2746. // since it requires extra conditions and jumps
  2747. case 186: l_bc = (asDWORD*)186; break;
  2748. case 187: l_bc = (asDWORD*)187; break;
  2749. case 188: l_bc = (asDWORD*)188; break;
  2750. case 189: l_bc = (asDWORD*)189; break;
  2751. case 190: l_bc = (asDWORD*)190; break;
  2752. case 191: l_bc = (asDWORD*)191; break;
  2753. case 192: l_bc = (asDWORD*)192; break;
  2754. case 193: l_bc = (asDWORD*)193; break;
  2755. case 194: l_bc = (asDWORD*)194; break;
  2756. case 195: l_bc = (asDWORD*)195; break;
  2757. case 196: l_bc = (asDWORD*)196; break;
  2758. case 197: l_bc = (asDWORD*)197; break;
  2759. case 198: l_bc = (asDWORD*)198; break;
  2760. case 199: l_bc = (asDWORD*)199; break;
  2761. case 200: l_bc = (asDWORD*)200; break;
  2762. case 201: l_bc = (asDWORD*)201; break;
  2763. case 202: l_bc = (asDWORD*)202; break;
  2764. case 203: l_bc = (asDWORD*)203; break;
  2765. case 204: l_bc = (asDWORD*)204; break;
  2766. case 205: l_bc = (asDWORD*)205; break;
  2767. case 206: l_bc = (asDWORD*)206; break;
  2768. case 207: l_bc = (asDWORD*)207; break;
  2769. case 208: l_bc = (asDWORD*)208; break;
  2770. case 209: l_bc = (asDWORD*)209; break;
  2771. case 210: l_bc = (asDWORD*)210; break;
  2772. case 211: l_bc = (asDWORD*)211; break;
  2773. case 212: l_bc = (asDWORD*)212; break;
  2774. case 213: l_bc = (asDWORD*)213; break;
  2775. case 214: l_bc = (asDWORD*)214; break;
  2776. case 215: l_bc = (asDWORD*)215; break;
  2777. case 216: l_bc = (asDWORD*)216; break;
  2778. case 217: l_bc = (asDWORD*)217; break;
  2779. case 218: l_bc = (asDWORD*)218; break;
  2780. case 219: l_bc = (asDWORD*)219; break;
  2781. case 220: l_bc = (asDWORD*)220; break;
  2782. case 221: l_bc = (asDWORD*)221; break;
  2783. case 222: l_bc = (asDWORD*)222; break;
  2784. case 223: l_bc = (asDWORD*)223; break;
  2785. case 224: l_bc = (asDWORD*)224; break;
  2786. case 225: l_bc = (asDWORD*)225; break;
  2787. case 226: l_bc = (asDWORD*)226; break;
  2788. case 227: l_bc = (asDWORD*)227; break;
  2789. case 228: l_bc = (asDWORD*)228; break;
  2790. case 229: l_bc = (asDWORD*)229; break;
  2791. case 230: l_bc = (asDWORD*)230; break;
  2792. case 231: l_bc = (asDWORD*)231; break;
  2793. case 232: l_bc = (asDWORD*)232; break;
  2794. case 233: l_bc = (asDWORD*)233; break;
  2795. case 234: l_bc = (asDWORD*)234; break;
  2796. case 235: l_bc = (asDWORD*)235; break;
  2797. case 236: l_bc = (asDWORD*)236; break;
  2798. case 237: l_bc = (asDWORD*)237; break;
  2799. case 238: l_bc = (asDWORD*)238; break;
  2800. case 239: l_bc = (asDWORD*)239; break;
  2801. case 240: l_bc = (asDWORD*)240; break;
  2802. case 241: l_bc = (asDWORD*)241; break;
  2803. case 242: l_bc = (asDWORD*)242; break;
  2804. case 243: l_bc = (asDWORD*)243; break;
  2805. case 244: l_bc = (asDWORD*)244; break;
  2806. case 245: l_bc = (asDWORD*)245; break;
  2807. case 246: l_bc = (asDWORD*)246; break;
  2808. case 247: l_bc = (asDWORD*)247; break;
  2809. case 248: l_bc = (asDWORD*)248; break;
  2810. case 249: l_bc = (asDWORD*)249; break;
  2811. case 250: l_bc = (asDWORD*)250; break;
  2812. case 251: l_bc = (asDWORD*)251; break;
  2813. case 252: l_bc = (asDWORD*)252; break;
  2814. case 253: l_bc = (asDWORD*)253; break;
  2815. case 254: l_bc = (asDWORD*)254; break;
  2816. case 255: l_bc = (asDWORD*)255; break;
  2817. #ifdef AS_DEBUG
  2818. default:
  2819. asASSERT(false);
  2820. #endif
  2821. /*
  2822. default:
  2823. // This Microsoft specific code allows the
  2824. // compiler to optimize the switch case as
  2825. // it will know that the code will never
  2826. // reach this point
  2827. __assume(0);
  2828. */ }
  2829. #ifdef AS_DEBUG
  2830. asDWORD instr = *(asBYTE*)old;
  2831. if( instr != asBC_JMP && instr != asBC_JMPP && (instr < asBC_JZ || instr > asBC_JNP) &&
  2832. instr != asBC_CALL && instr != asBC_CALLBND && instr != asBC_CALLINTF && instr != asBC_RET && instr != asBC_ALLOC && instr != asBC_CallPtr )
  2833. {
  2834. asASSERT( (l_bc - old) == asBCTypeSize[asBCInfo[instr].type] );
  2835. }
  2836. #endif
  2837. }
  2838. SetInternalException(TXT_UNRECOGNIZED_BYTE_CODE);
  2839. }
  2840. int asCContext::SetException(const char *descr)
  2841. {
  2842. // Only allow this if we're executing a CALL byte code
  2843. if( !isCallingSystemFunction ) return asERROR;
  2844. SetInternalException(descr);
  2845. return 0;
  2846. }
  2847. void asCContext::SetInternalException(const char *descr)
  2848. {
  2849. if( inExceptionHandler )
  2850. {
  2851. asASSERT(false); // Shouldn't happen
  2852. return; // but if it does, at least this will not crash the application
  2853. }
  2854. status = asEXECUTION_EXCEPTION;
  2855. regs.doProcessSuspend = true;
  2856. exceptionString = descr;
  2857. exceptionFunction = currentFunction->id;
  2858. exceptionLine = currentFunction->GetLineNumber(int(regs.programPointer - currentFunction->byteCode.AddressOf()));
  2859. exceptionColumn = exceptionLine >> 20;
  2860. exceptionLine &= 0xFFFFF;
  2861. if( exceptionCallback )
  2862. CallExceptionCallback();
  2863. }
  2864. void asCContext::CleanReturnObject()
  2865. {
  2866. if( regs.objectRegister == 0 ) return;
  2867. asASSERT( regs.objectType != 0 );
  2868. if( regs.objectType )
  2869. {
  2870. // Call the destructor on the object
  2871. asSTypeBehaviour *beh = &((asCObjectType*)regs.objectType)->beh;
  2872. if( beh->release )
  2873. {
  2874. engine->CallObjectMethod(regs.objectRegister, beh->release);
  2875. regs.objectRegister = 0;
  2876. // The release method is responsible for freeing the memory
  2877. }
  2878. else
  2879. {
  2880. if( beh->destruct )
  2881. engine->CallObjectMethod(regs.objectRegister, beh->destruct);
  2882. // Free the memory
  2883. engine->CallFree(regs.objectRegister);
  2884. regs.objectRegister = 0;
  2885. }
  2886. }
  2887. }
  2888. void asCContext::CleanStack()
  2889. {
  2890. inExceptionHandler = true;
  2891. // Run the clean up code for each of the functions called
  2892. CleanStackFrame();
  2893. while( callStack.GetLength() > 0 )
  2894. {
  2895. PopCallState();
  2896. CleanStackFrame();
  2897. }
  2898. inExceptionHandler = false;
  2899. }
  2900. void asCContext::DetermineLiveObjects(asCArray<int> &liveObjects, asUINT stackLevel)
  2901. {
  2902. asASSERT( stackLevel < GetCallstackSize() );
  2903. asCScriptFunction *func;
  2904. asUINT pos;
  2905. if( stackLevel == 0 )
  2906. {
  2907. func = currentFunction;
  2908. pos = asUINT(regs.programPointer - func->byteCode.AddressOf());
  2909. }
  2910. else
  2911. {
  2912. size_t *s = callStack.AddressOf() + (GetCallstackSize()-stackLevel-1)*CALLSTACK_FRAME_SIZE;
  2913. func = (asCScriptFunction*)s[1];
  2914. pos = asUINT((asDWORD*)s[2] - func->byteCode.AddressOf());
  2915. }
  2916. // Determine which object variables that are really live ones
  2917. liveObjects.SetLength(func->objVariablePos.GetLength());
  2918. memset(liveObjects.AddressOf(), 0, sizeof(int)*liveObjects.GetLength());
  2919. for( int n = 0; n < (int)func->objVariableInfo.GetLength(); n++ )
  2920. {
  2921. if( func->objVariableInfo[n].programPos >= pos )
  2922. {
  2923. // We've determined how far the execution ran, now determine which variables are alive
  2924. for( --n; n >= 0; n-- )
  2925. {
  2926. switch( func->objVariableInfo[n].option )
  2927. {
  2928. case asOBJ_UNINIT: // Object was destroyed
  2929. {
  2930. // TODO: optimize: This should have been done by the compiler already
  2931. // Which variable is this?
  2932. asUINT var = 0;
  2933. for( asUINT v = 0; v < func->objVariablePos.GetLength(); v++ )
  2934. if( func->objVariablePos[v] == func->objVariableInfo[n].variableOffset )
  2935. {
  2936. var = v;
  2937. break;
  2938. }
  2939. liveObjects[var] -= 1;
  2940. }
  2941. break;
  2942. case asOBJ_INIT: // Object was created
  2943. {
  2944. // Which variable is this?
  2945. asUINT var = 0;
  2946. for( asUINT v = 0; v < func->objVariablePos.GetLength(); v++ )
  2947. if( func->objVariablePos[v] == func->objVariableInfo[n].variableOffset )
  2948. {
  2949. var = v;
  2950. break;
  2951. }
  2952. liveObjects[var] += 1;
  2953. }
  2954. break;
  2955. case asBLOCK_BEGIN: // Start block
  2956. // We should ignore start blocks, since it just means the
  2957. // program was within the block when the exception ocurred
  2958. break;
  2959. case asBLOCK_END: // End block
  2960. // We need to skip the entire block, as the objects created
  2961. // and destroyed inside this block are already out of scope
  2962. {
  2963. int nested = 1;
  2964. while( nested > 0 )
  2965. {
  2966. int option = func->objVariableInfo[--n].option;
  2967. if( option == 3 )
  2968. nested++;
  2969. if( option == 2 )
  2970. nested--;
  2971. }
  2972. }
  2973. break;
  2974. }
  2975. }
  2976. // We're done with the investigation
  2977. break;
  2978. }
  2979. }
  2980. }
  2981. void asCContext::CleanStackFrame()
  2982. {
  2983. // Clean object variables
  2984. if( !isStackMemoryNotAllocated )
  2985. {
  2986. // Determine which object variables that are really live ones
  2987. asCArray<int> liveObjects;
  2988. DetermineLiveObjects(liveObjects, 0);
  2989. for( asUINT n = 0; n < currentFunction->objVariablePos.GetLength(); n++ )
  2990. {
  2991. int pos = currentFunction->objVariablePos[n];
  2992. if( currentFunction->objVariableIsOnHeap[n] )
  2993. {
  2994. // Check if the pointer is initialized
  2995. if( *(size_t*)&regs.stackFramePointer[-pos] )
  2996. {
  2997. // Call the object's destructor
  2998. asSTypeBehaviour *beh = &currentFunction->objVariableTypes[n]->beh;
  2999. if( beh->release )
  3000. {
  3001. engine->CallObjectMethod((void*)*(size_t*)&regs.stackFramePointer[-pos], beh->release);
  3002. *(size_t*)&regs.stackFramePointer[-pos] = 0;
  3003. }
  3004. else
  3005. {
  3006. if( beh->destruct )
  3007. engine->CallObjectMethod((void*)*(size_t*)&regs.stackFramePointer[-pos], beh->destruct);
  3008. // Free the memory
  3009. engine->CallFree((void*)*(size_t*)&regs.stackFramePointer[-pos]);
  3010. *(size_t*)&regs.stackFramePointer[-pos] = 0;
  3011. }
  3012. }
  3013. }
  3014. else
  3015. {
  3016. asASSERT( currentFunction->objVariableTypes[n]->GetFlags() & asOBJ_VALUE );
  3017. // Only destroy the object if it is truly alive
  3018. if( liveObjects[n] > 0 )
  3019. {
  3020. asSTypeBehaviour *beh = &currentFunction->objVariableTypes[n]->beh;
  3021. if( beh->destruct )
  3022. engine->CallObjectMethod((void*)(size_t*)&regs.stackFramePointer[-pos], beh->destruct);
  3023. }
  3024. }
  3025. }
  3026. if( currentFunction->objectType )
  3027. {
  3028. // If the object is a script declared object, then we must release it
  3029. // as the compiler adds a reference at the entry of the function
  3030. asSTypeBehaviour *beh = &currentFunction->objectType->beh;
  3031. if( beh->release && *(size_t*)&regs.stackFramePointer[0] != 0 )
  3032. {
  3033. engine->CallObjectMethod((void*)*(size_t*)&regs.stackFramePointer[0], beh->release);
  3034. *(size_t*)&regs.stackFramePointer[0] = 0;
  3035. }
  3036. }
  3037. }
  3038. else
  3039. isStackMemoryNotAllocated = false;
  3040. // Functions that do not own the object and parameters shouldn't do any clean up
  3041. if( currentFunction->dontCleanUpOnException )
  3042. return;
  3043. // Clean object and parameters
  3044. int offset = 0;
  3045. if( currentFunction->objectType )
  3046. {
  3047. offset += AS_PTR_SIZE;
  3048. }
  3049. for( asUINT n = 0; n < currentFunction->parameterTypes.GetLength(); n++ )
  3050. {
  3051. if( currentFunction->parameterTypes[n].IsObject() && !currentFunction->parameterTypes[n].IsReference() )
  3052. {
  3053. if( *(size_t*)&regs.stackFramePointer[offset] )
  3054. {
  3055. // Call the object's destructor
  3056. asSTypeBehaviour *beh = currentFunction->parameterTypes[n].GetBehaviour();
  3057. if( beh->release )
  3058. {
  3059. engine->CallObjectMethod((void*)*(size_t*)&regs.stackFramePointer[offset], beh->release);
  3060. *(size_t*)&regs.stackFramePointer[offset] = 0;
  3061. }
  3062. else
  3063. {
  3064. if( beh->destruct )
  3065. engine->CallObjectMethod((void*)*(size_t*)&regs.stackFramePointer[offset], beh->destruct);
  3066. // Free the memory
  3067. engine->CallFree((void*)*(size_t*)&regs.stackFramePointer[offset]);
  3068. *(size_t*)&regs.stackFramePointer[offset] = 0;
  3069. }
  3070. }
  3071. }
  3072. offset += currentFunction->parameterTypes[n].GetSizeOnStackDWords();
  3073. }
  3074. }
  3075. // interface
  3076. int asCContext::GetExceptionLineNumber(int *column, const char **sectionName)
  3077. {
  3078. if( GetState() != asEXECUTION_EXCEPTION ) return asERROR;
  3079. if( column ) *column = exceptionColumn;
  3080. if( sectionName ) *sectionName = engine->scriptFunctions[exceptionFunction]->GetScriptSectionName();
  3081. return exceptionLine;
  3082. }
  3083. // interface
  3084. int asCContext::GetExceptionFunction()
  3085. {
  3086. if( GetState() != asEXECUTION_EXCEPTION ) return asERROR;
  3087. return exceptionFunction;
  3088. }
  3089. #ifdef AS_DEPRECATED
  3090. // deprecated since 2.20.0
  3091. // interface
  3092. int asCContext::GetCurrentFunction()
  3093. {
  3094. if( status == asEXECUTION_SUSPENDED || status == asEXECUTION_ACTIVE )
  3095. return currentFunction->id;
  3096. return -1;
  3097. }
  3098. // interface
  3099. int asCContext::GetCurrentLineNumber(int *column, const char **sectionName)
  3100. {
  3101. if( status == asEXECUTION_SUSPENDED || status == asEXECUTION_ACTIVE )
  3102. {
  3103. asDWORD line = currentFunction->GetLineNumber(int(regs.programPointer - currentFunction->byteCode.AddressOf()));
  3104. if( column ) *column = line >> 20;
  3105. if( sectionName ) *sectionName = currentFunction->GetScriptSectionName();
  3106. return line & 0xFFFFF;
  3107. }
  3108. return -1;
  3109. }
  3110. #endif
  3111. // interface
  3112. const char *asCContext::GetExceptionString()
  3113. {
  3114. if( GetState() != asEXECUTION_EXCEPTION ) return 0;
  3115. return exceptionString.AddressOf();
  3116. }
  3117. // interface
  3118. asEContextState asCContext::GetState() const
  3119. {
  3120. return status;
  3121. }
  3122. // interface
  3123. int asCContext::SetLineCallback(asSFuncPtr callback, void *obj, int callConv)
  3124. {
  3125. lineCallback = true;
  3126. regs.doProcessSuspend = true;
  3127. lineCallbackObj = obj;
  3128. bool isObj = false;
  3129. if( (unsigned)callConv == asCALL_GENERIC )
  3130. {
  3131. lineCallback = false;
  3132. regs.doProcessSuspend = doSuspend;
  3133. return asNOT_SUPPORTED;
  3134. }
  3135. if( (unsigned)callConv >= asCALL_THISCALL )
  3136. {
  3137. isObj = true;
  3138. if( obj == 0 )
  3139. {
  3140. lineCallback = false;
  3141. regs.doProcessSuspend = doSuspend;
  3142. return asINVALID_ARG;
  3143. }
  3144. }
  3145. int r = DetectCallingConvention(isObj, callback, callConv, &lineCallbackFunc);
  3146. if( r < 0 ) lineCallback = false;
  3147. regs.doProcessSuspend = doSuspend || lineCallback;
  3148. return r;
  3149. }
  3150. void asCContext::CallLineCallback()
  3151. {
  3152. if( lineCallbackFunc.callConv < ICC_THISCALL )
  3153. engine->CallGlobalFunction(this, lineCallbackObj, &lineCallbackFunc, 0);
  3154. else
  3155. engine->CallObjectMethod(lineCallbackObj, this, &lineCallbackFunc, 0);
  3156. }
  3157. // interface
  3158. int asCContext::SetExceptionCallback(asSFuncPtr callback, void *obj, int callConv)
  3159. {
  3160. exceptionCallback = true;
  3161. exceptionCallbackObj = obj;
  3162. bool isObj = false;
  3163. if( (unsigned)callConv == asCALL_GENERIC )
  3164. return asNOT_SUPPORTED;
  3165. if( (unsigned)callConv >= asCALL_THISCALL )
  3166. {
  3167. isObj = true;
  3168. if( obj == 0 )
  3169. {
  3170. exceptionCallback = false;
  3171. return asINVALID_ARG;
  3172. }
  3173. }
  3174. int r = DetectCallingConvention(isObj, callback, callConv, &exceptionCallbackFunc);
  3175. if( r < 0 ) exceptionCallback = false;
  3176. return r;
  3177. }
  3178. void asCContext::CallExceptionCallback()
  3179. {
  3180. if( exceptionCallbackFunc.callConv < ICC_THISCALL )
  3181. engine->CallGlobalFunction(this, exceptionCallbackObj, &exceptionCallbackFunc, 0);
  3182. else
  3183. engine->CallObjectMethod(exceptionCallbackObj, this, &exceptionCallbackFunc, 0);
  3184. }
  3185. // interface
  3186. void asCContext::ClearLineCallback()
  3187. {
  3188. lineCallback = false;
  3189. regs.doProcessSuspend = doSuspend;
  3190. }
  3191. // interface
  3192. void asCContext::ClearExceptionCallback()
  3193. {
  3194. exceptionCallback = false;
  3195. }
  3196. int asCContext::CallGeneric(int id, void *objectPointer)
  3197. {
  3198. asCScriptFunction *sysFunction = engine->scriptFunctions[id];
  3199. asSSystemFunctionInterface *sysFunc = sysFunction->sysFuncIntf;
  3200. void (*func)(asIScriptGeneric*) = (void (*)(asIScriptGeneric*))sysFunc->func;
  3201. int popSize = sysFunc->paramSize;
  3202. asDWORD *args = regs.stackPointer;
  3203. // Verify the object pointer if it is a class method
  3204. void *currentObject = 0;
  3205. if( sysFunc->callConv == ICC_GENERIC_METHOD )
  3206. {
  3207. if( objectPointer )
  3208. {
  3209. currentObject = objectPointer;
  3210. // Don't increase the reference of this pointer
  3211. // since it will not have been constructed yet
  3212. }
  3213. else
  3214. {
  3215. // The object pointer should be popped from the context stack
  3216. popSize += AS_PTR_SIZE;
  3217. // Check for null pointer
  3218. currentObject = (void*)*(size_t*)(args);
  3219. if( currentObject == 0 )
  3220. {
  3221. SetInternalException(TXT_NULL_POINTER_ACCESS);
  3222. return 0;
  3223. }
  3224. // Add the base offset for multiple inheritance
  3225. currentObject = (void*)(size_t(currentObject) + sysFunc->baseOffset);
  3226. // Skip object pointer
  3227. args += AS_PTR_SIZE;
  3228. }
  3229. }
  3230. asCGeneric gen(engine, sysFunction, currentObject, args);
  3231. isCallingSystemFunction = true;
  3232. func(&gen);
  3233. isCallingSystemFunction = false;
  3234. regs.valueRegister = gen.returnVal;
  3235. regs.objectRegister = gen.objectRegister;
  3236. regs.objectType = sysFunction->returnType.GetObjectType();
  3237. // Clean up function parameters
  3238. int offset = 0;
  3239. for( asUINT n = 0; n < sysFunction->parameterTypes.GetLength(); n++ )
  3240. {
  3241. if( sysFunction->parameterTypes[n].IsObject() && !sysFunction->parameterTypes[n].IsReference() )
  3242. {
  3243. void *obj = *(void**)&args[offset];
  3244. if( obj )
  3245. {
  3246. // Release the object
  3247. asSTypeBehaviour *beh = &sysFunction->parameterTypes[n].GetObjectType()->beh;
  3248. if( beh->release )
  3249. engine->CallObjectMethod(obj, beh->release);
  3250. else
  3251. {
  3252. // Call the destructor then free the memory
  3253. if( beh->destruct )
  3254. engine->CallObjectMethod(obj, beh->destruct);
  3255. engine->CallFree(obj);
  3256. }
  3257. }
  3258. }
  3259. offset += sysFunction->parameterTypes[n].GetSizeOnStackDWords();
  3260. }
  3261. // Return how much should be popped from the stack
  3262. return popSize;
  3263. }
  3264. // interface
  3265. int asCContext::GetVarCount(asUINT stackLevel)
  3266. {
  3267. asIScriptFunction *func = GetFunction(stackLevel);
  3268. if( func == 0 ) return asINVALID_ARG;
  3269. return func->GetVarCount();
  3270. }
  3271. // interface
  3272. const char *asCContext::GetVarName(int varIndex, asUINT stackLevel)
  3273. {
  3274. asIScriptFunction *func = GetFunction(stackLevel);
  3275. if( func == 0 ) return 0;
  3276. const char *name = 0;
  3277. int r = func->GetVar(varIndex, &name);
  3278. return r >= 0 ? name : 0;
  3279. }
  3280. // interface
  3281. const char *asCContext::GetVarDeclaration(int varIndex, asUINT stackLevel)
  3282. {
  3283. asIScriptFunction *func = GetFunction(stackLevel);
  3284. if( func == 0 ) return 0;
  3285. return func->GetVarDecl(varIndex);
  3286. }
  3287. // interface
  3288. int asCContext::GetVarTypeId(int varIndex, asUINT stackLevel)
  3289. {
  3290. asIScriptFunction *func = GetFunction(stackLevel);
  3291. if( func == 0 ) return asINVALID_ARG;
  3292. int typeId;
  3293. int r = func->GetVar(varIndex, 0, &typeId);
  3294. return r < 0 ? r : typeId;
  3295. }
  3296. // interface
  3297. void *asCContext::GetAddressOfVar(int varIndex, asUINT stackLevel)
  3298. {
  3299. if( stackLevel >= GetCallstackSize() ) return 0;
  3300. asCScriptFunction *func;
  3301. asDWORD *sf;
  3302. if( stackLevel == 0 )
  3303. {
  3304. func = currentFunction;
  3305. sf = regs.stackFramePointer;
  3306. }
  3307. else
  3308. {
  3309. size_t *s = callStack.AddressOf() + (GetCallstackSize()-stackLevel-1)*CALLSTACK_FRAME_SIZE;
  3310. func = (asCScriptFunction*)s[1];
  3311. sf = (asDWORD*)s[0];
  3312. }
  3313. if( func == 0 )
  3314. return 0;
  3315. if( varIndex < 0 || varIndex >= (signed)func->variables.GetLength() )
  3316. return 0;
  3317. // For object variables it's necessary to dereference the pointer to get the address of the value
  3318. if( func->variables[varIndex]->type.IsObject() && !func->variables[varIndex]->type.IsObjectHandle() )
  3319. {
  3320. // Determine if the object is really on the heap
  3321. bool onHeap = true;
  3322. if( func->variables[varIndex]->type.GetObjectType()->GetFlags() & asOBJ_VALUE )
  3323. {
  3324. int pos = func->variables[varIndex]->stackOffset;
  3325. for( asUINT n = 0; n < func->objVariablePos.GetLength(); n++ )
  3326. {
  3327. if( func->objVariablePos[n] == pos )
  3328. {
  3329. onHeap = func->objVariableIsOnHeap[n];
  3330. if( !onHeap )
  3331. {
  3332. // If the object on the stack is not initialized return a null pointer instead
  3333. asCArray<int> liveObjects;
  3334. DetermineLiveObjects(liveObjects, stackLevel);
  3335. if( liveObjects[n] <= 0 )
  3336. return 0;
  3337. }
  3338. break;
  3339. }
  3340. }
  3341. }
  3342. if( onHeap )
  3343. return *(void**)(sf - func->variables[varIndex]->stackOffset);
  3344. }
  3345. return sf - func->variables[varIndex]->stackOffset;
  3346. }
  3347. // interface
  3348. // returns the typeId of the 'this' object at the given call stack level (-1 for current)
  3349. // returns 0 if the function call at the given stack level is not a method
  3350. int asCContext::GetThisTypeId(asUINT stackLevel)
  3351. {
  3352. asIScriptFunction *func = GetFunction(stackLevel);
  3353. if( func == 0 ) return asINVALID_ARG;
  3354. if( func->GetObjectType() == 0 )
  3355. return 0; // not in a method
  3356. // create a datatype
  3357. asCDataType dt = asCDataType::CreateObject((asCObjectType*)func->GetObjectType(), false);
  3358. // return a typeId from the data type
  3359. return engine->GetTypeIdFromDataType(dt);
  3360. }
  3361. // interface
  3362. // returns the 'this' object pointer at the given call stack level (-1 for current)
  3363. // returns 0 if the function call at the given stack level is not a method
  3364. void *asCContext::GetThisPointer(asUINT stackLevel)
  3365. {
  3366. if( stackLevel >= GetCallstackSize() )
  3367. return 0;
  3368. asCScriptFunction *func;
  3369. asDWORD *sf;
  3370. if( stackLevel == 0 )
  3371. {
  3372. func = currentFunction;
  3373. sf = regs.stackFramePointer;
  3374. }
  3375. else
  3376. {
  3377. size_t *s = callStack.AddressOf() + (GetCallstackSize()-stackLevel-1)*CALLSTACK_FRAME_SIZE;
  3378. func = (asCScriptFunction*)s[1];
  3379. sf = (asDWORD*)s[0];
  3380. }
  3381. if( func == 0 )
  3382. return 0;
  3383. if( func->objectType == 0 )
  3384. return 0; // not in a method
  3385. void *thisPointer = (void*)*(size_t*)(sf);
  3386. if( thisPointer == 0 )
  3387. {
  3388. return 0;
  3389. }
  3390. // NOTE: this returns the pointer to the 'this' while the GetVarPointer functions return
  3391. // a pointer to a pointer. I can't imagine someone would want to change the 'this'
  3392. return thisPointer;
  3393. }
  3394. END_AS_NAMESPACE