as_restore.cpp 127 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209421042114212421342144215421642174218421942204221422242234224422542264227422842294230423142324233423442354236423742384239424042414242424342444245424642474248424942504251425242534254425542564257425842594260426142624263426442654266426742684269427042714272427342744275427642774278427942804281428242834284428542864287428842894290429142924293429442954296429742984299430043014302430343044305430643074308430943104311431243134314431543164317431843194320432143224323432443254326432743284329433043314332433343344335433643374338433943404341434243434344434543464347434843494350435143524353435443554356435743584359436043614362436343644365436643674368436943704371437243734374437543764377437843794380438143824383438443854386438743884389439043914392439343944395439643974398439944004401440244034404440544064407440844094410441144124413441444154416441744184419442044214422442344244425442644274428442944304431443244334434443544364437443844394440444144424443444444454446444744484449445044514452445344544455445644574458445944604461446244634464446544664467446844694470447144724473447444754476447744784479448044814482448344844485448644874488448944904491449244934494449544964497449844994500450145024503450445054506450745084509451045114512451345144515451645174518451945204521452245234524452545264527452845294530453145324533453445354536453745384539454045414542454345444545454645474548454945504551455245534554455545564557455845594560456145624563456445654566456745684569457045714572457345744575457645774578457945804581458245834584458545864587458845894590459145924593459445954596459745984599460046014602460346044605460646074608460946104611461246134614461546164617461846194620462146224623462446254626462746284629463046314632463346344635463646374638463946404641464246434644464546464647464846494650465146524653465446554656465746584659466046614662466346644665466646674668466946704671467246734674467546764677467846794680468146824683468446854686468746884689469046914692469346944695469646974698469947004701470247034704470547064707470847094710471147124713471447154716471747184719472047214722472347244725472647274728472947304731473247334734473547364737473847394740474147424743
  1. /*
  2. AngelCode Scripting Library
  3. Copyright (c) 2003-2014 Andreas Jonsson
  4. This software is provided 'as-is', without any express or implied
  5. warranty. In no event will the authors be held liable for any
  6. damages arising from the use of this software.
  7. Permission is granted to anyone to use this software for any
  8. purpose, including commercial applications, and to alter it and
  9. redistribute it freely, subject to the following restrictions:
  10. 1. The origin of this software must not be misrepresented; you
  11. must not claim that you wrote the original software. If you use
  12. this software in a product, an acknowledgment in the product
  13. documentation would be appreciated but is not required.
  14. 2. Altered source versions must be plainly marked as such, and
  15. must not be misrepresented as being the original software.
  16. 3. This notice may not be removed or altered from any source
  17. distribution.
  18. The original version of this library can be located at:
  19. http://www.angelcode.com/angelscript/
  20. Andreas Jonsson
  21. [email protected]
  22. */
  23. //
  24. // as_restore.cpp
  25. //
  26. // Functions for saving and restoring module bytecode
  27. // asCRestore was originally written by Dennis Bollyn, [email protected]
  28. #include "as_config.h"
  29. #include "as_restore.h"
  30. #include "as_bytecode.h"
  31. #include "as_scriptobject.h"
  32. #include "as_texts.h"
  33. BEGIN_AS_NAMESPACE
  34. asCReader::asCReader(asCModule* _module, asIBinaryStream* _stream, asCScriptEngine* _engine)
  35. : module(_module), stream(_stream), engine(_engine)
  36. {
  37. error = false;
  38. bytesRead = 0;
  39. }
  40. void asCReader::ReadData(void *data, asUINT size)
  41. {
  42. asASSERT(size == 1 || size == 2 || size == 4 || size == 8);
  43. #if defined(AS_BIG_ENDIAN)
  44. for( asUINT n = 0; n < size; n++ )
  45. stream->Read(((asBYTE*)data)+n, 1);
  46. #else
  47. for( int n = size-1; n >= 0; n-- )
  48. stream->Read(((asBYTE*)data)+n, 1);
  49. #endif
  50. bytesRead += size;
  51. }
  52. int asCReader::Read(bool *wasDebugInfoStripped)
  53. {
  54. // Before starting the load, make sure that
  55. // any existing resources have been freed
  56. module->InternalReset();
  57. // Call the inner method to do the actual loading
  58. int r = ReadInner();
  59. if( r < 0 )
  60. {
  61. // Something went wrong while loading the bytecode, so we need
  62. // to clean-up whatever has been created during the process.
  63. // Make sure none of the loaded functions attempt to release
  64. // references that have not yet been increased
  65. asUINT i;
  66. for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
  67. if( !dontTranslate.MoveTo(0, module->scriptFunctions[i]) )
  68. if( module->scriptFunctions[i]->scriptData )
  69. module->scriptFunctions[i]->scriptData->byteCode.SetLength(0);
  70. asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List();
  71. for( ; it; it++ )
  72. if( (*it)->GetInitFunc() )
  73. if( (*it)->GetInitFunc()->scriptData )
  74. (*it)->GetInitFunc()->scriptData->byteCode.SetLength(0);
  75. module->InternalReset();
  76. }
  77. else
  78. {
  79. // Init system functions properly
  80. engine->PrepareEngine();
  81. // Initialize the global variables (unless requested not to)
  82. if( engine->ep.initGlobalVarsAfterBuild )
  83. r = module->ResetGlobalVars(0);
  84. if( wasDebugInfoStripped )
  85. *wasDebugInfoStripped = noDebugInfo;
  86. }
  87. return r;
  88. }
  89. int asCReader::Error(const char *msg)
  90. {
  91. // Don't write if it has already been reported an error earlier
  92. if( !error )
  93. {
  94. asCString str;
  95. str.Format(msg, bytesRead);
  96. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  97. error = true;
  98. }
  99. return -1;
  100. }
  101. int asCReader::ReadInner()
  102. {
  103. // This function will load each entity one by one from the stream.
  104. // If any error occurs, it will return to the caller who is
  105. // responsible for cleaning up the partially loaded entities.
  106. engine->deferValidationOfTemplateTypes = true;
  107. unsigned long i, count;
  108. asCScriptFunction* func;
  109. ReadData(&noDebugInfo, 1);
  110. // Read enums
  111. count = ReadEncodedUInt();
  112. module->enumTypes.Allocate(count, false);
  113. for( i = 0; i < count && !error; i++ )
  114. {
  115. asCObjectType *ot = asNEW(asCObjectType)(engine);
  116. if( ot == 0 )
  117. {
  118. error = true;
  119. return asOUT_OF_MEMORY;
  120. }
  121. ReadObjectTypeDeclaration(ot, 1);
  122. // If the type is shared then we should use the original if it exists
  123. bool sharedExists = false;
  124. if( ot->IsShared() )
  125. {
  126. for( asUINT n = 0; n < engine->classTypes.GetLength(); n++ )
  127. {
  128. asCObjectType *t = engine->classTypes[n];
  129. if( t &&
  130. t->IsShared() &&
  131. t->name == ot->name &&
  132. t->nameSpace == ot->nameSpace &&
  133. (t->flags & asOBJ_ENUM) )
  134. {
  135. asDELETE(ot, asCObjectType);
  136. ot = t;
  137. sharedExists = true;
  138. break;
  139. }
  140. }
  141. }
  142. if( sharedExists )
  143. existingShared.Insert(ot, true);
  144. else
  145. engine->classTypes.PushLast(ot);
  146. module->enumTypes.PushLast(ot);
  147. ot->AddRef();
  148. ReadObjectTypeDeclaration(ot, 2);
  149. }
  150. if( error ) return asERROR;
  151. // classTypes[]
  152. // First restore the structure names, then the properties
  153. count = ReadEncodedUInt();
  154. module->classTypes.Allocate(count, false);
  155. for( i = 0; i < count && !error; ++i )
  156. {
  157. asCObjectType *ot = asNEW(asCObjectType)(engine);
  158. if( ot == 0 )
  159. {
  160. error = true;
  161. return asOUT_OF_MEMORY;
  162. }
  163. ReadObjectTypeDeclaration(ot, 1);
  164. // If the type is shared, then we should use the original if it exists
  165. bool sharedExists = false;
  166. if( ot->IsShared() )
  167. {
  168. for( asUINT n = 0; n < engine->classTypes.GetLength(); n++ )
  169. {
  170. asCObjectType *t = engine->classTypes[n];
  171. if( t &&
  172. t->IsShared() &&
  173. t->name == ot->name &&
  174. t->nameSpace == ot->nameSpace &&
  175. t->IsInterface() == ot->IsInterface() )
  176. {
  177. asDELETE(ot, asCObjectType);
  178. ot = t;
  179. sharedExists = true;
  180. break;
  181. }
  182. }
  183. }
  184. if( sharedExists )
  185. existingShared.Insert(ot, true);
  186. else
  187. {
  188. engine->classTypes.PushLast(ot);
  189. // Set this module as the owner
  190. ot->module = module;
  191. }
  192. module->classTypes.PushLast(ot);
  193. ot->AddRef();
  194. }
  195. if( error ) return asERROR;
  196. // Read func defs
  197. count = ReadEncodedUInt();
  198. module->funcDefs.Allocate(count, false);
  199. for( i = 0; i < count && !error; i++ )
  200. {
  201. bool isNew;
  202. asCScriptFunction *func = ReadFunction(isNew, false, true);
  203. if( func )
  204. {
  205. module->funcDefs.PushLast(func);
  206. engine->funcDefs.PushLast(func);
  207. // TODO: clean up: This is also done by the builder. It should probably be moved to a method in the module
  208. // Check if there is another identical funcdef from another module and if so reuse that instead
  209. for( asUINT n = 0; n < engine->funcDefs.GetLength(); n++ )
  210. {
  211. asCScriptFunction *f2 = engine->funcDefs[n];
  212. if( f2 == 0 || func == f2 )
  213. continue;
  214. if( f2->name == func->name &&
  215. f2->nameSpace == func->nameSpace &&
  216. f2->IsSignatureExceptNameEqual(func) )
  217. {
  218. // Replace our funcdef for the existing one
  219. module->funcDefs[module->funcDefs.IndexOf(func)] = f2;
  220. f2->AddRef();
  221. engine->funcDefs.RemoveValue(func);
  222. savedFunctions[savedFunctions.IndexOf(func)] = f2;
  223. func->Release();
  224. // Funcdefs aren't deleted when the ref count reaches zero so we must manually delete it here
  225. asDELETE(func,asCScriptFunction);
  226. break;
  227. }
  228. }
  229. }
  230. else
  231. Error(TXT_INVALID_BYTECODE_d);
  232. }
  233. // Read interface methods
  234. for( i = 0; i < module->classTypes.GetLength() && !error; i++ )
  235. {
  236. if( module->classTypes[i]->IsInterface() )
  237. ReadObjectTypeDeclaration(module->classTypes[i], 2);
  238. }
  239. // Read class methods and behaviours
  240. for( i = 0; i < module->classTypes.GetLength() && !error; ++i )
  241. {
  242. if( !module->classTypes[i]->IsInterface() )
  243. ReadObjectTypeDeclaration(module->classTypes[i], 2);
  244. }
  245. // Read class properties
  246. for( i = 0; i < module->classTypes.GetLength() && !error; ++i )
  247. {
  248. if( !module->classTypes[i]->IsInterface() )
  249. ReadObjectTypeDeclaration(module->classTypes[i], 3);
  250. }
  251. if( error ) return asERROR;
  252. // Read typedefs
  253. count = ReadEncodedUInt();
  254. module->typeDefs.Allocate(count, false);
  255. for( i = 0; i < count && !error; i++ )
  256. {
  257. asCObjectType *ot = asNEW(asCObjectType)(engine);
  258. if( ot == 0 )
  259. {
  260. error = true;
  261. return asOUT_OF_MEMORY;
  262. }
  263. ReadObjectTypeDeclaration(ot, 1);
  264. engine->classTypes.PushLast(ot);
  265. module->typeDefs.PushLast(ot);
  266. ot->AddRef();
  267. ReadObjectTypeDeclaration(ot, 2);
  268. }
  269. if( error ) return asERROR;
  270. // scriptGlobals[]
  271. count = ReadEncodedUInt();
  272. if( count && engine->ep.disallowGlobalVars )
  273. {
  274. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, TXT_GLOBAL_VARS_NOT_ALLOWED);
  275. Error(TXT_INVALID_BYTECODE_d);
  276. }
  277. module->scriptGlobals.Allocate(count, false);
  278. for( i = 0; i < count && !error; ++i )
  279. {
  280. ReadGlobalProperty();
  281. }
  282. // scriptFunctions[]
  283. count = ReadEncodedUInt();
  284. for( i = 0; i < count && !error; ++i )
  285. {
  286. size_t len = module->scriptFunctions.GetLength();
  287. bool isNew;
  288. func = ReadFunction(isNew);
  289. if( func == 0 )
  290. {
  291. Error(TXT_INVALID_BYTECODE_d);
  292. break;
  293. }
  294. // Is the function shared and was it created now?
  295. if( func->isShared && len != module->scriptFunctions.GetLength() )
  296. {
  297. // If the function already existed in another module, then
  298. // we need to replace it with previously existing one
  299. for( asUINT n = 0; n < engine->scriptFunctions.GetLength() && !error; n++ )
  300. {
  301. asCScriptFunction *realFunc = engine->scriptFunctions[n];
  302. if( realFunc &&
  303. realFunc != func &&
  304. realFunc->IsShared() &&
  305. realFunc->IsSignatureEqual(func) )
  306. {
  307. // Replace the recently created function with the pre-existing function
  308. module->scriptFunctions[module->scriptFunctions.GetLength()-1] = realFunc;
  309. realFunc->AddRef();
  310. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  311. engine->FreeScriptFunctionId(func->id);
  312. // Insert the function in the dontTranslate array
  313. dontTranslate.Insert(realFunc, true);
  314. // Release the function, but make sure nothing else is released
  315. func->id = 0;
  316. func->scriptData->byteCode.SetLength(0);
  317. func->Release();
  318. break;
  319. }
  320. }
  321. }
  322. }
  323. // globalFunctions[]
  324. count = ReadEncodedUInt();
  325. for( i = 0; i < count && !error; ++i )
  326. {
  327. bool isNew;
  328. func = ReadFunction(isNew, false, false);
  329. if( func )
  330. {
  331. module->globalFunctions.Put(func);
  332. func->AddRef();
  333. }
  334. else
  335. Error(TXT_INVALID_BYTECODE_d);
  336. }
  337. if( error ) return asERROR;
  338. // bindInformations[]
  339. count = ReadEncodedUInt();
  340. module->bindInformations.Allocate(count, false);
  341. for( i = 0; i < count && !error; ++i )
  342. {
  343. sBindInfo *info = asNEW(sBindInfo);
  344. if( info == 0 )
  345. {
  346. error = true;
  347. return asOUT_OF_MEMORY;
  348. }
  349. bool isNew;
  350. info->importedFunctionSignature = ReadFunction(isNew, false, false);
  351. if( info->importedFunctionSignature == 0 )
  352. {
  353. Error(TXT_INVALID_BYTECODE_d);
  354. break;
  355. }
  356. if( engine->freeImportedFunctionIdxs.GetLength() )
  357. {
  358. int id = engine->freeImportedFunctionIdxs.PopLast();
  359. info->importedFunctionSignature->id = int(FUNC_IMPORTED + id);
  360. engine->importedFunctions[id] = info;
  361. }
  362. else
  363. {
  364. info->importedFunctionSignature->id = int(FUNC_IMPORTED + engine->importedFunctions.GetLength());
  365. engine->importedFunctions.PushLast(info);
  366. }
  367. ReadString(&info->importFromModule);
  368. info->boundFunctionId = -1;
  369. module->bindInformations.PushLast(info);
  370. }
  371. if( error ) return asERROR;
  372. // usedTypes[]
  373. count = ReadEncodedUInt();
  374. usedTypes.Allocate(count, false);
  375. for( i = 0; i < count && !error; ++i )
  376. {
  377. asCObjectType *ot = ReadObjectType();
  378. usedTypes.PushLast(ot);
  379. }
  380. // usedTypeIds[]
  381. if( !error )
  382. ReadUsedTypeIds();
  383. // usedFunctions[]
  384. if( !error )
  385. ReadUsedFunctions();
  386. // usedGlobalProperties[]
  387. if( !error )
  388. ReadUsedGlobalProps();
  389. // usedStringConstants[]
  390. if( !error )
  391. ReadUsedStringConstants();
  392. // usedObjectProperties
  393. if( !error )
  394. ReadUsedObjectProps();
  395. // Validate the template types
  396. if( !error )
  397. {
  398. for( i = 0; i < usedTypes.GetLength() && !error; i++ )
  399. {
  400. if( !(usedTypes[i]->flags & asOBJ_TEMPLATE) ||
  401. !usedTypes[i]->beh.templateCallback )
  402. continue;
  403. bool dontGarbageCollect = false;
  404. asCScriptFunction *callback = engine->scriptFunctions[usedTypes[i]->beh.templateCallback];
  405. if( !engine->CallGlobalFunctionRetBool(usedTypes[i], &dontGarbageCollect, callback->sysFuncIntf, callback) )
  406. {
  407. asCString sub = usedTypes[i]->templateSubTypes[0].Format();
  408. for( asUINT n = 1; n < usedTypes[i]->templateSubTypes.GetLength(); n++ )
  409. {
  410. sub += ",";
  411. sub += usedTypes[i]->templateSubTypes[n].Format();
  412. }
  413. asCString str;
  414. str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, usedTypes[i]->name.AddressOf(), sub.AddressOf());
  415. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  416. Error(TXT_INVALID_BYTECODE_d);
  417. }
  418. }
  419. }
  420. engine->deferValidationOfTemplateTypes = false;
  421. if( error ) return asERROR;
  422. // Update the loaded bytecode to point to the correct types, property offsets,
  423. // function ids, etc. This is basically a linking stage.
  424. for( i = 0; i < module->scriptFunctions.GetLength() && !error; i++ )
  425. if( module->scriptFunctions[i]->funcType == asFUNC_SCRIPT )
  426. TranslateFunction(module->scriptFunctions[i]);
  427. asCSymbolTable<asCGlobalProperty>::iterator globIt = module->scriptGlobals.List();
  428. while( globIt && !error )
  429. {
  430. asCScriptFunction *initFunc = (*globIt)->GetInitFunc();
  431. if( initFunc )
  432. TranslateFunction(initFunc);
  433. globIt++;
  434. }
  435. if( error ) return asERROR;
  436. // Add references for all functions (except for the pre-existing shared code)
  437. for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
  438. if( !dontTranslate.MoveTo(0, module->scriptFunctions[i]) )
  439. module->scriptFunctions[i]->AddReferences();
  440. globIt = module->scriptGlobals.List();
  441. while( globIt )
  442. {
  443. asCScriptFunction *initFunc = (*globIt)->GetInitFunc();
  444. if( initFunc )
  445. initFunc->AddReferences();
  446. globIt++;
  447. }
  448. return error ? asERROR : asSUCCESS;
  449. }
  450. void asCReader::ReadUsedStringConstants()
  451. {
  452. asCString str;
  453. asUINT count;
  454. count = ReadEncodedUInt();
  455. usedStringConstants.Allocate(count, false);
  456. for( asUINT i = 0; i < count; ++i )
  457. {
  458. ReadString(&str);
  459. usedStringConstants.PushLast(engine->AddConstantString(str.AddressOf(), str.GetLength()));
  460. }
  461. }
  462. void asCReader::ReadUsedFunctions()
  463. {
  464. asUINT count;
  465. count = ReadEncodedUInt();
  466. usedFunctions.SetLength(count);
  467. memset(usedFunctions.AddressOf(), 0, sizeof(asCScriptFunction *)*count);
  468. for( asUINT n = 0; n < usedFunctions.GetLength(); n++ )
  469. {
  470. char c;
  471. // Read the data to be able to uniquely identify the function
  472. // Is the function from the module or the application?
  473. ReadData(&c, 1);
  474. if( c == 'n' )
  475. {
  476. // Null function pointer
  477. usedFunctions[n] = 0;
  478. }
  479. else
  480. {
  481. asCScriptFunction func(engine, c == 'm' ? module : 0, asFUNC_DUMMY);
  482. ReadFunctionSignature(&func);
  483. if( error )
  484. {
  485. func.funcType = asFUNC_DUMMY;
  486. return;
  487. }
  488. // Find the correct function
  489. if( c == 'm' )
  490. {
  491. for( asUINT i = 0; i < module->scriptFunctions.GetLength(); i++ )
  492. {
  493. asCScriptFunction *f = module->scriptFunctions[i];
  494. if( !func.IsSignatureEqual(f) ||
  495. func.objectType != f->objectType ||
  496. func.funcType != f->funcType ||
  497. func.nameSpace != f->nameSpace )
  498. continue;
  499. usedFunctions[n] = f;
  500. break;
  501. }
  502. }
  503. else
  504. {
  505. for( asUINT i = 0; i < engine->scriptFunctions.GetLength(); i++ )
  506. {
  507. asCScriptFunction *f = engine->scriptFunctions[i];
  508. if( f == 0 ||
  509. !func.IsSignatureEqual(f) ||
  510. func.objectType != f->objectType ||
  511. func.nameSpace != f->nameSpace )
  512. continue;
  513. usedFunctions[n] = f;
  514. break;
  515. }
  516. }
  517. // Set the type to dummy so it won't try to release the id
  518. func.funcType = asFUNC_DUMMY;
  519. if( usedFunctions[n] == 0 )
  520. {
  521. Error(TXT_INVALID_BYTECODE_d);
  522. return;
  523. }
  524. }
  525. }
  526. }
  527. void asCReader::ReadFunctionSignature(asCScriptFunction *func)
  528. {
  529. asUINT i, count;
  530. asCDataType dt;
  531. int num;
  532. ReadString(&func->name);
  533. if( func->name == DELEGATE_FACTORY )
  534. {
  535. // It's not necessary to read anymore, everything is known
  536. asCScriptFunction *f = engine->registeredGlobalFuncs.GetFirst(engine->nameSpaces[0], DELEGATE_FACTORY);
  537. asASSERT( f );
  538. func->returnType = f->returnType;
  539. func->parameterTypes = f->parameterTypes;
  540. func->inOutFlags = f->inOutFlags;
  541. func->funcType = f->funcType;
  542. func->defaultArgs = f->defaultArgs;
  543. func->nameSpace = f->nameSpace;
  544. return;
  545. }
  546. ReadDataType(&func->returnType);
  547. count = ReadEncodedUInt();
  548. if( count > 256 )
  549. {
  550. // Too many arguments, must be something wrong in the file
  551. Error(TXT_INVALID_BYTECODE_d);
  552. return;
  553. }
  554. func->parameterTypes.Allocate(count, false);
  555. for( i = 0; i < count; ++i )
  556. {
  557. ReadDataType(&dt);
  558. func->parameterTypes.PushLast(dt);
  559. }
  560. func->inOutFlags.SetLength(func->parameterTypes.GetLength());
  561. memset(func->inOutFlags.AddressOf(), 0, sizeof(asETypeModifiers)*func->inOutFlags.GetLength());
  562. count = ReadEncodedUInt();
  563. if( count > func->parameterTypes.GetLength() )
  564. {
  565. // Cannot be more than the number of arguments
  566. Error(TXT_INVALID_BYTECODE_d);
  567. return;
  568. }
  569. for( i = 0; i < count; ++i )
  570. {
  571. num = ReadEncodedUInt();
  572. func->inOutFlags[i] = static_cast<asETypeModifiers>(num);
  573. }
  574. func->funcType = (asEFuncType)ReadEncodedUInt();
  575. // Read the default args, from last to first
  576. count = ReadEncodedUInt();
  577. if( count > func->parameterTypes.GetLength() )
  578. {
  579. // Cannot be more than the number of arguments
  580. Error(TXT_INVALID_BYTECODE_d);
  581. return;
  582. }
  583. if( count )
  584. {
  585. func->defaultArgs.SetLength(func->parameterTypes.GetLength());
  586. memset(func->defaultArgs.AddressOf(), 0, sizeof(asCString*)*func->defaultArgs.GetLength());
  587. for( i = 0; i < count; i++ )
  588. {
  589. asCString *str = asNEW(asCString);
  590. if( str == 0 )
  591. {
  592. // Out of memory
  593. error = true;
  594. return;
  595. }
  596. func->defaultArgs[func->defaultArgs.GetLength()-1-i] = str;
  597. ReadString(str);
  598. }
  599. }
  600. func->objectType = ReadObjectType();
  601. if( func->objectType )
  602. {
  603. asBYTE b;
  604. ReadData(&b, 1);
  605. func->isReadOnly = (b & 1) ? true : false;
  606. func->isPrivate = (b & 2) ? true : false;
  607. func->nameSpace = engine->nameSpaces[0];
  608. }
  609. else
  610. {
  611. asCString ns;
  612. ReadString(&ns);
  613. func->nameSpace = engine->AddNameSpace(ns.AddressOf());
  614. }
  615. }
  616. asCScriptFunction *asCReader::ReadFunction(bool &isNew, bool addToModule, bool addToEngine, bool addToGC)
  617. {
  618. isNew = false;
  619. if( error ) return 0;
  620. char c;
  621. ReadData(&c, 1);
  622. if( c == '\0' )
  623. {
  624. // There is no function, so return a null pointer
  625. return 0;
  626. }
  627. if( c == 'r' )
  628. {
  629. // This is a reference to a previously saved function
  630. asUINT index = ReadEncodedUInt();
  631. if( index < savedFunctions.GetLength() )
  632. return savedFunctions[index];
  633. else
  634. {
  635. Error(TXT_INVALID_BYTECODE_d);
  636. return 0;
  637. }
  638. }
  639. // Load the new function
  640. isNew = true;
  641. asCScriptFunction *func = asNEW(asCScriptFunction)(engine,module,asFUNC_DUMMY);
  642. if( func == 0 )
  643. {
  644. // Out of memory
  645. error = true;
  646. return 0;
  647. }
  648. savedFunctions.PushLast(func);
  649. int i, count;
  650. asCDataType dt;
  651. int num;
  652. ReadFunctionSignature(func);
  653. if( error )
  654. {
  655. asDELETE(func, asCScriptFunction);
  656. return 0;
  657. }
  658. if( func->funcType == asFUNC_SCRIPT )
  659. {
  660. func->AllocateScriptFunctionData();
  661. if( addToGC && !addToModule )
  662. engine->gc.AddScriptObjectToGC(func, &engine->functionBehaviours);
  663. ReadByteCode(func);
  664. func->scriptData->variableSpace = ReadEncodedUInt();
  665. count = ReadEncodedUInt();
  666. func->scriptData->objVariablePos.Allocate(count, false);
  667. func->scriptData->objVariableTypes.Allocate(count, false);
  668. func->scriptData->funcVariableTypes.Allocate(count, false);
  669. for( i = 0; i < count; ++i )
  670. {
  671. func->scriptData->objVariableTypes.PushLast(ReadObjectType());
  672. asUINT idx = ReadEncodedUInt();
  673. func->scriptData->funcVariableTypes.PushLast((asCScriptFunction*)(asPWORD)idx);
  674. num = ReadEncodedUInt();
  675. func->scriptData->objVariablePos.PushLast(num);
  676. }
  677. if( count > 0 )
  678. func->scriptData->objVariablesOnHeap = ReadEncodedUInt();
  679. else
  680. func->scriptData->objVariablesOnHeap = 0;
  681. int length = ReadEncodedUInt();
  682. func->scriptData->objVariableInfo.SetLength(length);
  683. for( i = 0; i < length; ++i )
  684. {
  685. func->scriptData->objVariableInfo[i].programPos = ReadEncodedUInt();
  686. func->scriptData->objVariableInfo[i].variableOffset = ReadEncodedUInt();
  687. func->scriptData->objVariableInfo[i].option = ReadEncodedUInt();
  688. }
  689. if( !noDebugInfo )
  690. {
  691. length = ReadEncodedUInt();
  692. func->scriptData->lineNumbers.SetLength(length);
  693. for( i = 0; i < length; ++i )
  694. func->scriptData->lineNumbers[i] = ReadEncodedUInt();
  695. // Read the array of script sections
  696. length = ReadEncodedUInt();
  697. func->scriptData->sectionIdxs.SetLength(length);
  698. for( i = 0; i < length; ++i )
  699. {
  700. if( (i & 1) == 0 )
  701. func->scriptData->sectionIdxs[i] = ReadEncodedUInt();
  702. else
  703. {
  704. asCString str;
  705. ReadString(&str);
  706. func->scriptData->sectionIdxs[i] = engine->GetScriptSectionNameIndex(str.AddressOf());
  707. }
  708. }
  709. }
  710. ReadData(&func->isShared, 1);
  711. // Read the variable information
  712. if( !noDebugInfo )
  713. {
  714. length = ReadEncodedUInt();
  715. func->scriptData->variables.Allocate(length, false);
  716. for( i = 0; i < length; i++ )
  717. {
  718. asSScriptVariable *var = asNEW(asSScriptVariable);
  719. if( var == 0 )
  720. {
  721. // Out of memory
  722. error = true;
  723. asDELETE(func, asCScriptFunction);
  724. return 0;
  725. }
  726. func->scriptData->variables.PushLast(var);
  727. var->declaredAtProgramPos = ReadEncodedUInt();
  728. var->stackOffset = ReadEncodedUInt();
  729. ReadString(&var->name);
  730. ReadDataType(&var->type);
  731. }
  732. }
  733. ReadData(&func->dontCleanUpOnException, 1);
  734. // Read script section name
  735. if( !noDebugInfo )
  736. {
  737. asCString name;
  738. ReadString(&name);
  739. func->scriptData->scriptSectionIdx = engine->GetScriptSectionNameIndex(name.AddressOf());
  740. func->scriptData->declaredAt = ReadEncodedUInt();
  741. }
  742. }
  743. else if( func->funcType == asFUNC_VIRTUAL || func->funcType == asFUNC_INTERFACE )
  744. {
  745. func->vfTableIdx = ReadEncodedUInt();
  746. }
  747. if( addToModule )
  748. {
  749. // The refCount is already 1
  750. module->scriptFunctions.PushLast(func);
  751. }
  752. if( addToEngine )
  753. {
  754. func->id = engine->GetNextScriptFunctionId();
  755. engine->SetScriptFunction(func);
  756. }
  757. if( func->objectType )
  758. func->ComputeSignatureId();
  759. return func;
  760. }
  761. void asCReader::ReadObjectTypeDeclaration(asCObjectType *ot, int phase)
  762. {
  763. if( phase == 1 )
  764. {
  765. // Read the initial attributes
  766. ReadString(&ot->name);
  767. ReadData(&ot->flags, 4);
  768. ot->size = ReadEncodedUInt();
  769. asCString ns;
  770. ReadString(&ns);
  771. ot->nameSpace = engine->AddNameSpace(ns.AddressOf());
  772. // Reset the size of script classes, since it will be recalculated as properties are added
  773. if( (ot->flags & asOBJ_SCRIPT_OBJECT) && ot->size != 0 )
  774. ot->size = sizeof(asCScriptObject);
  775. // Use the default script class behaviours
  776. ot->beh = engine->scriptTypeBehaviours.beh;
  777. ot->beh.construct = 0;
  778. ot->beh.factory = 0;
  779. ot->beh.constructors.PopLast(); // These will be read from the file
  780. ot->beh.factories.PopLast(); // These will be read from the file
  781. engine->scriptFunctions[ot->beh.addref]->AddRef();
  782. engine->scriptFunctions[ot->beh.release]->AddRef();
  783. engine->scriptFunctions[ot->beh.gcEnumReferences]->AddRef();
  784. engine->scriptFunctions[ot->beh.gcGetFlag]->AddRef();
  785. engine->scriptFunctions[ot->beh.gcGetRefCount]->AddRef();
  786. engine->scriptFunctions[ot->beh.gcReleaseAllReferences]->AddRef();
  787. engine->scriptFunctions[ot->beh.gcSetFlag]->AddRef();
  788. engine->scriptFunctions[ot->beh.copy]->AddRef();
  789. // TODO: weak: Should not do this if the class has been declared with 'noweak'
  790. engine->scriptFunctions[ot->beh.getWeakRefFlag]->AddRef();
  791. for( asUINT i = 1; i < ot->beh.operators.GetLength(); i += 2 )
  792. engine->scriptFunctions[ot->beh.operators[i]]->AddRef();
  793. }
  794. else if( phase == 2 )
  795. {
  796. if( ot->flags & asOBJ_ENUM )
  797. {
  798. int count = ReadEncodedUInt();
  799. bool sharedExists = existingShared.MoveTo(0, ot);
  800. if( !sharedExists )
  801. {
  802. ot->enumValues.Allocate(count, false);
  803. for( int n = 0; n < count; n++ )
  804. {
  805. asSEnumValue *e = asNEW(asSEnumValue);
  806. if( e == 0 )
  807. {
  808. // Out of memory
  809. error = true;
  810. return;
  811. }
  812. ReadString(&e->name);
  813. ReadData(&e->value, 4); // TODO: Should be encoded
  814. ot->enumValues.PushLast(e);
  815. }
  816. }
  817. else
  818. {
  819. // Verify that the enum values exists in the original
  820. asCString name;
  821. int value;
  822. for( int n = 0; n < count; n++ )
  823. {
  824. ReadString(&name);
  825. ReadData(&value, 4); // TODO: Should be encoded
  826. bool found = false;
  827. for( asUINT e = 0; e < ot->enumValues.GetLength(); e++ )
  828. {
  829. if( ot->enumValues[e]->name == name &&
  830. ot->enumValues[e]->value == value )
  831. {
  832. found = true;
  833. break;
  834. }
  835. }
  836. if( !found )
  837. {
  838. asCString str;
  839. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  840. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  841. Error(TXT_INVALID_BYTECODE_d);
  842. }
  843. }
  844. }
  845. }
  846. else if( ot->flags & asOBJ_TYPEDEF )
  847. {
  848. eTokenType t = (eTokenType)ReadEncodedUInt();
  849. ot->templateSubTypes.PushLast(asCDataType::CreatePrimitive(t, false));
  850. }
  851. else
  852. {
  853. // If the type is shared and pre-existing, we should just
  854. // validate that the loaded methods match the original
  855. bool sharedExists = existingShared.MoveTo(0, ot);
  856. if( sharedExists )
  857. {
  858. asCObjectType *dt = ReadObjectType();
  859. if( ot->derivedFrom != dt )
  860. {
  861. asCString str;
  862. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  863. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  864. Error(TXT_INVALID_BYTECODE_d);
  865. }
  866. }
  867. else
  868. {
  869. ot->derivedFrom = ReadObjectType();
  870. if( ot->derivedFrom )
  871. ot->derivedFrom->AddRef();
  872. }
  873. // interfaces[] / interfaceVFTOffsets[]
  874. int size = ReadEncodedUInt();
  875. if( sharedExists )
  876. {
  877. for( int n = 0; n < size; n++ )
  878. {
  879. asCObjectType *intf = ReadObjectType();
  880. ReadEncodedUInt();
  881. if( !ot->Implements(intf) )
  882. {
  883. asCString str;
  884. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  885. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  886. Error(TXT_INVALID_BYTECODE_d);
  887. }
  888. }
  889. }
  890. else
  891. {
  892. ot->interfaces.Allocate(size, false);
  893. ot->interfaceVFTOffsets.Allocate(size, false);
  894. for( int n = 0; n < size; n++ )
  895. {
  896. asCObjectType *intf = ReadObjectType();
  897. ot->interfaces.PushLast(intf);
  898. asUINT offset = ReadEncodedUInt();
  899. ot->interfaceVFTOffsets.PushLast(offset);
  900. }
  901. }
  902. // behaviours
  903. if( !ot->IsInterface() && ot->flags != asOBJ_TYPEDEF && ot->flags != asOBJ_ENUM )
  904. {
  905. bool isNew;
  906. asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
  907. if( sharedExists )
  908. {
  909. // Find the real function in the object, and update the savedFunctions array
  910. asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.destruct);
  911. if( (realFunc == 0 && func == 0) || realFunc->IsSignatureEqual(func) )
  912. {
  913. // If the function is not the last, then the substitution has already occurred before
  914. if( func && savedFunctions[savedFunctions.GetLength()-1] == func )
  915. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  916. }
  917. else
  918. {
  919. asCString str;
  920. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  921. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  922. Error(TXT_INVALID_BYTECODE_d);
  923. }
  924. if( func )
  925. {
  926. if( isNew )
  927. {
  928. // Destroy the function without releasing any references
  929. func->id = 0;
  930. func->scriptData->byteCode.SetLength(0);
  931. func->Release();
  932. }
  933. module->scriptFunctions.PushLast(realFunc);
  934. realFunc->AddRef();
  935. dontTranslate.Insert(realFunc, true);
  936. }
  937. }
  938. else
  939. {
  940. if( func )
  941. {
  942. ot->beh.destruct = func->id;
  943. func->AddRef();
  944. }
  945. else
  946. ot->beh.destruct = 0;
  947. }
  948. size = ReadEncodedUInt();
  949. for( int n = 0; n < size; n++ )
  950. {
  951. bool isNew;
  952. asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
  953. if( func )
  954. {
  955. if( sharedExists )
  956. {
  957. // Find the real function in the object, and update the savedFunctions array
  958. bool found = false;
  959. for( asUINT n = 0; n < ot->beh.constructors.GetLength(); n++ )
  960. {
  961. asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.constructors[n]);
  962. if( realFunc->IsSignatureEqual(func) )
  963. {
  964. // If the function is not the last, then the substitution has already occurred before
  965. if( savedFunctions[savedFunctions.GetLength()-1] == func )
  966. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  967. found = true;
  968. module->scriptFunctions.PushLast(realFunc);
  969. realFunc->AddRef();
  970. dontTranslate.Insert(realFunc, true);
  971. break;
  972. }
  973. }
  974. if( !found )
  975. {
  976. asCString str;
  977. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  978. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  979. Error(TXT_INVALID_BYTECODE_d);
  980. }
  981. if( isNew )
  982. {
  983. // Destroy the function without releasing any references
  984. func->id = 0;
  985. func->scriptData->byteCode.SetLength(0);
  986. func->Release();
  987. }
  988. }
  989. else
  990. {
  991. ot->beh.constructors.PushLast(func->id);
  992. func->AddRef();
  993. if( func->parameterTypes.GetLength() == 0 )
  994. ot->beh.construct = func->id;
  995. }
  996. }
  997. else
  998. {
  999. Error(TXT_INVALID_BYTECODE_d);
  1000. }
  1001. func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
  1002. if( func )
  1003. {
  1004. if( sharedExists )
  1005. {
  1006. // Find the real function in the object, and update the savedFunctions array
  1007. bool found = false;
  1008. for( asUINT n = 0; n < ot->beh.factories.GetLength(); n++ )
  1009. {
  1010. asCScriptFunction *realFunc = engine->GetScriptFunction(ot->beh.factories[n]);
  1011. if( realFunc->IsSignatureEqual(func) )
  1012. {
  1013. // If the function is not the last, then the substitution has already occurred before
  1014. if( savedFunctions[savedFunctions.GetLength()-1] == func )
  1015. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  1016. found = true;
  1017. module->scriptFunctions.PushLast(realFunc);
  1018. realFunc->AddRef();
  1019. dontTranslate.Insert(realFunc, true);
  1020. break;
  1021. }
  1022. }
  1023. if( !found )
  1024. {
  1025. asCString str;
  1026. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  1027. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1028. Error(TXT_INVALID_BYTECODE_d);
  1029. }
  1030. if( isNew )
  1031. {
  1032. // Destroy the function without releasing any references
  1033. func->id = 0;
  1034. func->scriptData->byteCode.SetLength(0);
  1035. func->Release();
  1036. }
  1037. }
  1038. else
  1039. {
  1040. ot->beh.factories.PushLast(func->id);
  1041. func->AddRef();
  1042. if( func->parameterTypes.GetLength() == 0 )
  1043. ot->beh.factory = func->id;
  1044. }
  1045. }
  1046. else
  1047. {
  1048. Error(TXT_INVALID_BYTECODE_d);
  1049. }
  1050. }
  1051. }
  1052. // methods[]
  1053. size = ReadEncodedUInt();
  1054. int n;
  1055. for( n = 0; n < size; n++ )
  1056. {
  1057. bool isNew;
  1058. asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
  1059. if( func )
  1060. {
  1061. if( sharedExists )
  1062. {
  1063. // Find the real function in the object, and update the savedFunctions array
  1064. bool found = false;
  1065. for( asUINT n = 0; n < ot->methods.GetLength(); n++ )
  1066. {
  1067. asCScriptFunction *realFunc = engine->GetScriptFunction(ot->methods[n]);
  1068. if( realFunc->IsSignatureEqual(func) )
  1069. {
  1070. // If the function is not the last, then the substitution has already occurred before
  1071. if( savedFunctions[savedFunctions.GetLength()-1] == func )
  1072. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  1073. found = true;
  1074. module->scriptFunctions.PushLast(realFunc);
  1075. realFunc->AddRef();
  1076. dontTranslate.Insert(realFunc, true);
  1077. break;
  1078. }
  1079. }
  1080. if( !found )
  1081. {
  1082. asCString str;
  1083. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  1084. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1085. Error(TXT_INVALID_BYTECODE_d);
  1086. }
  1087. if( isNew )
  1088. {
  1089. // Destroy the function without releasing any references
  1090. func->id = 0;
  1091. if( func->scriptData )
  1092. func->scriptData->byteCode.SetLength(0);
  1093. func->Release();
  1094. }
  1095. }
  1096. else
  1097. {
  1098. // If the method is the assignment operator we need to replace the default implementation
  1099. if( func->name == "opAssign" && func->parameterTypes.GetLength() == 1 &&
  1100. func->parameterTypes[0].GetObjectType() == func->objectType &&
  1101. (func->inOutFlags[0] & asTM_INREF) )
  1102. {
  1103. engine->scriptFunctions[ot->beh.copy]->Release();
  1104. ot->beh.copy = func->id;
  1105. func->AddRef();
  1106. }
  1107. ot->methods.PushLast(func->id);
  1108. func->AddRef();
  1109. }
  1110. }
  1111. else
  1112. {
  1113. Error(TXT_INVALID_BYTECODE_d);
  1114. }
  1115. }
  1116. // virtualFunctionTable[]
  1117. size = ReadEncodedUInt();
  1118. for( n = 0; n < size; n++ )
  1119. {
  1120. bool isNew;
  1121. asCScriptFunction *func = ReadFunction(isNew, !sharedExists, !sharedExists, !sharedExists);
  1122. if( func )
  1123. {
  1124. if( sharedExists )
  1125. {
  1126. // Find the real function in the object, and update the savedFunctions array
  1127. bool found = false;
  1128. for( asUINT n = 0; n < ot->virtualFunctionTable.GetLength(); n++ )
  1129. {
  1130. asCScriptFunction *realFunc = ot->virtualFunctionTable[n];
  1131. if( realFunc->IsSignatureEqual(func) )
  1132. {
  1133. // If the function is not the last, then the substitution has already occurred before
  1134. if( savedFunctions[savedFunctions.GetLength()-1] == func )
  1135. savedFunctions[savedFunctions.GetLength()-1] = realFunc;
  1136. found = true;
  1137. module->scriptFunctions.PushLast(realFunc);
  1138. realFunc->AddRef();
  1139. dontTranslate.Insert(realFunc, true);
  1140. break;
  1141. }
  1142. }
  1143. if( !found )
  1144. {
  1145. asCString str;
  1146. str.Format(TXT_SHARED_s_DOESNT_MATCH_ORIGINAL, ot->GetName());
  1147. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1148. Error(TXT_INVALID_BYTECODE_d);
  1149. }
  1150. if( isNew )
  1151. {
  1152. // Destroy the function without releasing any references
  1153. func->id = 0;
  1154. if( func->scriptData )
  1155. func->scriptData->byteCode.SetLength(0);
  1156. func->Release();
  1157. }
  1158. }
  1159. else
  1160. {
  1161. ot->virtualFunctionTable.PushLast(func);
  1162. func->AddRef();
  1163. }
  1164. }
  1165. else
  1166. {
  1167. Error(TXT_INVALID_BYTECODE_d);
  1168. }
  1169. }
  1170. }
  1171. }
  1172. else if( phase == 3 )
  1173. {
  1174. // properties[]
  1175. asUINT size = ReadEncodedUInt();
  1176. for( asUINT n = 0; n < size; n++ )
  1177. ReadObjectProperty(ot);
  1178. }
  1179. }
  1180. asWORD asCReader::ReadEncodedUInt16()
  1181. {
  1182. asDWORD dw = ReadEncodedUInt();
  1183. if( (dw>>16) != 0 && (dw>>16) != 0xFFFF )
  1184. {
  1185. Error(TXT_INVALID_BYTECODE_d);
  1186. }
  1187. return asWORD(dw & 0xFFFF);
  1188. }
  1189. asUINT asCReader::ReadEncodedUInt()
  1190. {
  1191. asQWORD qw = ReadEncodedUInt64();
  1192. if( (qw>>32) != 0 && (qw>>32) != 0xFFFFFFFF )
  1193. {
  1194. Error(TXT_INVALID_BYTECODE_d);
  1195. }
  1196. return asUINT(qw & 0xFFFFFFFFu);
  1197. }
  1198. asQWORD asCReader::ReadEncodedUInt64()
  1199. {
  1200. asQWORD i = 0;
  1201. asBYTE b;
  1202. ReadData(&b, 1);
  1203. bool isNegative = ( b & 0x80 ) ? true : false;
  1204. b &= 0x7F;
  1205. if( (b & 0x7F) == 0x7F )
  1206. {
  1207. ReadData(&b, 1); i = asQWORD(b) << 56;
  1208. ReadData(&b, 1); i += asQWORD(b) << 48;
  1209. ReadData(&b, 1); i += asQWORD(b) << 40;
  1210. ReadData(&b, 1); i += asQWORD(b) << 32;
  1211. ReadData(&b, 1); i += asUINT(b) << 24;
  1212. ReadData(&b, 1); i += asUINT(b) << 16;
  1213. ReadData(&b, 1); i += asUINT(b) << 8;
  1214. ReadData(&b, 1); i += b;
  1215. }
  1216. else if( (b & 0x7E) == 0x7E )
  1217. {
  1218. i = asQWORD(b & 0x01) << 48;
  1219. ReadData(&b, 1); i += asQWORD(b) << 40;
  1220. ReadData(&b, 1); i += asQWORD(b) << 32;
  1221. ReadData(&b, 1); i += asUINT(b) << 24;
  1222. ReadData(&b, 1); i += asUINT(b) << 16;
  1223. ReadData(&b, 1); i += asUINT(b) << 8;
  1224. ReadData(&b, 1); i += b;
  1225. }
  1226. else if( (b & 0x7C) == 0x7C )
  1227. {
  1228. i = asQWORD(b & 0x03) << 40;
  1229. ReadData(&b, 1); i += asQWORD(b) << 32;
  1230. ReadData(&b, 1); i += asUINT(b) << 24;
  1231. ReadData(&b, 1); i += asUINT(b) << 16;
  1232. ReadData(&b, 1); i += asUINT(b) << 8;
  1233. ReadData(&b, 1); i += b;
  1234. }
  1235. else if( (b & 0x78) == 0x78 )
  1236. {
  1237. i = asQWORD(b & 0x07) << 32;
  1238. ReadData(&b, 1); i += asUINT(b) << 24;
  1239. ReadData(&b, 1); i += asUINT(b) << 16;
  1240. ReadData(&b, 1); i += asUINT(b) << 8;
  1241. ReadData(&b, 1); i += b;
  1242. }
  1243. else if( (b & 0x70) == 0x70 )
  1244. {
  1245. i = asUINT(b & 0x0F) << 24;
  1246. ReadData(&b, 1); i += asUINT(b) << 16;
  1247. ReadData(&b, 1); i += asUINT(b) << 8;
  1248. ReadData(&b, 1); i += b;
  1249. }
  1250. else if( (b & 0x60) == 0x60 )
  1251. {
  1252. i = asUINT(b & 0x1F) << 16;
  1253. ReadData(&b, 1); i += asUINT(b) << 8;
  1254. ReadData(&b, 1); i += b;
  1255. }
  1256. else if( (b & 0x40) == 0x40 )
  1257. {
  1258. i = asUINT(b & 0x3F) << 8;
  1259. ReadData(&b, 1); i += b;
  1260. }
  1261. else
  1262. {
  1263. i = b;
  1264. }
  1265. if( isNegative )
  1266. i = (asQWORD)(-asINT64(i));
  1267. return i;
  1268. }
  1269. void asCReader::ReadString(asCString* str)
  1270. {
  1271. char b;
  1272. ReadData(&b, 1);
  1273. if( b == '\0' )
  1274. {
  1275. str->SetLength(0);
  1276. }
  1277. else if( b == 'n' )
  1278. {
  1279. asUINT len = ReadEncodedUInt();
  1280. str->SetLength(len);
  1281. stream->Read(str->AddressOf(), len);
  1282. savedStrings.PushLast(*str);
  1283. }
  1284. else
  1285. {
  1286. asUINT n = ReadEncodedUInt();
  1287. if( n < savedStrings.GetLength() )
  1288. *str = savedStrings[n];
  1289. else
  1290. Error(TXT_INVALID_BYTECODE_d);
  1291. }
  1292. }
  1293. void asCReader::ReadGlobalProperty()
  1294. {
  1295. asCString name;
  1296. asCDataType type;
  1297. ReadString(&name);
  1298. asCString ns;
  1299. ReadString(&ns);
  1300. asSNameSpace *nameSpace = engine->AddNameSpace(ns.AddressOf());
  1301. ReadDataType(&type);
  1302. asCGlobalProperty *prop = module->AllocateGlobalProperty(name.AddressOf(), type, nameSpace);
  1303. // Read the initialization function
  1304. bool f;
  1305. ReadData(&f, 1);
  1306. if( f )
  1307. {
  1308. bool isNew;
  1309. // Do not add the function to the GC at this time. It will
  1310. // only be added to the GC when the module releases the property
  1311. asCScriptFunction *func = ReadFunction(isNew, false, true, false);
  1312. if( func )
  1313. {
  1314. prop->SetInitFunc(func);
  1315. func->Release();
  1316. }
  1317. else
  1318. Error(TXT_INVALID_BYTECODE_d);
  1319. }
  1320. }
  1321. void asCReader::ReadObjectProperty(asCObjectType *ot)
  1322. {
  1323. asCString name;
  1324. ReadString(&name);
  1325. asCDataType dt;
  1326. ReadDataType(&dt);
  1327. bool isPrivate;
  1328. ReadData(&isPrivate, 1);
  1329. // TODO: shared: If the type is shared and pre-existing, we should just
  1330. // validate that the loaded methods match the original
  1331. if( !existingShared.MoveTo(0, ot) )
  1332. ot->AddPropertyToClass(name, dt, isPrivate);
  1333. }
  1334. void asCReader::ReadDataType(asCDataType *dt)
  1335. {
  1336. eTokenType tokenType;
  1337. tokenType = (eTokenType)ReadEncodedUInt();
  1338. if( tokenType == 0 )
  1339. {
  1340. // Get the datatype from the cache
  1341. asUINT n = ReadEncodedUInt();
  1342. *dt = savedDataTypes[n];
  1343. return;
  1344. }
  1345. // Reserve a spot in the savedDataTypes
  1346. size_t saveSlot = savedDataTypes.GetLength();
  1347. savedDataTypes.PushLast(asCDataType());
  1348. // Read the datatype for the first time
  1349. asCObjectType *objType = 0;
  1350. bool isObjectHandle = false;
  1351. bool isReadOnly = false;
  1352. bool isHandleToConst = false;
  1353. bool isReference = false;
  1354. if( tokenType == ttIdentifier )
  1355. {
  1356. objType = ReadObjectType();
  1357. ReadData(&isObjectHandle, 1);
  1358. ReadData(&isHandleToConst, 1);
  1359. }
  1360. ReadData(&isReference, 1);
  1361. ReadData(&isReadOnly, 1);
  1362. asCScriptFunction *funcDef = 0;
  1363. if( tokenType == ttIdentifier && objType && objType->name == "_builtin_function_" )
  1364. {
  1365. asCScriptFunction func(engine, module, asFUNC_DUMMY);
  1366. ReadFunctionSignature(&func);
  1367. if( error ) return;
  1368. for( asUINT n = 0; n < engine->registeredFuncDefs.GetLength(); n++ )
  1369. {
  1370. // TODO: access: Only return the definitions that the module has access to
  1371. if( engine->registeredFuncDefs[n]->name == func.name &&
  1372. engine->registeredFuncDefs[n]->nameSpace == func.nameSpace )
  1373. {
  1374. funcDef = engine->registeredFuncDefs[n];
  1375. break;
  1376. }
  1377. }
  1378. if( !funcDef && module )
  1379. {
  1380. for( asUINT n = 0; n < module->funcDefs.GetLength(); n++ )
  1381. {
  1382. if( module->funcDefs[n]->name == func.name &&
  1383. module->funcDefs[n]->nameSpace == func.nameSpace )
  1384. {
  1385. funcDef = module->funcDefs[n];
  1386. break;
  1387. }
  1388. }
  1389. }
  1390. // Set to dummy to avoid unwanted release of resources
  1391. func.funcType = asFUNC_DUMMY;
  1392. }
  1393. if( funcDef )
  1394. *dt = asCDataType::CreateFuncDef(funcDef);
  1395. else if( tokenType == ttIdentifier )
  1396. *dt = asCDataType::CreateObject(objType, false);
  1397. else
  1398. *dt = asCDataType::CreatePrimitive(tokenType, false);
  1399. if( isObjectHandle )
  1400. {
  1401. dt->MakeReadOnly(isHandleToConst);
  1402. // Here we must allow a scoped type to be a handle
  1403. // e.g. if the datatype is for a system function
  1404. dt->MakeHandle(true, true);
  1405. }
  1406. dt->MakeReadOnly(isReadOnly);
  1407. dt->MakeReference(isReference);
  1408. // Update the previously saved slot
  1409. savedDataTypes[saveSlot] = *dt;
  1410. }
  1411. asCObjectType* asCReader::ReadObjectType()
  1412. {
  1413. asCObjectType *ot = 0;
  1414. char ch;
  1415. ReadData(&ch, 1);
  1416. if( ch == 'a' )
  1417. {
  1418. // Read the name of the template type
  1419. asCString typeName;
  1420. ReadString(&typeName);
  1421. asCObjectType *tmpl = engine->GetRegisteredObjectType(typeName.AddressOf(), engine->nameSpaces[0]);
  1422. if( tmpl == 0 )
  1423. {
  1424. asCString str;
  1425. str.Format(TXT_TEMPLATE_TYPE_s_DOESNT_EXIST, typeName.AddressOf());
  1426. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1427. Error(TXT_INVALID_BYTECODE_d);
  1428. return 0;
  1429. }
  1430. asUINT numSubTypes = ReadEncodedUInt();
  1431. asCArray<asCDataType> subTypes;
  1432. for( asUINT n = 0; n < numSubTypes; n++ )
  1433. {
  1434. ReadData(&ch, 1);
  1435. if( ch == 's' )
  1436. {
  1437. asCDataType dt;
  1438. ReadDataType(&dt);
  1439. subTypes.PushLast(dt);
  1440. }
  1441. else
  1442. {
  1443. eTokenType tokenType = (eTokenType)ReadEncodedUInt();
  1444. asCDataType dt = asCDataType::CreatePrimitive(tokenType, false);
  1445. subTypes.PushLast(dt);
  1446. }
  1447. }
  1448. // Return the actual template if the subtypes are the template's dummy types
  1449. if( tmpl->templateSubTypes == subTypes )
  1450. ot = tmpl;
  1451. else
  1452. {
  1453. // Get the template instance type based on the loaded subtypes
  1454. ot = engine->GetTemplateInstanceType(tmpl, subTypes);
  1455. }
  1456. if( ot == 0 )
  1457. {
  1458. // Show all subtypes in error message
  1459. asCString sub = subTypes[0].Format();
  1460. for( asUINT n = 1; n < subTypes.GetLength(); n++ )
  1461. {
  1462. sub += ",";
  1463. sub += subTypes[n].Format();
  1464. }
  1465. asCString str;
  1466. str.Format(TXT_INSTANCING_INVLD_TMPL_TYPE_s_s, typeName.AddressOf(), sub.AddressOf());
  1467. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1468. Error(TXT_INVALID_BYTECODE_d);
  1469. return 0;
  1470. }
  1471. }
  1472. else if( ch == 'l' )
  1473. {
  1474. asCObjectType *st = ReadObjectType();
  1475. if( st == 0 || st->beh.listFactory == 0 )
  1476. {
  1477. Error(TXT_INVALID_BYTECODE_d);
  1478. return 0;
  1479. }
  1480. ot = engine->GetListPatternType(st->beh.listFactory);
  1481. }
  1482. else if( ch == 's' )
  1483. {
  1484. // Read the name of the template subtype
  1485. asCString typeName;
  1486. ReadString(&typeName);
  1487. // Find the template subtype
  1488. ot = 0;
  1489. for( asUINT n = 0; n < engine->templateSubTypes.GetLength(); n++ )
  1490. {
  1491. if( engine->templateSubTypes[n] && engine->templateSubTypes[n]->name == typeName )
  1492. {
  1493. ot = engine->templateSubTypes[n];
  1494. break;
  1495. }
  1496. }
  1497. if( ot == 0 )
  1498. {
  1499. asCString str;
  1500. str.Format(TXT_TEMPLATE_SUBTYPE_s_DOESNT_EXIST, typeName.AddressOf());
  1501. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1502. Error(TXT_INVALID_BYTECODE_d);
  1503. return 0;
  1504. }
  1505. }
  1506. else if( ch == 'o' )
  1507. {
  1508. // Read the object type name
  1509. asCString typeName, ns;
  1510. ReadString(&typeName);
  1511. ReadString(&ns);
  1512. asSNameSpace *nameSpace = engine->AddNameSpace(ns.AddressOf());
  1513. if( typeName.GetLength() && typeName != "_builtin_object_" && typeName != "_builtin_function_" )
  1514. {
  1515. // Find the object type
  1516. ot = module->GetObjectType(typeName.AddressOf(), nameSpace);
  1517. if( !ot )
  1518. ot = engine->GetRegisteredObjectType(typeName.AddressOf(), nameSpace);
  1519. if( ot == 0 )
  1520. {
  1521. asCString str;
  1522. str.Format(TXT_OBJECT_TYPE_s_DOESNT_EXIST, typeName.AddressOf());
  1523. engine->WriteMessage("", 0, 0, asMSGTYPE_ERROR, str.AddressOf());
  1524. Error(TXT_INVALID_BYTECODE_d);
  1525. return 0;
  1526. }
  1527. }
  1528. else if( typeName == "_builtin_object_" )
  1529. {
  1530. ot = &engine->scriptTypeBehaviours;
  1531. }
  1532. else if( typeName == "_builtin_function_" )
  1533. {
  1534. ot = &engine->functionBehaviours;
  1535. }
  1536. else
  1537. asASSERT( false );
  1538. }
  1539. else
  1540. {
  1541. // No object type
  1542. asASSERT( ch == '\0' );
  1543. ot = 0;
  1544. }
  1545. return ot;
  1546. }
  1547. void asCReader::ReadByteCode(asCScriptFunction *func)
  1548. {
  1549. asASSERT( func->scriptData );
  1550. // Read number of instructions
  1551. asUINT total, numInstructions;
  1552. total = numInstructions = ReadEncodedUInt();
  1553. // Reserve some space for the instructions
  1554. func->scriptData->byteCode.AllocateNoConstruct(numInstructions, false);
  1555. asUINT pos = 0;
  1556. while( numInstructions )
  1557. {
  1558. asBYTE b;
  1559. ReadData(&b, 1);
  1560. // Allocate the space for the instruction
  1561. asUINT len = asBCTypeSize[asBCInfo[b].type];
  1562. asUINT newSize = asUINT(func->scriptData->byteCode.GetLength()) + len;
  1563. if( func->scriptData->byteCode.GetCapacity() < newSize )
  1564. {
  1565. // Determine the average size of the loaded instructions and re-estimate the final size
  1566. asUINT size = asUINT(float(newSize) / (total - numInstructions) * total) + 1;
  1567. func->scriptData->byteCode.AllocateNoConstruct(size, true);
  1568. }
  1569. if( !func->scriptData->byteCode.SetLengthNoConstruct(newSize) )
  1570. {
  1571. // Out of memory
  1572. error = true;
  1573. return;
  1574. }
  1575. asDWORD *bc = func->scriptData->byteCode.AddressOf() + pos;
  1576. pos += len;
  1577. switch( asBCInfo[b].type )
  1578. {
  1579. case asBCTYPE_NO_ARG:
  1580. {
  1581. *(asBYTE*)(bc) = b;
  1582. bc++;
  1583. }
  1584. break;
  1585. case asBCTYPE_W_ARG:
  1586. case asBCTYPE_wW_ARG:
  1587. case asBCTYPE_rW_ARG:
  1588. {
  1589. *(asBYTE*)(bc) = b;
  1590. // Read the argument
  1591. asWORD w = ReadEncodedUInt16();
  1592. *(((asWORD*)bc)+1) = w;
  1593. bc++;
  1594. }
  1595. break;
  1596. case asBCTYPE_rW_DW_ARG:
  1597. case asBCTYPE_wW_DW_ARG:
  1598. case asBCTYPE_W_DW_ARG:
  1599. {
  1600. *(asBYTE*)(bc) = b;
  1601. // Read the word argument
  1602. asWORD w = ReadEncodedUInt16();
  1603. *(((asWORD*)bc)+1) = w;
  1604. bc++;
  1605. // Read the dword argument
  1606. *bc++ = ReadEncodedUInt();
  1607. }
  1608. break;
  1609. case asBCTYPE_DW_ARG:
  1610. {
  1611. *(asBYTE*)(bc) = b;
  1612. bc++;
  1613. // Read the argument
  1614. *bc++ = ReadEncodedUInt();
  1615. }
  1616. break;
  1617. case asBCTYPE_DW_DW_ARG:
  1618. {
  1619. *(asBYTE*)(bc) = b;
  1620. bc++;
  1621. // Read the first argument
  1622. *bc++ = ReadEncodedUInt();
  1623. // Read the second argument
  1624. *bc++ = ReadEncodedUInt();
  1625. }
  1626. break;
  1627. case asBCTYPE_wW_rW_rW_ARG:
  1628. {
  1629. *(asBYTE*)(bc) = b;
  1630. // Read the first argument
  1631. asWORD w = ReadEncodedUInt16();
  1632. *(((asWORD*)bc)+1) = w;
  1633. bc++;
  1634. // Read the second argument
  1635. w = ReadEncodedUInt16();
  1636. *(asWORD*)bc = w;
  1637. // Read the third argument
  1638. w = ReadEncodedUInt16();
  1639. *(((asWORD*)bc)+1) = w;
  1640. bc++;
  1641. }
  1642. break;
  1643. case asBCTYPE_wW_rW_ARG:
  1644. case asBCTYPE_rW_rW_ARG:
  1645. case asBCTYPE_wW_W_ARG:
  1646. {
  1647. *(asBYTE*)(bc) = b;
  1648. // Read the first argument
  1649. asWORD w = ReadEncodedUInt16();
  1650. *(((asWORD*)bc)+1) = w;
  1651. bc++;
  1652. // Read the second argument
  1653. w = ReadEncodedUInt16();
  1654. *(asWORD*)bc = w;
  1655. bc++;
  1656. }
  1657. break;
  1658. case asBCTYPE_wW_rW_DW_ARG:
  1659. case asBCTYPE_rW_W_DW_ARG:
  1660. {
  1661. *(asBYTE*)(bc) = b;
  1662. // Read the first argument
  1663. asWORD w = ReadEncodedUInt16();
  1664. *(((asWORD*)bc)+1) = w;
  1665. bc++;
  1666. // Read the second argument
  1667. w = ReadEncodedUInt16();
  1668. *(asWORD*)bc = w;
  1669. bc++;
  1670. // Read the third argument
  1671. asDWORD dw = ReadEncodedUInt();
  1672. *bc++ = dw;
  1673. }
  1674. break;
  1675. case asBCTYPE_QW_ARG:
  1676. {
  1677. *(asBYTE*)(bc) = b;
  1678. bc++;
  1679. // Read the argument
  1680. asQWORD qw = ReadEncodedUInt64();
  1681. *(asQWORD*)bc = qw;
  1682. bc += 2;
  1683. }
  1684. break;
  1685. case asBCTYPE_QW_DW_ARG:
  1686. {
  1687. *(asBYTE*)(bc) = b;
  1688. bc++;
  1689. // Read the first argument
  1690. asQWORD qw = ReadEncodedUInt64();
  1691. *(asQWORD*)bc = qw;
  1692. bc += 2;
  1693. // Read the second argument
  1694. asDWORD dw = ReadEncodedUInt();
  1695. *bc++ = dw;
  1696. }
  1697. break;
  1698. case asBCTYPE_rW_QW_ARG:
  1699. case asBCTYPE_wW_QW_ARG:
  1700. {
  1701. *(asBYTE*)(bc) = b;
  1702. // Read the first argument
  1703. asWORD w = ReadEncodedUInt16();
  1704. *(((asWORD*)bc)+1) = w;
  1705. bc++;
  1706. // Read the argument
  1707. asQWORD qw = ReadEncodedUInt64();
  1708. *(asQWORD*)bc = qw;
  1709. bc += 2;
  1710. }
  1711. break;
  1712. case asBCTYPE_rW_DW_DW_ARG:
  1713. {
  1714. *(asBYTE*)(bc) = b;
  1715. // Read the 1st argument
  1716. asWORD w = ReadEncodedUInt16();
  1717. *(((asWORD*)bc)+1) = w;
  1718. bc++;
  1719. // Read the 2nd argument
  1720. *bc++ = ReadEncodedUInt();
  1721. // Read the 3rd argument
  1722. *bc++ = ReadEncodedUInt();
  1723. }
  1724. break;
  1725. default:
  1726. {
  1727. // This should never happen
  1728. asASSERT(false);
  1729. // Read the next 3 bytes
  1730. asDWORD c; asBYTE t;
  1731. #if defined(AS_BIG_ENDIAN)
  1732. c = b << 24;
  1733. ReadData(&t, 1); c += t << 16;
  1734. ReadData(&t, 1); c += t << 8;
  1735. ReadData(&t, 1); c += t;
  1736. #else
  1737. c = b;
  1738. ReadData(&t, 1); c += t << 8;
  1739. ReadData(&t, 1); c += t << 16;
  1740. ReadData(&t, 1); c += t << 24;
  1741. #endif
  1742. *bc++ = c;
  1743. c = *(asBYTE*)&c;
  1744. // Read the bc as is
  1745. for( int n = 1; n < asBCTypeSize[asBCInfo[c].type]; n++ )
  1746. ReadData(&*bc++, 4);
  1747. }
  1748. }
  1749. numInstructions--;
  1750. }
  1751. // Correct the final size in case we over-estimated it
  1752. func->scriptData->byteCode.SetLengthNoConstruct(pos);
  1753. }
  1754. void asCReader::ReadUsedTypeIds()
  1755. {
  1756. asUINT count = ReadEncodedUInt();
  1757. usedTypeIds.Allocate(count, false);
  1758. for( asUINT n = 0; n < count; n++ )
  1759. {
  1760. asCDataType dt;
  1761. ReadDataType(&dt);
  1762. usedTypeIds.PushLast(engine->GetTypeIdFromDataType(dt));
  1763. }
  1764. }
  1765. void asCReader::ReadUsedGlobalProps()
  1766. {
  1767. int c = ReadEncodedUInt();
  1768. usedGlobalProperties.Allocate(c, false);
  1769. for( int n = 0; n < c; n++ )
  1770. {
  1771. asCString name, ns;
  1772. asCDataType type;
  1773. char moduleProp;
  1774. ReadString(&name);
  1775. ReadString(&ns);
  1776. ReadDataType(&type);
  1777. ReadData(&moduleProp, 1);
  1778. asSNameSpace *nameSpace = engine->AddNameSpace(ns.AddressOf());
  1779. // Find the real property
  1780. asCGlobalProperty *globProp = 0;
  1781. if( moduleProp )
  1782. globProp = module->scriptGlobals.GetFirst(nameSpace, name);
  1783. else
  1784. globProp = engine->registeredGlobalProps.GetFirst(nameSpace, name);
  1785. void *prop = 0;
  1786. if( globProp && globProp->type == type )
  1787. prop = globProp->GetAddressOfValue();
  1788. usedGlobalProperties.PushLast(prop);
  1789. if( prop == 0 )
  1790. {
  1791. Error(TXT_INVALID_BYTECODE_d);
  1792. }
  1793. }
  1794. }
  1795. void asCReader::ReadUsedObjectProps()
  1796. {
  1797. asUINT c = ReadEncodedUInt();
  1798. usedObjectProperties.SetLength(c);
  1799. for( asUINT n = 0; n < c; n++ )
  1800. {
  1801. asCObjectType *objType = ReadObjectType();
  1802. if( objType == 0 )
  1803. {
  1804. Error(TXT_INVALID_BYTECODE_d);
  1805. break;
  1806. }
  1807. asCString name;
  1808. ReadString(&name);
  1809. // Find the property offset
  1810. bool found = false;
  1811. for( asUINT p = 0; p < objType->properties.GetLength(); p++ )
  1812. {
  1813. if( objType->properties[p]->name == name )
  1814. {
  1815. usedObjectProperties[n].objType = objType;
  1816. usedObjectProperties[n].offset = objType->properties[p]->byteOffset;
  1817. found = true;
  1818. break;
  1819. }
  1820. }
  1821. if( !found )
  1822. {
  1823. Error(TXT_INVALID_BYTECODE_d);
  1824. return;
  1825. }
  1826. }
  1827. }
  1828. short asCReader::FindObjectPropOffset(asWORD index)
  1829. {
  1830. if( index >= usedObjectProperties.GetLength() )
  1831. {
  1832. Error(TXT_INVALID_BYTECODE_d);
  1833. return 0;
  1834. }
  1835. return (short)usedObjectProperties[index].offset;
  1836. }
  1837. asCScriptFunction *asCReader::FindFunction(int idx)
  1838. {
  1839. if( idx >= 0 && idx < (int)usedFunctions.GetLength() )
  1840. return usedFunctions[idx];
  1841. else
  1842. {
  1843. Error(TXT_INVALID_BYTECODE_d);
  1844. return 0;
  1845. }
  1846. }
  1847. void asCReader::TranslateFunction(asCScriptFunction *func)
  1848. {
  1849. // Skip this if the function is part of an pre-existing shared object
  1850. if( dontTranslate.MoveTo(0, func) ) return;
  1851. asASSERT( func->scriptData );
  1852. // Pre-compute the size of each instruction in order to translate jump offsets
  1853. asUINT n;
  1854. asDWORD *bc = func->scriptData->byteCode.AddressOf();
  1855. asCArray<asUINT> bcSizes(func->scriptData->byteCode.GetLength());
  1856. asCArray<asUINT> instructionNbrToPos(func->scriptData->byteCode.GetLength());
  1857. for( n = 0; n < func->scriptData->byteCode.GetLength(); )
  1858. {
  1859. int c = *(asBYTE*)&bc[n];
  1860. asUINT size = asBCTypeSize[asBCInfo[c].type];
  1861. if( size == 0 )
  1862. {
  1863. Error(TXT_INVALID_BYTECODE_d);
  1864. return;
  1865. }
  1866. bcSizes.PushLast(size);
  1867. instructionNbrToPos.PushLast(n);
  1868. n += size;
  1869. }
  1870. asUINT bcNum = 0;
  1871. for( n = 0; n < func->scriptData->byteCode.GetLength(); bcNum++ )
  1872. {
  1873. int c = *(asBYTE*)&bc[n];
  1874. if( c == asBC_REFCPY ||
  1875. c == asBC_RefCpyV ||
  1876. c == asBC_OBJTYPE )
  1877. {
  1878. // Translate the index to the true object type
  1879. asPWORD *ot = (asPWORD*)&bc[n+1];
  1880. *(asCObjectType**)ot = FindObjectType(*(int*)ot);
  1881. }
  1882. else if( c == asBC_TYPEID ||
  1883. c == asBC_Cast )
  1884. {
  1885. // Translate the index to the type id
  1886. int *tid = (int*)&bc[n+1];
  1887. *tid = FindTypeId(*tid);
  1888. }
  1889. else if( c == asBC_ADDSi ||
  1890. c == asBC_LoadThisR )
  1891. {
  1892. // Translate the index to the type id
  1893. int *tid = (int*)&bc[n+1];
  1894. *tid = FindTypeId(*tid);
  1895. // Translate the prop index into the property offset
  1896. *(((short*)&bc[n])+1) = FindObjectPropOffset(*(((short*)&bc[n])+1));
  1897. }
  1898. else if( c == asBC_LoadRObjR ||
  1899. c == asBC_LoadVObjR )
  1900. {
  1901. // Translate the index to the type id
  1902. int *tid = (int*)&bc[n+2];
  1903. *tid = FindTypeId(*tid);
  1904. asCObjectType *ot = engine->GetObjectTypeFromTypeId(*tid);
  1905. if( ot && (ot->flags & asOBJ_LIST_PATTERN) )
  1906. {
  1907. // List patterns have a different way of adjusting the offsets
  1908. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  1909. *(((short*)&bc[n])+2) = (short)listAdj->AdjustOffset(*(((short*)&bc[n])+2), ot);
  1910. }
  1911. else
  1912. {
  1913. // Translate the prop index into the property offset
  1914. *(((short*)&bc[n])+2) = FindObjectPropOffset(*(((short*)&bc[n])+2));
  1915. }
  1916. }
  1917. else if( c == asBC_COPY )
  1918. {
  1919. // Translate the index to the type id
  1920. int *tid = (int*)&bc[n+1];
  1921. *tid = FindTypeId(*tid);
  1922. // COPY is used to copy POD types that don't have the opAssign method. It is
  1923. // also used to copy references to scoped types during variable initializations.
  1924. // Update the number of dwords to copy as it may be different on the target platform
  1925. if( (*tid) & asTYPEID_OBJHANDLE )
  1926. {
  1927. // It is the actual reference that is being copied, not the object itself
  1928. asBC_SWORDARG0(&bc[n]) = AS_PTR_SIZE;
  1929. }
  1930. else
  1931. {
  1932. asCDataType dt = engine->GetDataTypeFromTypeId(*tid);
  1933. if( !dt.IsValid() )
  1934. {
  1935. Error(TXT_INVALID_BYTECODE_d);
  1936. }
  1937. else
  1938. asBC_SWORDARG0(&bc[n]) = (short)dt.GetSizeInMemoryDWords();
  1939. }
  1940. }
  1941. else if( c == asBC_RET )
  1942. {
  1943. // Determine the correct amount of DWORDs to pop
  1944. asWORD dw = (asWORD)func->GetSpaceNeededForArguments();
  1945. if( func->DoesReturnOnStack() ) dw += AS_PTR_SIZE;
  1946. if( func->objectType ) dw += AS_PTR_SIZE;
  1947. asBC_WORDARG0(&bc[n]) = dw;
  1948. }
  1949. else if( c == asBC_CALL ||
  1950. c == asBC_CALLINTF ||
  1951. c == asBC_CALLSYS )
  1952. {
  1953. // Translate the index to the func id
  1954. int *fid = (int*)&bc[n+1];
  1955. asCScriptFunction *f = FindFunction(*fid);
  1956. if( f )
  1957. *fid = f->id;
  1958. else
  1959. {
  1960. Error(TXT_INVALID_BYTECODE_d);
  1961. return;
  1962. }
  1963. }
  1964. else if( c == asBC_FuncPtr )
  1965. {
  1966. // Translate the index to the func pointer
  1967. asPWORD *fid = (asPWORD*)&bc[n+1];
  1968. *fid = (asPWORD)FindFunction((int)*fid);
  1969. }
  1970. else if( c == asBC_ALLOC )
  1971. {
  1972. // Translate the index to the true object type
  1973. asPWORD *arg = (asPWORD*)&bc[n+1];
  1974. *(asCObjectType**)arg = FindObjectType(*(int*)arg);
  1975. // The constructor function id must be translated, unless it is zero
  1976. int *fid = (int*)&bc[n+1+AS_PTR_SIZE];
  1977. if( *fid != 0 )
  1978. {
  1979. // Subtract 1 from the id, as it was incremented during the writing
  1980. asCScriptFunction *f = FindFunction(*fid-1);
  1981. if( f )
  1982. *fid = f->id;
  1983. else
  1984. {
  1985. Error(TXT_INVALID_BYTECODE_d);
  1986. return;
  1987. }
  1988. }
  1989. }
  1990. else if( c == asBC_STR )
  1991. {
  1992. // Translate the index to the true string id
  1993. asWORD *arg = ((asWORD*)&bc[n])+1;
  1994. if( *arg < usedStringConstants.GetLength() )
  1995. *arg = (asWORD)usedStringConstants[*arg];
  1996. else
  1997. {
  1998. Error(TXT_INVALID_BYTECODE_d);
  1999. return;
  2000. }
  2001. }
  2002. else if( c == asBC_CALLBND )
  2003. {
  2004. // Translate the function id
  2005. asUINT *fid = (asUINT*)&bc[n+1];
  2006. if( *fid < module->bindInformations.GetLength() )
  2007. {
  2008. sBindInfo *bi = module->bindInformations[*fid];
  2009. if( bi )
  2010. *fid = bi->importedFunctionSignature->id;
  2011. else
  2012. {
  2013. Error(TXT_INVALID_BYTECODE_d);
  2014. return;
  2015. }
  2016. }
  2017. else
  2018. {
  2019. Error(TXT_INVALID_BYTECODE_d);
  2020. return;
  2021. }
  2022. }
  2023. else if( c == asBC_PGA ||
  2024. c == asBC_PshGPtr ||
  2025. c == asBC_LDG ||
  2026. c == asBC_PshG4 ||
  2027. c == asBC_LdGRdR4 ||
  2028. c == asBC_CpyGtoV4 ||
  2029. c == asBC_CpyVtoG4 ||
  2030. c == asBC_SetG4 )
  2031. {
  2032. // Translate the global var index to pointer
  2033. asPWORD *index = (asPWORD*)&bc[n+1];
  2034. if( *(asUINT*)index < usedGlobalProperties.GetLength() )
  2035. *(void**)index = usedGlobalProperties[*(asUINT*)index];
  2036. else
  2037. {
  2038. Error(TXT_INVALID_BYTECODE_d);
  2039. return;
  2040. }
  2041. }
  2042. else if( c == asBC_JMP ||
  2043. c == asBC_JZ ||
  2044. c == asBC_JNZ ||
  2045. c == asBC_JLowZ ||
  2046. c == asBC_JLowNZ ||
  2047. c == asBC_JS ||
  2048. c == asBC_JNS ||
  2049. c == asBC_JP ||
  2050. c == asBC_JNP ) // The JMPP instruction doesn't need modification
  2051. {
  2052. // Get the offset
  2053. int offset = int(bc[n+1]);
  2054. // Count the instruction sizes to the destination instruction
  2055. int size = 0;
  2056. if( offset >= 0 )
  2057. // If moving ahead, then start from next instruction
  2058. for( asUINT num = bcNum+1; offset-- > 0; num++ )
  2059. size += bcSizes[num];
  2060. else
  2061. // If moving backwards, then start at current instruction
  2062. for( asUINT num = bcNum; offset++ < 0; num-- )
  2063. size -= bcSizes[num];
  2064. // The size is dword offset
  2065. bc[n+1] = size;
  2066. }
  2067. else if( c == asBC_AllocMem )
  2068. {
  2069. // The size of the allocated memory is only known after all the elements has been seen.
  2070. // This helper class will collect this information and adjust the size when the
  2071. // corresponding asBC_FREE is encountered
  2072. // The adjuster also needs to know the list type so it can know the type of the elements
  2073. asCObjectType *ot = func->GetObjectTypeOfLocalVar(asBC_SWORDARG0(&bc[n]));
  2074. listAdjusters.PushLast(asNEW(SListAdjuster)(&bc[n], ot));
  2075. }
  2076. else if( c == asBC_FREE )
  2077. {
  2078. // Translate the index to the true object type
  2079. asPWORD *pot = (asPWORD*)&bc[n+1];
  2080. *(asCObjectType**)pot = FindObjectType(*(int*)pot);
  2081. asCObjectType *ot = *(asCObjectType**)pot;
  2082. if( ot && (ot->flags & asOBJ_LIST_PATTERN) )
  2083. {
  2084. // Finalize the adjustment of the list buffer that was initiated with asBC_AllocMem
  2085. SListAdjuster *list = listAdjusters.PopLast();
  2086. list->AdjustAllocMem();
  2087. asDELETE(list, SListAdjuster);
  2088. }
  2089. }
  2090. else if( c == asBC_SetListSize )
  2091. {
  2092. // Adjust the offset in the list where the size is informed
  2093. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  2094. bc[n+1] = listAdj->AdjustOffset(bc[n+1], listAdj->patternType);
  2095. // Inform the list adjuster how many values will be repeated
  2096. listAdj->SetRepeatCount(bc[n+2]);
  2097. }
  2098. else if( c == asBC_PshListElmnt )
  2099. {
  2100. // Adjust the offset in the list where the size is informed
  2101. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  2102. bc[n+1] = listAdj->AdjustOffset(bc[n+1], listAdj->patternType);
  2103. }
  2104. else if( c == asBC_SetListType )
  2105. {
  2106. // Adjust the offset in the list where the typeid is informed
  2107. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  2108. bc[n+1] = listAdj->AdjustOffset(bc[n+1], listAdj->patternType);
  2109. // Translate the type id
  2110. bc[n+2] = FindTypeId(bc[n+2]);
  2111. // Inform the list adjuster the type id of the next element
  2112. listAdj->SetNextType(bc[n+2]);
  2113. }
  2114. n += asBCTypeSize[asBCInfo[c].type];
  2115. }
  2116. // Calculate the stack adjustments
  2117. CalculateAdjustmentByPos(func);
  2118. // Adjust all variable positions in the bytecode
  2119. bc = func->scriptData->byteCode.AddressOf();
  2120. for( n = 0; n < func->scriptData->byteCode.GetLength(); )
  2121. {
  2122. int c = *(asBYTE*)&bc[n];
  2123. switch( asBCInfo[c].type )
  2124. {
  2125. case asBCTYPE_wW_ARG:
  2126. case asBCTYPE_rW_DW_ARG:
  2127. case asBCTYPE_wW_QW_ARG:
  2128. case asBCTYPE_rW_ARG:
  2129. case asBCTYPE_wW_DW_ARG:
  2130. case asBCTYPE_wW_W_ARG:
  2131. case asBCTYPE_rW_QW_ARG:
  2132. case asBCTYPE_rW_W_DW_ARG:
  2133. case asBCTYPE_rW_DW_DW_ARG:
  2134. {
  2135. asBC_SWORDARG0(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG0(&bc[n]));
  2136. }
  2137. break;
  2138. case asBCTYPE_wW_rW_ARG:
  2139. case asBCTYPE_wW_rW_DW_ARG:
  2140. case asBCTYPE_rW_rW_ARG:
  2141. {
  2142. asBC_SWORDARG0(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG0(&bc[n]));
  2143. asBC_SWORDARG1(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG1(&bc[n]));
  2144. }
  2145. break;
  2146. case asBCTYPE_wW_rW_rW_ARG:
  2147. {
  2148. asBC_SWORDARG0(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG0(&bc[n]));
  2149. asBC_SWORDARG1(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG1(&bc[n]));
  2150. asBC_SWORDARG2(&bc[n]) = (short)AdjustStackPosition(asBC_SWORDARG2(&bc[n]));
  2151. }
  2152. break;
  2153. default:
  2154. // The other types don't treat variables so won't be modified
  2155. break;
  2156. }
  2157. n += asBCTypeSize[asBCInfo[c].type];
  2158. }
  2159. // Adjust the space needed for local variables
  2160. func->scriptData->variableSpace = AdjustStackPosition(func->scriptData->variableSpace);
  2161. // Adjust the variable information. This will be used during the adjustment below
  2162. for( n = 0; n < func->scriptData->variables.GetLength(); n++ )
  2163. {
  2164. func->scriptData->variables[n]->declaredAtProgramPos = instructionNbrToPos[func->scriptData->variables[n]->declaredAtProgramPos];
  2165. func->scriptData->variables[n]->stackOffset = AdjustStackPosition(func->scriptData->variables[n]->stackOffset);
  2166. }
  2167. // objVariablePos
  2168. for( n = 0; n < func->scriptData->objVariablePos.GetLength(); n++ )
  2169. {
  2170. func->scriptData->objVariablePos[n] = AdjustStackPosition(func->scriptData->objVariablePos[n]);
  2171. func->scriptData->funcVariableTypes[n] = FindFunction((int)(asPWORD)func->scriptData->funcVariableTypes[n]);
  2172. }
  2173. // Adjust the get offsets. This must be done in the second iteration because
  2174. // it relies on the function ids and variable position already being correct in the
  2175. // bytecodes that come after the GET instructions.
  2176. // TODO: optimize: Instead of doing a full extra loop. We can push the GET instructions
  2177. // on a stack, and then when a call instruction is found update all of them.
  2178. // This will also make the AdjustGetOffset() function quicker as it can
  2179. // receive the called function directly instead of having to search for it.
  2180. bc = func->scriptData->byteCode.AddressOf();
  2181. for( n = 0; n < func->scriptData->byteCode.GetLength(); )
  2182. {
  2183. int c = *(asBYTE*)&bc[n];
  2184. if( c == asBC_GETREF ||
  2185. c == asBC_GETOBJ ||
  2186. c == asBC_GETOBJREF )
  2187. {
  2188. asBC_WORDARG0(&bc[n]) = (asWORD)AdjustGetOffset(asBC_WORDARG0(&bc[n]), func, n);
  2189. }
  2190. n += asBCTypeSize[asBCInfo[c].type];
  2191. }
  2192. for( n = 0; n < func->scriptData->objVariableInfo.GetLength(); n++ )
  2193. {
  2194. // The program position must be adjusted as it is stored in number of instructions
  2195. func->scriptData->objVariableInfo[n].programPos = instructionNbrToPos[func->scriptData->objVariableInfo[n].programPos];
  2196. func->scriptData->objVariableInfo[n].variableOffset = AdjustStackPosition(func->scriptData->objVariableInfo[n].variableOffset);
  2197. }
  2198. // The program position (every even number) needs to be adjusted
  2199. // for the line numbers to be in number of dwords instead of number of instructions
  2200. for( n = 0; n < func->scriptData->lineNumbers.GetLength(); n += 2 )
  2201. func->scriptData->lineNumbers[n] = instructionNbrToPos[func->scriptData->lineNumbers[n]];
  2202. for( n = 0; n < func->scriptData->sectionIdxs.GetLength(); n += 2 )
  2203. func->scriptData->sectionIdxs[n] = instructionNbrToPos[func->scriptData->sectionIdxs[n]];
  2204. CalculateStackNeeded(func);
  2205. }
  2206. asCReader::SListAdjuster::SListAdjuster(asDWORD *bc, asCObjectType *listType) :
  2207. allocMemBC(bc), maxOffset(0), patternType(listType), repeatCount(0), lastOffset(-1), nextTypeId(-1)
  2208. {
  2209. asASSERT( patternType && (patternType->flags & asOBJ_LIST_PATTERN) );
  2210. // Find the first expected value in the list
  2211. asSListPatternNode *node = patternType->engine->scriptFunctions[patternType->templateSubTypes[0].GetBehaviour()->listFactory]->listPattern;
  2212. asASSERT( node && node->type == asLPT_START );
  2213. patternNode = node->next;
  2214. }
  2215. int asCReader::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatternType)
  2216. {
  2217. // TODO: cleanup: The listPatternType parameter is not needed
  2218. asASSERT( listPatternType == patternType );
  2219. UNUSED_VAR( listPatternType );
  2220. asASSERT( offset >= lastOffset );
  2221. // If it is the same offset being accessed again, just return the same adjusted value
  2222. if( lastOffset == offset )
  2223. return lastAdjustedOffset;
  2224. lastOffset = offset;
  2225. lastAdjustedOffset = maxOffset;
  2226. // What is being expected at this position?
  2227. if( patternNode->type == asLPT_REPEAT )
  2228. {
  2229. // Align the offset to 4 bytes boundary
  2230. if( maxOffset & 0x3 )
  2231. {
  2232. maxOffset += 4 - (maxOffset & 0x3);
  2233. lastAdjustedOffset = maxOffset;
  2234. }
  2235. // Don't move the patternNode yet because the caller must make a call to SetRepeatCount too
  2236. maxOffset += 4;
  2237. return lastAdjustedOffset;
  2238. }
  2239. else if( patternNode->type == asLPT_TYPE )
  2240. {
  2241. const asCDataType &dt = reinterpret_cast<asSListPatternDataTypeNode*>(patternNode)->dataType;
  2242. if( dt.GetTokenType() == ttQuestion )
  2243. {
  2244. if( nextTypeId != -1 )
  2245. {
  2246. if( repeatCount > 0 )
  2247. repeatCount--;
  2248. asCDataType dt = patternType->engine->GetDataTypeFromTypeId(nextTypeId);
  2249. asUINT size;
  2250. if( dt.IsObjectHandle() )
  2251. size = AS_PTR_SIZE*4;
  2252. else
  2253. size = dt.GetSizeInMemoryBytes();
  2254. // Align the offset to 4 bytes boundary
  2255. if( size >= 4 && (maxOffset & 0x3) )
  2256. {
  2257. maxOffset += 4 - (maxOffset & 0x3);
  2258. lastAdjustedOffset = maxOffset;
  2259. }
  2260. // Only move the patternNode if we're not expecting any more repeated entries
  2261. if( repeatCount == 0 )
  2262. patternNode = patternNode->next;
  2263. nextTypeId = -1;
  2264. maxOffset += size;
  2265. return lastAdjustedOffset;
  2266. }
  2267. else
  2268. {
  2269. // Align the offset to 4 bytes boundary
  2270. if( maxOffset & 0x3 )
  2271. {
  2272. maxOffset += 4 - (maxOffset & 0x3);
  2273. lastAdjustedOffset = maxOffset;
  2274. }
  2275. // The first adjustment is for the typeId
  2276. maxOffset += 4;
  2277. return lastAdjustedOffset;
  2278. }
  2279. }
  2280. else
  2281. {
  2282. if( repeatCount > 0 )
  2283. repeatCount--;
  2284. // Determine the size of the element
  2285. asUINT size;
  2286. asCDataType dt = reinterpret_cast<asSListPatternDataTypeNode*>(patternNode)->dataType;
  2287. if( dt.IsObjectHandle() )
  2288. size = AS_PTR_SIZE*4;
  2289. else
  2290. size = dt.GetSizeInMemoryBytes();
  2291. // Align the offset to 4 bytes boundary
  2292. if( size >= 4 && (maxOffset & 0x3) )
  2293. {
  2294. maxOffset += 4 - (maxOffset & 0x3);
  2295. lastAdjustedOffset = maxOffset;
  2296. }
  2297. maxOffset += size;
  2298. // Only move the patternNode if we're not expecting any more repeated entries
  2299. if( repeatCount == 0 )
  2300. patternNode = patternNode->next;
  2301. return lastAdjustedOffset;
  2302. }
  2303. }
  2304. else if( patternNode->type == asLPT_START )
  2305. {
  2306. if( repeatCount > 0 )
  2307. repeatCount--;
  2308. SInfo info = {repeatCount, patternNode};
  2309. stack.PushLast(info);
  2310. repeatCount = 0;
  2311. patternNode = patternNode->next;
  2312. lastOffset--;
  2313. return AdjustOffset(offset, listPatternType);
  2314. }
  2315. else if( patternNode->type == asLPT_END )
  2316. {
  2317. SInfo info = stack.PopLast();
  2318. repeatCount = info.repeatCount;
  2319. if( repeatCount )
  2320. patternNode = info.startNode;
  2321. else
  2322. patternNode = patternNode->next;
  2323. lastOffset--;
  2324. return AdjustOffset(offset, listPatternType);
  2325. }
  2326. else
  2327. {
  2328. // Something is wrong with the pattern list declaration
  2329. asASSERT( false );
  2330. }
  2331. return 0;
  2332. }
  2333. void asCReader::SListAdjuster::SetRepeatCount(asUINT rc)
  2334. {
  2335. // Make sure the list is expecting a repeat at this location
  2336. asASSERT( patternNode->type == asLPT_REPEAT );
  2337. // Now move to the next patternNode
  2338. patternNode = patternNode->next;
  2339. repeatCount = rc;
  2340. }
  2341. void asCReader::SListAdjuster::AdjustAllocMem()
  2342. {
  2343. allocMemBC[1] = maxOffset;
  2344. }
  2345. void asCReader::SListAdjuster::SetNextType(int typeId)
  2346. {
  2347. asASSERT( nextTypeId == -1 );
  2348. nextTypeId = typeId;
  2349. }
  2350. void asCReader::CalculateStackNeeded(asCScriptFunction *func)
  2351. {
  2352. asASSERT( func->scriptData );
  2353. int largestStackUsed = 0;
  2354. // Clear the known stack size for each bytecode
  2355. asCArray<int> stackSize;
  2356. stackSize.SetLength(func->scriptData->byteCode.GetLength());
  2357. memset(&stackSize[0], -1, stackSize.GetLength()*4);
  2358. // Add the first instruction to the list of unchecked code
  2359. // paths and set the stack size at that instruction to variableSpace
  2360. asCArray<asUINT> paths;
  2361. paths.PushLast(0);
  2362. stackSize[0] = func->scriptData->variableSpace;
  2363. // Go through each of the code paths
  2364. for( asUINT p = 0; p < paths.GetLength(); ++p )
  2365. {
  2366. asUINT pos = paths[p];
  2367. int currStackSize = stackSize[pos];
  2368. asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[pos];
  2369. if( bc == asBC_RET )
  2370. continue;
  2371. // Determine the change in stack size for this instruction
  2372. int stackInc = asBCInfo[bc].stackInc;
  2373. if( stackInc == 0xFFFF )
  2374. {
  2375. // Determine the true delta from the instruction arguments
  2376. if( bc == asBC_CALL ||
  2377. bc == asBC_CALLSYS ||
  2378. bc == asBC_CALLBND ||
  2379. bc == asBC_ALLOC ||
  2380. bc == asBC_CALLINTF ||
  2381. bc == asBC_CallPtr )
  2382. {
  2383. asCScriptFunction *called = GetCalledFunction(func, pos);
  2384. if( called )
  2385. {
  2386. stackInc = -called->GetSpaceNeededForArguments();
  2387. if( called->objectType )
  2388. stackInc -= AS_PTR_SIZE;
  2389. if( called->DoesReturnOnStack() )
  2390. stackInc -= AS_PTR_SIZE;
  2391. }
  2392. else
  2393. {
  2394. // It is an allocation for an object without a constructor
  2395. asASSERT( bc == asBC_ALLOC );
  2396. stackInc = -AS_PTR_SIZE;
  2397. }
  2398. }
  2399. }
  2400. currStackSize += stackInc;
  2401. asASSERT( currStackSize >= 0 );
  2402. if( currStackSize > largestStackUsed )
  2403. largestStackUsed = currStackSize;
  2404. if( bc == asBC_JMP )
  2405. {
  2406. // Find the label that we should jump to
  2407. int offset = asBC_INTARG(&func->scriptData->byteCode[pos]);
  2408. pos += 2 + offset;
  2409. // Add the destination as a new path
  2410. if( stackSize[pos] == -1 )
  2411. {
  2412. stackSize[pos] = currStackSize;
  2413. paths.PushLast(pos);
  2414. }
  2415. else
  2416. asASSERT(stackSize[pos] == currStackSize);
  2417. continue;
  2418. }
  2419. else if( bc == asBC_JZ || bc == asBC_JNZ ||
  2420. bc == asBC_JLowZ || bc == asBC_JLowNZ ||
  2421. bc == asBC_JS || bc == asBC_JNS ||
  2422. bc == asBC_JP || bc == asBC_JNP )
  2423. {
  2424. // Find the label that is being jumped to
  2425. int offset = asBC_INTARG(&func->scriptData->byteCode[pos]);
  2426. // Add both paths to the code paths
  2427. pos += 2;
  2428. if( stackSize[pos] == -1 )
  2429. {
  2430. stackSize[pos] = currStackSize;
  2431. paths.PushLast(pos);
  2432. }
  2433. else
  2434. asASSERT(stackSize[pos] == currStackSize);
  2435. pos += offset;
  2436. if( stackSize[pos] == -1 )
  2437. {
  2438. stackSize[pos] = currStackSize;
  2439. paths.PushLast(pos);
  2440. }
  2441. else
  2442. asASSERT(stackSize[pos] == currStackSize);
  2443. continue;
  2444. }
  2445. else if( bc == asBC_JMPP )
  2446. {
  2447. pos++;
  2448. // Add all subsequent JMP instructions to the path
  2449. while( *(asBYTE*)&func->scriptData->byteCode[pos] == asBC_JMP )
  2450. {
  2451. if( stackSize[pos] == -1 )
  2452. {
  2453. stackSize[pos] = currStackSize;
  2454. paths.PushLast(pos);
  2455. }
  2456. else
  2457. asASSERT(stackSize[pos] == currStackSize);
  2458. pos += 2;
  2459. }
  2460. continue;
  2461. }
  2462. else
  2463. {
  2464. // Add next instruction to the paths
  2465. pos += asBCTypeSize[asBCInfo[bc].type];
  2466. if( stackSize[pos] == -1 )
  2467. {
  2468. stackSize[pos] = currStackSize;
  2469. paths.PushLast(pos);
  2470. }
  2471. else
  2472. asASSERT(stackSize[pos] == currStackSize);
  2473. continue;
  2474. }
  2475. }
  2476. func->scriptData->stackNeeded = largestStackUsed;
  2477. }
  2478. void asCReader::CalculateAdjustmentByPos(asCScriptFunction *func)
  2479. {
  2480. // Adjust the offset of all negative variables (parameters) as
  2481. // all pointers have been stored as having a size of 1 dword
  2482. asUINT n;
  2483. asCArray<int> adjustments;
  2484. asUINT offset = 0;
  2485. if( func->objectType )
  2486. {
  2487. adjustments.PushLast(offset);
  2488. adjustments.PushLast(1-AS_PTR_SIZE);
  2489. offset += 1;
  2490. }
  2491. if( func->DoesReturnOnStack() )
  2492. {
  2493. adjustments.PushLast(offset);
  2494. adjustments.PushLast(1-AS_PTR_SIZE);
  2495. offset += 1;
  2496. }
  2497. for( n = 0; n < func->parameterTypes.GetLength(); n++ )
  2498. {
  2499. if( !func->parameterTypes[n].IsPrimitive() ||
  2500. func->parameterTypes[n].IsReference() )
  2501. {
  2502. adjustments.PushLast(offset);
  2503. adjustments.PushLast(1-AS_PTR_SIZE);
  2504. offset += 1;
  2505. }
  2506. else
  2507. {
  2508. asASSERT( func->parameterTypes[n].IsPrimitive() );
  2509. offset += func->parameterTypes[n].GetSizeOnStackDWords();
  2510. }
  2511. }
  2512. // Build look-up table with the adjustments for each stack position
  2513. adjustNegativeStackByPos.SetLength(offset);
  2514. memset(adjustNegativeStackByPos.AddressOf(), 0, adjustNegativeStackByPos.GetLength()*sizeof(int));
  2515. for( n = 0; n < adjustments.GetLength(); n+=2 )
  2516. {
  2517. int pos = adjustments[n];
  2518. int adjust = adjustments[n+1];
  2519. for( asUINT i = pos+1; i < adjustNegativeStackByPos.GetLength(); i++ )
  2520. adjustNegativeStackByPos[i] += adjust;
  2521. }
  2522. // The bytecode has been stored as if all object variables take up only 1 dword.
  2523. // It is necessary to adjust to the size according to the current platform.
  2524. adjustments.SetLength(0);
  2525. int highestPos = 0;
  2526. for( n = 0; n < func->scriptData->objVariableTypes.GetLength(); n++ )
  2527. {
  2528. if( func->scriptData->objVariableTypes[n] )
  2529. {
  2530. // Determine the size the variable currently occupies on the stack
  2531. int size = AS_PTR_SIZE;
  2532. if( (func->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE) &&
  2533. n >= func->scriptData->objVariablesOnHeap )
  2534. {
  2535. size = func->scriptData->objVariableTypes[n]->GetSize();
  2536. if( size < 4 )
  2537. size = 1;
  2538. else
  2539. size /= 4;
  2540. }
  2541. // Check if type has a different size than stored
  2542. if( size > 1 )
  2543. {
  2544. if( func->scriptData->objVariablePos[n] > highestPos )
  2545. highestPos = func->scriptData->objVariablePos[n];
  2546. adjustments.PushLast(func->scriptData->objVariablePos[n]);
  2547. adjustments.PushLast(size-1);
  2548. }
  2549. }
  2550. }
  2551. // Count position 0 too
  2552. adjustByPos.SetLength(highestPos+1);
  2553. memset(adjustByPos.AddressOf(), 0, adjustByPos.GetLength()*sizeof(int));
  2554. // Build look-up table with the adjustments for each stack position
  2555. for( n = 0; n < adjustments.GetLength(); n+=2 )
  2556. {
  2557. int pos = adjustments[n];
  2558. int adjust = adjustments[n+1];
  2559. for( asUINT i = pos; i < adjustByPos.GetLength(); i++ )
  2560. adjustByPos[i] += adjust;
  2561. }
  2562. }
  2563. int asCReader::AdjustStackPosition(int pos)
  2564. {
  2565. if( pos >= (int)adjustByPos.GetLength() )
  2566. {
  2567. // It can be higher for primitives allocated on top of highest object variable
  2568. if( adjustByPos.GetLength() )
  2569. pos += (short)adjustByPos[adjustByPos.GetLength()-1];
  2570. }
  2571. else if( pos >= 0 )
  2572. pos += (short)adjustByPos[pos];
  2573. else if( -pos >= (int)adjustNegativeStackByPos.GetLength() )
  2574. Error(TXT_INVALID_BYTECODE_d);
  2575. else
  2576. pos += (short)adjustNegativeStackByPos[-pos];
  2577. return pos;
  2578. }
  2579. asCScriptFunction *asCReader::GetCalledFunction(asCScriptFunction *func, asDWORD programPos)
  2580. {
  2581. asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[programPos];
  2582. if( bc == asBC_CALL ||
  2583. bc == asBC_CALLSYS ||
  2584. bc == asBC_CALLINTF )
  2585. {
  2586. // Find the function from the function id in bytecode
  2587. int funcId = asBC_INTARG(&func->scriptData->byteCode[programPos]);
  2588. return engine->scriptFunctions[funcId];
  2589. }
  2590. else if( bc == asBC_ALLOC )
  2591. {
  2592. // Find the function from the function id in the bytecode
  2593. int funcId = asBC_INTARG(&func->scriptData->byteCode[programPos+AS_PTR_SIZE]);
  2594. return engine->scriptFunctions[funcId];
  2595. }
  2596. else if( bc == asBC_CALLBND )
  2597. {
  2598. // Find the function from the engine's bind array
  2599. int funcId = asBC_INTARG(&func->scriptData->byteCode[programPos]);
  2600. return engine->importedFunctions[funcId & ~FUNC_IMPORTED]->importedFunctionSignature;
  2601. }
  2602. else if( bc == asBC_CallPtr )
  2603. {
  2604. asUINT v;
  2605. int var = asBC_SWORDARG0(&func->scriptData->byteCode[programPos]);
  2606. // Find the funcdef from the local variable
  2607. for( v = 0; v < func->scriptData->objVariablePos.GetLength(); v++ )
  2608. if( func->scriptData->objVariablePos[v] == var )
  2609. return func->scriptData->funcVariableTypes[v];
  2610. // Look in parameters
  2611. int paramPos = 0;
  2612. if( func->objectType )
  2613. paramPos -= AS_PTR_SIZE;
  2614. if( func->DoesReturnOnStack() )
  2615. paramPos -= AS_PTR_SIZE;
  2616. for( v = 0; v < func->parameterTypes.GetLength(); v++ )
  2617. {
  2618. if( var == paramPos )
  2619. return func->parameterTypes[v].GetFuncDef();
  2620. paramPos -= func->parameterTypes[v].GetSizeOnStackDWords();
  2621. }
  2622. }
  2623. return 0;
  2624. }
  2625. int asCReader::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD programPos)
  2626. {
  2627. // TODO: optimize: multiple instructions for the same function doesn't need to look for the function everytime
  2628. // the function can remember where it found the function and check if the programPos is still valid
  2629. // Get offset 0 doesn't need adjustment
  2630. if( offset == 0 ) return 0;
  2631. // Find out which function that will be called
  2632. asCScriptFunction *calledFunc = 0;
  2633. for( asUINT n = programPos; func->scriptData->byteCode.GetLength(); )
  2634. {
  2635. asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[n];
  2636. if( bc == asBC_CALL ||
  2637. bc == asBC_CALLSYS ||
  2638. bc == asBC_CALLINTF ||
  2639. bc == asBC_ALLOC ||
  2640. bc == asBC_CALLBND ||
  2641. bc == asBC_CallPtr )
  2642. {
  2643. calledFunc = GetCalledFunction(func, n);
  2644. break;
  2645. }
  2646. else if( bc == asBC_REFCPY ||
  2647. bc == asBC_COPY )
  2648. {
  2649. // In this case we know there is only 1 pointer on the stack above
  2650. asASSERT( offset == 1 );
  2651. return offset - (1 - AS_PTR_SIZE);
  2652. }
  2653. n += asBCTypeSize[asBCInfo[bc].type];
  2654. }
  2655. if( calledFunc == 0 )
  2656. {
  2657. Error(TXT_INVALID_BYTECODE_d);
  2658. return offset;
  2659. }
  2660. // Count the number of pointers pushed on the stack above the
  2661. // current offset, and then adjust the offset accordingly
  2662. asUINT numPtrs = 0;
  2663. int currOffset = 0;
  2664. if( offset > currOffset && calledFunc->GetObjectType() )
  2665. {
  2666. numPtrs++;
  2667. currOffset++;
  2668. }
  2669. if( offset > currOffset && calledFunc->DoesReturnOnStack() )
  2670. {
  2671. numPtrs++;
  2672. currOffset++;
  2673. }
  2674. for( asUINT p = 0; p < calledFunc->parameterTypes.GetLength(); p++ )
  2675. {
  2676. if( offset <= currOffset ) break;
  2677. if( !calledFunc->parameterTypes[p].IsPrimitive() ||
  2678. calledFunc->parameterTypes[p].IsReference() )
  2679. {
  2680. numPtrs++;
  2681. currOffset++;
  2682. // The variable arg ? has an additiona 32bit integer with the typeid
  2683. if( calledFunc->parameterTypes[p].IsAnyType() )
  2684. currOffset += 1;
  2685. }
  2686. else
  2687. {
  2688. // Enums or built-in primitives are passed by value
  2689. asASSERT( calledFunc->parameterTypes[p].IsPrimitive() );
  2690. currOffset += calledFunc->parameterTypes[p].GetSizeOnStackDWords();
  2691. }
  2692. }
  2693. return offset - numPtrs * (1 - AS_PTR_SIZE);
  2694. }
  2695. int asCReader::FindTypeId(int idx)
  2696. {
  2697. if( idx >= 0 && idx < (int)usedTypeIds.GetLength() )
  2698. return usedTypeIds[idx];
  2699. else
  2700. {
  2701. Error(TXT_INVALID_BYTECODE_d);
  2702. return 0;
  2703. }
  2704. }
  2705. asCObjectType *asCReader::FindObjectType(int idx)
  2706. {
  2707. if( idx < 0 || idx >= (int)usedTypes.GetLength() )
  2708. {
  2709. Error(TXT_INVALID_BYTECODE_d);
  2710. return 0;
  2711. }
  2712. return usedTypes[idx];
  2713. }
  2714. #ifndef AS_NO_COMPILER
  2715. asCWriter::asCWriter(asCModule* _module, asIBinaryStream* _stream, asCScriptEngine* _engine, bool _stripDebug)
  2716. : module(_module), stream(_stream), engine(_engine), stripDebugInfo(_stripDebug)
  2717. {
  2718. }
  2719. void asCWriter::WriteData(const void *data, asUINT size)
  2720. {
  2721. asASSERT(size == 1 || size == 2 || size == 4 || size == 8);
  2722. #if defined(AS_BIG_ENDIAN)
  2723. for( asUINT n = 0; n < size; n++ )
  2724. stream->Write(((asBYTE*)data)+n, 1);
  2725. #else
  2726. for( int n = size-1; n >= 0; n-- )
  2727. stream->Write(((asBYTE*)data)+n, 1);
  2728. #endif
  2729. }
  2730. int asCWriter::Write()
  2731. {
  2732. unsigned long i, count;
  2733. // Store everything in the same order that the builder parses scripts
  2734. // TODO: Should be possible to skip saving the enum values. They are usually not needed after the script is compiled anyway
  2735. // TODO: Should be possible to skip saving the typedefs. They are usually not needed after the script is compiled anyway
  2736. // TODO: Should be possible to skip saving constants. They are usually not needed after the script is compiled anyway
  2737. WriteData(&stripDebugInfo, sizeof(stripDebugInfo));
  2738. // Store enums
  2739. count = (asUINT)module->enumTypes.GetLength();
  2740. WriteEncodedInt64(count);
  2741. for( i = 0; i < count; i++ )
  2742. {
  2743. WriteObjectTypeDeclaration(module->enumTypes[i], 1);
  2744. WriteObjectTypeDeclaration(module->enumTypes[i], 2);
  2745. }
  2746. // Store type declarations first
  2747. count = (asUINT)module->classTypes.GetLength();
  2748. WriteEncodedInt64(count);
  2749. for( i = 0; i < count; i++ )
  2750. {
  2751. // Store only the name of the class/interface types
  2752. WriteObjectTypeDeclaration(module->classTypes[i], 1);
  2753. }
  2754. // Store func defs
  2755. count = (asUINT)module->funcDefs.GetLength();
  2756. WriteEncodedInt64(count);
  2757. for( i = 0; i < count; i++ )
  2758. WriteFunction(module->funcDefs[i]);
  2759. // Now store all interface methods
  2760. count = (asUINT)module->classTypes.GetLength();
  2761. for( i = 0; i < count; i++ )
  2762. {
  2763. if( module->classTypes[i]->IsInterface() )
  2764. WriteObjectTypeDeclaration(module->classTypes[i], 2);
  2765. }
  2766. // Then store the class methods and behaviours
  2767. for( i = 0; i < count; ++i )
  2768. {
  2769. if( !module->classTypes[i]->IsInterface() )
  2770. WriteObjectTypeDeclaration(module->classTypes[i], 2);
  2771. }
  2772. // Then store the class properties
  2773. for( i = 0; i < count; ++i )
  2774. {
  2775. if( !module->classTypes[i]->IsInterface() )
  2776. WriteObjectTypeDeclaration(module->classTypes[i], 3);
  2777. }
  2778. // Store typedefs
  2779. count = (asUINT)module->typeDefs.GetLength();
  2780. WriteEncodedInt64(count);
  2781. for( i = 0; i < count; i++ )
  2782. {
  2783. WriteObjectTypeDeclaration(module->typeDefs[i], 1);
  2784. WriteObjectTypeDeclaration(module->typeDefs[i], 2);
  2785. }
  2786. // scriptGlobals[]
  2787. count = (asUINT)module->scriptGlobals.GetSize();
  2788. WriteEncodedInt64(count);
  2789. asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List();
  2790. for( ; it; it++ )
  2791. WriteGlobalProperty(*it);
  2792. // scriptFunctions[]
  2793. count = 0;
  2794. for( i = 0; i < module->scriptFunctions.GetLength(); i++ )
  2795. if( module->scriptFunctions[i]->objectType == 0 )
  2796. count++;
  2797. WriteEncodedInt64(count);
  2798. for( i = 0; i < module->scriptFunctions.GetLength(); ++i )
  2799. if( module->scriptFunctions[i]->objectType == 0 )
  2800. WriteFunction(module->scriptFunctions[i]);
  2801. // globalFunctions[]
  2802. count = (int)module->globalFunctions.GetSize();
  2803. asCSymbolTable<asCScriptFunction>::iterator funcIt = module->globalFunctions.List();
  2804. WriteEncodedInt64(count);
  2805. while( funcIt )
  2806. {
  2807. WriteFunction(*funcIt);
  2808. funcIt++;
  2809. }
  2810. // bindInformations[]
  2811. count = (asUINT)module->bindInformations.GetLength();
  2812. WriteEncodedInt64(count);
  2813. for( i = 0; i < count; ++i )
  2814. {
  2815. WriteFunction(module->bindInformations[i]->importedFunctionSignature);
  2816. WriteString(&module->bindInformations[i]->importFromModule);
  2817. }
  2818. // usedTypes[]
  2819. count = (asUINT)usedTypes.GetLength();
  2820. WriteEncodedInt64(count);
  2821. for( i = 0; i < count; ++i )
  2822. WriteObjectType(usedTypes[i]);
  2823. // usedTypeIds[]
  2824. WriteUsedTypeIds();
  2825. // usedFunctions[]
  2826. WriteUsedFunctions();
  2827. // usedGlobalProperties[]
  2828. WriteUsedGlobalProps();
  2829. // usedStringConstants[]
  2830. WriteUsedStringConstants();
  2831. // usedObjectProperties[]
  2832. WriteUsedObjectProps();
  2833. return asSUCCESS;
  2834. }
  2835. int asCWriter::FindStringConstantIndex(int id)
  2836. {
  2837. asSMapNode<int,int> *cursor = 0;
  2838. if (stringIdToIndexMap.MoveTo(&cursor, id))
  2839. return cursor->value;
  2840. usedStringConstants.PushLast(id);
  2841. int index = int(usedStringConstants.GetLength() - 1);
  2842. stringIdToIndexMap.Insert(id, index);
  2843. return index;
  2844. }
  2845. void asCWriter::WriteUsedStringConstants()
  2846. {
  2847. asUINT count = (asUINT)usedStringConstants.GetLength();
  2848. WriteEncodedInt64(count);
  2849. for( asUINT i = 0; i < count; ++i )
  2850. WriteString(engine->stringConstants[usedStringConstants[i]]);
  2851. }
  2852. void asCWriter::WriteUsedFunctions()
  2853. {
  2854. asUINT count = (asUINT)usedFunctions.GetLength();
  2855. WriteEncodedInt64(count);
  2856. for( asUINT n = 0; n < usedFunctions.GetLength(); n++ )
  2857. {
  2858. char c;
  2859. // Write enough data to be able to uniquely identify the function upon load
  2860. if( usedFunctions[n] )
  2861. {
  2862. // Is the function from the module or the application?
  2863. c = usedFunctions[n]->module ? 'm' : 'a';
  2864. WriteData(&c, 1);
  2865. WriteFunctionSignature(usedFunctions[n]);
  2866. }
  2867. else
  2868. {
  2869. // null function pointer
  2870. c = 'n';
  2871. WriteData(&c, 1);
  2872. }
  2873. }
  2874. }
  2875. void asCWriter::WriteFunctionSignature(asCScriptFunction *func)
  2876. {
  2877. asUINT i, count;
  2878. WriteString(&func->name);
  2879. if( func->name == DELEGATE_FACTORY )
  2880. {
  2881. // It's not necessary to write anything else
  2882. return;
  2883. }
  2884. WriteDataType(&func->returnType);
  2885. count = (asUINT)func->parameterTypes.GetLength();
  2886. WriteEncodedInt64(count);
  2887. for( i = 0; i < count; ++i )
  2888. WriteDataType(&func->parameterTypes[i]);
  2889. // Only write the inout flags if any of them are set
  2890. count = 0;
  2891. for( i = asUINT(func->inOutFlags.GetLength()); i > 0; i-- )
  2892. if( func->inOutFlags[i-1] != asTM_NONE )
  2893. {
  2894. count = i;
  2895. break;
  2896. }
  2897. WriteEncodedInt64(count);
  2898. for( i = 0; i < count; ++i )
  2899. WriteEncodedInt64(func->inOutFlags[i]);
  2900. WriteEncodedInt64(func->funcType);
  2901. // Write the default args, from last to first
  2902. count = 0;
  2903. for( i = (asUINT)func->defaultArgs.GetLength(); i-- > 0; )
  2904. if( func->defaultArgs[i] )
  2905. count++;
  2906. WriteEncodedInt64(count);
  2907. for( i = (asUINT)func->defaultArgs.GetLength(); i-- > 0; )
  2908. if( func->defaultArgs[i] )
  2909. WriteString(func->defaultArgs[i]);
  2910. WriteObjectType(func->objectType);
  2911. if( func->objectType )
  2912. {
  2913. asBYTE b = 0;
  2914. b += func->isReadOnly ? 1 : 0;
  2915. b += func->isPrivate ? 2 : 0;
  2916. WriteData(&b, 1);
  2917. }
  2918. else
  2919. {
  2920. WriteString(&func->nameSpace->name);
  2921. }
  2922. }
  2923. void asCWriter::WriteFunction(asCScriptFunction* func)
  2924. {
  2925. char c;
  2926. // If there is no function, then store a null char
  2927. if( func == 0 )
  2928. {
  2929. c = '\0';
  2930. WriteData(&c, 1);
  2931. return;
  2932. }
  2933. // First check if the function has been saved already
  2934. for( asUINT f = 0; f < savedFunctions.GetLength(); f++ )
  2935. {
  2936. if( savedFunctions[f] == func )
  2937. {
  2938. c = 'r';
  2939. WriteData(&c, 1);
  2940. WriteEncodedInt64(f);
  2941. return;
  2942. }
  2943. }
  2944. // Keep a reference to the function in the list
  2945. savedFunctions.PushLast(func);
  2946. c = 'f';
  2947. WriteData(&c, 1);
  2948. asUINT i, count;
  2949. WriteFunctionSignature(func);
  2950. if( func->funcType == asFUNC_SCRIPT )
  2951. {
  2952. // Calculate the adjustment by position lookup table
  2953. CalculateAdjustmentByPos(func);
  2954. WriteByteCode(func);
  2955. asDWORD varSpace = AdjustStackPosition(func->scriptData->variableSpace);
  2956. WriteEncodedInt64(varSpace);
  2957. count = (asUINT)func->scriptData->objVariablePos.GetLength();
  2958. WriteEncodedInt64(count);
  2959. for( i = 0; i < count; ++i )
  2960. {
  2961. WriteObjectType(func->scriptData->objVariableTypes[i]);
  2962. // TODO: Only write this if the object type is the builtin function type
  2963. WriteEncodedInt64(FindFunctionIndex(func->scriptData->funcVariableTypes[i]));
  2964. WriteEncodedInt64(AdjustStackPosition(func->scriptData->objVariablePos[i]));
  2965. }
  2966. if( count > 0 )
  2967. WriteEncodedInt64(func->scriptData->objVariablesOnHeap);
  2968. WriteEncodedInt64((asUINT)func->scriptData->objVariableInfo.GetLength());
  2969. for( i = 0; i < func->scriptData->objVariableInfo.GetLength(); ++i )
  2970. {
  2971. // The program position must be adjusted to be in number of instructions
  2972. WriteEncodedInt64(bytecodeNbrByPos[func->scriptData->objVariableInfo[i].programPos]);
  2973. WriteEncodedInt64(AdjustStackPosition(func->scriptData->objVariableInfo[i].variableOffset));
  2974. WriteEncodedInt64(func->scriptData->objVariableInfo[i].option);
  2975. }
  2976. // The program position (every even number) needs to be adjusted
  2977. // to be in number of instructions instead of DWORD offset
  2978. if( !stripDebugInfo )
  2979. {
  2980. asUINT length = (asUINT)func->scriptData->lineNumbers.GetLength();
  2981. WriteEncodedInt64(length);
  2982. for( i = 0; i < length; ++i )
  2983. {
  2984. if( (i & 1) == 0 )
  2985. WriteEncodedInt64(bytecodeNbrByPos[func->scriptData->lineNumbers[i]]);
  2986. else
  2987. WriteEncodedInt64(func->scriptData->lineNumbers[i]);
  2988. }
  2989. // Write the array of script sections
  2990. length = (asUINT)func->scriptData->sectionIdxs.GetLength();
  2991. WriteEncodedInt64(length);
  2992. for( i = 0; i < length; ++i )
  2993. {
  2994. if( (i & 1) == 0 )
  2995. WriteEncodedInt64(bytecodeNbrByPos[func->scriptData->sectionIdxs[i]]);
  2996. else
  2997. {
  2998. if( func->scriptData->sectionIdxs[i] >= 0 )
  2999. WriteString(engine->scriptSectionNames[func->scriptData->sectionIdxs[i]]);
  3000. else
  3001. {
  3002. char c = 0;
  3003. WriteData(&c, 1);
  3004. }
  3005. }
  3006. }
  3007. }
  3008. WriteData(&func->isShared, 1);
  3009. // Write the variable information
  3010. if( !stripDebugInfo )
  3011. {
  3012. WriteEncodedInt64((asUINT)func->scriptData->variables.GetLength());
  3013. for( i = 0; i < func->scriptData->variables.GetLength(); i++ )
  3014. {
  3015. // The program position must be adjusted to be in number of instructions
  3016. WriteEncodedInt64(bytecodeNbrByPos[func->scriptData->variables[i]->declaredAtProgramPos]);
  3017. // The stack position must be adjusted according to the pointer sizes
  3018. WriteEncodedInt64(AdjustStackPosition(func->scriptData->variables[i]->stackOffset));
  3019. WriteString(&func->scriptData->variables[i]->name);
  3020. WriteDataType(&func->scriptData->variables[i]->type);
  3021. }
  3022. }
  3023. WriteData(&func->dontCleanUpOnException, 1);
  3024. // Store script section name
  3025. if( !stripDebugInfo )
  3026. {
  3027. if( func->scriptData->scriptSectionIdx >= 0 )
  3028. WriteString(engine->scriptSectionNames[func->scriptData->scriptSectionIdx]);
  3029. else
  3030. {
  3031. char c = 0;
  3032. WriteData(&c, 1);
  3033. }
  3034. WriteEncodedInt64(func->scriptData->declaredAt);
  3035. }
  3036. }
  3037. else if( func->funcType == asFUNC_VIRTUAL || func->funcType == asFUNC_INTERFACE )
  3038. {
  3039. // TODO: Do we really need to store this? It can probably be reconstructed by the reader
  3040. WriteEncodedInt64(func->vfTableIdx);
  3041. }
  3042. }
  3043. void asCWriter::WriteObjectTypeDeclaration(asCObjectType *ot, int phase)
  3044. {
  3045. if( phase == 1 )
  3046. {
  3047. // name
  3048. WriteString(&ot->name);
  3049. // flags
  3050. WriteData(&ot->flags, 4);
  3051. // size
  3052. // TODO: Do we really need to store this? The reader should be able to
  3053. // determine the correct size from the object type's flags
  3054. if( (ot->flags & asOBJ_SCRIPT_OBJECT) && ot->size > 0 )
  3055. {
  3056. // The size for script objects may vary from platform to platform so
  3057. // only store 1 to diferentiate from interfaces that have size 0.
  3058. WriteEncodedInt64(1);
  3059. }
  3060. else
  3061. {
  3062. // Enums, typedefs, and interfaces have fixed sizes independently
  3063. // of platform so it is safe to serialize the size directly.
  3064. WriteEncodedInt64(ot->size);
  3065. }
  3066. // namespace
  3067. WriteString(&ot->nameSpace->name);
  3068. }
  3069. else if( phase == 2 )
  3070. {
  3071. if( ot->flags & asOBJ_ENUM )
  3072. {
  3073. // enumValues[]
  3074. int size = (int)ot->enumValues.GetLength();
  3075. WriteEncodedInt64(size);
  3076. for( int n = 0; n < size; n++ )
  3077. {
  3078. WriteString(&ot->enumValues[n]->name);
  3079. WriteData(&ot->enumValues[n]->value, 4);
  3080. }
  3081. }
  3082. else if( ot->flags & asOBJ_TYPEDEF )
  3083. {
  3084. eTokenType t = ot->templateSubTypes[0].GetTokenType();
  3085. WriteEncodedInt64(t);
  3086. }
  3087. else
  3088. {
  3089. WriteObjectType(ot->derivedFrom);
  3090. // interfaces[] / interfaceVFTOffsets[]
  3091. // TOOD: Is it really necessary to store the VFTOffsets? Can't the reader calculate those?
  3092. int size = (asUINT)ot->interfaces.GetLength();
  3093. WriteEncodedInt64(size);
  3094. asUINT n;
  3095. for( n = 0; n < ot->interfaces.GetLength(); n++ )
  3096. {
  3097. WriteObjectType(ot->interfaces[n]);
  3098. WriteEncodedInt64(ot->interfaceVFTOffsets[n]);
  3099. }
  3100. // behaviours
  3101. // TODO: Default behaviours should just be stored as a indicator
  3102. // to avoid storing the actual function object
  3103. if( !ot->IsInterface() && ot->flags != asOBJ_TYPEDEF && ot->flags != asOBJ_ENUM )
  3104. {
  3105. WriteFunction(engine->scriptFunctions[ot->beh.destruct]);
  3106. size = (int)ot->beh.constructors.GetLength();
  3107. WriteEncodedInt64(size);
  3108. for( n = 0; n < ot->beh.constructors.GetLength(); n++ )
  3109. {
  3110. WriteFunction(engine->scriptFunctions[ot->beh.constructors[n]]);
  3111. WriteFunction(engine->scriptFunctions[ot->beh.factories[n]]);
  3112. }
  3113. }
  3114. // methods[]
  3115. // TODO: Avoid storing inherited methods in interfaces, as the reader
  3116. // can add those directly from the base interface
  3117. size = (int)ot->methods.GetLength();
  3118. WriteEncodedInt64(size);
  3119. for( n = 0; n < ot->methods.GetLength(); n++ )
  3120. {
  3121. WriteFunction(engine->scriptFunctions[ot->methods[n]]);
  3122. }
  3123. // virtualFunctionTable[]
  3124. // TODO: Is it really necessary to store this? Can't it be easily rebuilt by the reader
  3125. size = (int)ot->virtualFunctionTable.GetLength();
  3126. WriteEncodedInt64(size);
  3127. for( n = 0; n < (asUINT)size; n++ )
  3128. {
  3129. WriteFunction(ot->virtualFunctionTable[n]);
  3130. }
  3131. }
  3132. }
  3133. else if( phase == 3 )
  3134. {
  3135. // properties[]
  3136. asUINT size = (asUINT)ot->properties.GetLength();
  3137. WriteEncodedInt64(size);
  3138. for( asUINT n = 0; n < ot->properties.GetLength(); n++ )
  3139. {
  3140. WriteObjectProperty(ot->properties[n]);
  3141. }
  3142. }
  3143. }
  3144. void asCWriter::WriteEncodedInt64(asINT64 i)
  3145. {
  3146. asBYTE signBit = ( i & asINT64(1)<<63 ) ? 0x80 : 0;
  3147. if( signBit ) i = -i;
  3148. asBYTE b;
  3149. if( i < (1<<6) )
  3150. {
  3151. b = (asBYTE)(signBit + i); WriteData(&b, 1);
  3152. }
  3153. else if( i < (1<<13) )
  3154. {
  3155. b = asBYTE(0x40 + signBit + (i >> 8)); WriteData(&b, 1);
  3156. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3157. }
  3158. else if( i < (1<<20) )
  3159. {
  3160. b = asBYTE(0x60 + signBit + (i >> 16)); WriteData(&b, 1);
  3161. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3162. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3163. }
  3164. else if( i < (1<<27) )
  3165. {
  3166. b = asBYTE(0x70 + signBit + (i >> 24)); WriteData(&b, 1);
  3167. b = asBYTE((i >> 16) & 0xFF); WriteData(&b, 1);
  3168. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3169. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3170. }
  3171. else if( i < (asINT64(1)<<34) )
  3172. {
  3173. b = asBYTE(0x78 + signBit + (i >> 32)); WriteData(&b, 1);
  3174. b = asBYTE((i >> 24) & 0xFF); WriteData(&b, 1);
  3175. b = asBYTE((i >> 16) & 0xFF); WriteData(&b, 1);
  3176. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3177. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3178. }
  3179. else if( i < (asINT64(1)<<41) )
  3180. {
  3181. b = asBYTE(0x7C + signBit + (i >> 40)); WriteData(&b, 1);
  3182. b = asBYTE((i >> 32) & 0xFF); WriteData(&b, 1);
  3183. b = asBYTE((i >> 24) & 0xFF); WriteData(&b, 1);
  3184. b = asBYTE((i >> 16) & 0xFF); WriteData(&b, 1);
  3185. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3186. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3187. }
  3188. else if( i < (asINT64(1)<<48) )
  3189. {
  3190. b = asBYTE(0x7E + signBit + (i >> 48)); WriteData(&b, 1);
  3191. b = asBYTE((i >> 40) & 0xFF); WriteData(&b, 1);
  3192. b = asBYTE((i >> 32) & 0xFF); WriteData(&b, 1);
  3193. b = asBYTE((i >> 24) & 0xFF); WriteData(&b, 1);
  3194. b = asBYTE((i >> 16) & 0xFF); WriteData(&b, 1);
  3195. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3196. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3197. }
  3198. else
  3199. {
  3200. b = asBYTE(0x7F + signBit); WriteData(&b, 1);
  3201. b = asBYTE((i >> 56) & 0xFF); WriteData(&b, 1);
  3202. b = asBYTE((i >> 48) & 0xFF); WriteData(&b, 1);
  3203. b = asBYTE((i >> 40) & 0xFF); WriteData(&b, 1);
  3204. b = asBYTE((i >> 32) & 0xFF); WriteData(&b, 1);
  3205. b = asBYTE((i >> 24) & 0xFF); WriteData(&b, 1);
  3206. b = asBYTE((i >> 16) & 0xFF); WriteData(&b, 1);
  3207. b = asBYTE((i >> 8) & 0xFF); WriteData(&b, 1);
  3208. b = asBYTE(i & 0xFF); WriteData(&b, 1);
  3209. }
  3210. }
  3211. void asCWriter::WriteString(asCString* str)
  3212. {
  3213. // TODO: All strings should be stored in a separate section, and when
  3214. // they are used an offset into that section should be stored.
  3215. // This will make it unnecessary to store the extra byte to
  3216. // identify new versus old strings.
  3217. if( str->GetLength() == 0 )
  3218. {
  3219. char z = '\0';
  3220. WriteData(&z, 1);
  3221. return;
  3222. }
  3223. // First check if the string hasn't been saved already
  3224. asSMapNode<asCStringPointer, int> *cursor = 0;
  3225. if (stringToIdMap.MoveTo(&cursor, asCStringPointer(str)))
  3226. {
  3227. // Save a reference to the existing string
  3228. char b = 'r';
  3229. WriteData(&b, 1);
  3230. WriteEncodedInt64(cursor->value);
  3231. return;
  3232. }
  3233. // Save a new string
  3234. char b = 'n';
  3235. WriteData(&b, 1);
  3236. asUINT len = (asUINT)str->GetLength();
  3237. WriteEncodedInt64(len);
  3238. stream->Write(str->AddressOf(), (asUINT)len);
  3239. savedStrings.PushLast(*str);
  3240. stringToIdMap.Insert(asCStringPointer(str), int(savedStrings.GetLength()) - 1);
  3241. }
  3242. void asCWriter::WriteGlobalProperty(asCGlobalProperty* prop)
  3243. {
  3244. // TODO: We might be able to avoid storing the name and type of the global
  3245. // properties twice if we merge this with the WriteUsedGlobalProperties.
  3246. WriteString(&prop->name);
  3247. WriteString(&prop->nameSpace->name);
  3248. WriteDataType(&prop->type);
  3249. // Store the initialization function
  3250. if( prop->GetInitFunc() )
  3251. {
  3252. bool f = true;
  3253. WriteData(&f, 1);
  3254. WriteFunction(prop->GetInitFunc());
  3255. }
  3256. else
  3257. {
  3258. bool f = false;
  3259. WriteData(&f, 1);
  3260. }
  3261. }
  3262. void asCWriter::WriteObjectProperty(asCObjectProperty* prop)
  3263. {
  3264. WriteString(&prop->name);
  3265. WriteDataType(&prop->type);
  3266. WriteData(&prop->isPrivate, 1);
  3267. }
  3268. void asCWriter::WriteDataType(const asCDataType *dt)
  3269. {
  3270. // First check if the datatype has already been saved
  3271. for( asUINT n = 0; n < savedDataTypes.GetLength(); n++ )
  3272. {
  3273. if( *dt == savedDataTypes[n] )
  3274. {
  3275. asUINT c = 0;
  3276. WriteEncodedInt64(c);
  3277. WriteEncodedInt64(n);
  3278. return;
  3279. }
  3280. }
  3281. // Save the new datatype
  3282. savedDataTypes.PushLast(*dt);
  3283. bool b;
  3284. int t = dt->GetTokenType();
  3285. WriteEncodedInt64(t);
  3286. if( t == ttIdentifier )
  3287. {
  3288. WriteObjectType(dt->GetObjectType());
  3289. b = dt->IsObjectHandle();
  3290. WriteData(&b, 1);
  3291. b = dt->IsHandleToConst();
  3292. WriteData(&b, 1);
  3293. }
  3294. b = dt->IsReference();
  3295. WriteData(&b, 1);
  3296. b = dt->IsReadOnly();
  3297. WriteData(&b, 1);
  3298. if( t == ttIdentifier && dt->GetObjectType()->name == "_builtin_function_" )
  3299. {
  3300. WriteFunctionSignature(dt->GetFuncDef());
  3301. }
  3302. }
  3303. void asCWriter::WriteObjectType(asCObjectType* ot)
  3304. {
  3305. char ch;
  3306. if( ot )
  3307. {
  3308. // Check for template instances/specializations
  3309. if( ot->templateSubTypes.GetLength() )
  3310. {
  3311. // Check for list pattern type or template type
  3312. if( ot->flags & asOBJ_LIST_PATTERN )
  3313. {
  3314. ch = 'l';
  3315. WriteData(&ch, 1);
  3316. WriteObjectType(ot->templateSubTypes[0].GetObjectType());
  3317. }
  3318. else
  3319. {
  3320. ch = 'a';
  3321. WriteData(&ch, 1);
  3322. WriteString(&ot->name);
  3323. WriteEncodedInt64(ot->templateSubTypes.GetLength());
  3324. for( asUINT n = 0; n < ot->templateSubTypes.GetLength(); n++ )
  3325. {
  3326. if( ot->templateSubTypes[0].IsObject() || ot->templateSubTypes[0].IsEnumType() )
  3327. {
  3328. ch = 's';
  3329. WriteData(&ch, 1);
  3330. WriteDataType(&ot->templateSubTypes[0]);
  3331. }
  3332. else
  3333. {
  3334. ch = 't';
  3335. WriteData(&ch, 1);
  3336. eTokenType t = ot->templateSubTypes[0].GetTokenType();
  3337. WriteEncodedInt64(t);
  3338. }
  3339. }
  3340. }
  3341. }
  3342. else if( ot->flags & asOBJ_TEMPLATE_SUBTYPE )
  3343. {
  3344. ch = 's';
  3345. WriteData(&ch, 1);
  3346. WriteString(&ot->name);
  3347. }
  3348. else
  3349. {
  3350. ch = 'o';
  3351. WriteData(&ch, 1);
  3352. WriteString(&ot->name);
  3353. WriteString(&ot->nameSpace->name);
  3354. }
  3355. }
  3356. else
  3357. {
  3358. ch = '\0';
  3359. WriteData(&ch, 1);
  3360. }
  3361. }
  3362. void asCWriter::CalculateAdjustmentByPos(asCScriptFunction *func)
  3363. {
  3364. // Adjust the offset of all negative variables (parameters) so all pointers will have a size of 1 dword
  3365. asUINT n;
  3366. asCArray<int> adjustments;
  3367. asUINT offset = 0;
  3368. if( func->objectType )
  3369. {
  3370. adjustments.PushLast(offset);
  3371. adjustments.PushLast(1-AS_PTR_SIZE);
  3372. offset += AS_PTR_SIZE;
  3373. }
  3374. if( func->DoesReturnOnStack() )
  3375. {
  3376. adjustments.PushLast(offset);
  3377. adjustments.PushLast(1-AS_PTR_SIZE);
  3378. offset += AS_PTR_SIZE;
  3379. }
  3380. for( n = 0; n < func->parameterTypes.GetLength(); n++ )
  3381. {
  3382. if( !func->parameterTypes[n].IsPrimitive() ||
  3383. func->parameterTypes[n].IsReference() )
  3384. {
  3385. adjustments.PushLast(offset);
  3386. adjustments.PushLast(1-AS_PTR_SIZE);
  3387. offset += AS_PTR_SIZE;
  3388. }
  3389. else
  3390. {
  3391. asASSERT( func->parameterTypes[n].IsPrimitive() );
  3392. offset += func->parameterTypes[n].GetSizeOnStackDWords();
  3393. }
  3394. }
  3395. // Build look-up table with the adjustments for each stack position
  3396. adjustNegativeStackByPos.SetLength(offset);
  3397. memset(adjustNegativeStackByPos.AddressOf(), 0, adjustNegativeStackByPos.GetLength()*sizeof(int));
  3398. for( n = 0; n < adjustments.GetLength(); n+=2 )
  3399. {
  3400. int pos = adjustments[n];
  3401. int adjust = adjustments[n+1];
  3402. for( asUINT i = pos+1; i < adjustNegativeStackByPos.GetLength(); i++ )
  3403. adjustNegativeStackByPos[i] += adjust;
  3404. }
  3405. // Adjust the offset of all positive variables so that all object types and handles have a size of 1 dword
  3406. // This is similar to how the adjustment is done in the asCReader::TranslateFunction, only the reverse
  3407. adjustments.SetLength(0);
  3408. for( n = 0; n < func->scriptData->objVariableTypes.GetLength(); n++ )
  3409. {
  3410. if( func->scriptData->objVariableTypes[n] )
  3411. {
  3412. // Determine the size the variable currently occupies on the stack
  3413. int size = AS_PTR_SIZE;
  3414. if( (func->scriptData->objVariableTypes[n]->GetFlags() & asOBJ_VALUE) &&
  3415. n >= func->scriptData->objVariablesOnHeap )
  3416. {
  3417. size = func->scriptData->objVariableTypes[n]->GetSize();
  3418. if( size < 4 )
  3419. size = 1;
  3420. else
  3421. size /= 4;
  3422. }
  3423. // If larger than 1 dword, adjust the offsets accordingly
  3424. if( size > 1 )
  3425. {
  3426. // How much needs to be adjusted?
  3427. adjustments.PushLast(func->scriptData->objVariablePos[n]);
  3428. adjustments.PushLast(-(size-1));
  3429. }
  3430. }
  3431. }
  3432. // Build look-up table with the adjustments for each stack position
  3433. adjustStackByPos.SetLength(func->scriptData->stackNeeded);
  3434. memset(adjustStackByPos.AddressOf(), 0, adjustStackByPos.GetLength()*sizeof(int));
  3435. for( n = 0; n < adjustments.GetLength(); n+=2 )
  3436. {
  3437. int pos = adjustments[n];
  3438. int adjust = adjustments[n+1];
  3439. for( asUINT i = pos; i < adjustStackByPos.GetLength(); i++ )
  3440. adjustStackByPos[i] += adjust;
  3441. }
  3442. // Compute the sequence number of each bytecode instruction in order to update the jump offsets
  3443. size_t length = func->scriptData->byteCode.GetLength();
  3444. asDWORD *bc = func->scriptData->byteCode.AddressOf();
  3445. bytecodeNbrByPos.SetLength(length);
  3446. asUINT num;
  3447. for( offset = 0, num = 0; offset < length; )
  3448. {
  3449. bytecodeNbrByPos[offset] = num;
  3450. offset += asBCTypeSize[asBCInfo[*(asBYTE*)(bc+offset)].type];
  3451. num++;
  3452. }
  3453. // The last instruction is always a BC_RET. This make it possible to query
  3454. // the number of instructions by checking the last entry in bytecodeNbrByPos
  3455. asASSERT(*(asBYTE*)(bc+length-1) == asBC_RET);
  3456. }
  3457. int asCWriter::AdjustStackPosition(int pos)
  3458. {
  3459. if( pos >= (int)adjustStackByPos.GetLength() )
  3460. {
  3461. // This happens for example if the function only have temporary variables
  3462. // The adjustByPos can also be empty if the function doesn't have any variables at all, but receive a handle by parameter
  3463. if( adjustStackByPos.GetLength() > 0 )
  3464. pos += adjustStackByPos[adjustStackByPos.GetLength()-1];
  3465. }
  3466. else if( pos >= 0 )
  3467. pos += adjustStackByPos[pos];
  3468. else
  3469. {
  3470. asASSERT( -pos < (int)adjustNegativeStackByPos.GetLength() );
  3471. pos -= (short)adjustNegativeStackByPos[-pos];
  3472. }
  3473. return pos;
  3474. }
  3475. int asCWriter::AdjustGetOffset(int offset, asCScriptFunction *func, asDWORD programPos)
  3476. {
  3477. // TODO: optimize: multiple instructions for the same function doesn't need to look for the function everytime
  3478. // the function can remember where it found the function and check if the programPos is still valid
  3479. // Get offset 0 doesn't need adjustment
  3480. if( offset == 0 ) return 0;
  3481. // Find out which function that will be called
  3482. asCScriptFunction *calledFunc = 0;
  3483. for( asUINT n = programPos; n < func->scriptData->byteCode.GetLength(); )
  3484. {
  3485. asBYTE bc = *(asBYTE*)&func->scriptData->byteCode[n];
  3486. if( bc == asBC_CALL ||
  3487. bc == asBC_CALLSYS ||
  3488. bc == asBC_CALLINTF )
  3489. {
  3490. // Find the function from the function id in bytecode
  3491. int funcId = asBC_INTARG(&func->scriptData->byteCode[n]);
  3492. calledFunc = engine->scriptFunctions[funcId];
  3493. break;
  3494. }
  3495. else if( bc == asBC_ALLOC )
  3496. {
  3497. // Find the function from the function id in the bytecode
  3498. int funcId = asBC_INTARG(&func->scriptData->byteCode[n+AS_PTR_SIZE]);
  3499. calledFunc = engine->scriptFunctions[funcId];
  3500. break;
  3501. }
  3502. else if( bc == asBC_CALLBND )
  3503. {
  3504. // Find the function from the engine's bind array
  3505. int funcId = asBC_INTARG(&func->scriptData->byteCode[n]);
  3506. calledFunc = engine->importedFunctions[funcId & ~FUNC_IMPORTED]->importedFunctionSignature;
  3507. break;
  3508. }
  3509. else if( bc == asBC_CallPtr )
  3510. {
  3511. int var = asBC_SWORDARG0(&func->scriptData->byteCode[n]);
  3512. asUINT v;
  3513. // Find the funcdef from the local variable
  3514. for( v = 0; v < func->scriptData->objVariablePos.GetLength(); v++ )
  3515. {
  3516. if( func->scriptData->objVariablePos[v] == var )
  3517. {
  3518. calledFunc = func->scriptData->funcVariableTypes[v];
  3519. break;
  3520. }
  3521. }
  3522. if( !calledFunc )
  3523. {
  3524. // Look in parameters
  3525. int paramPos = 0;
  3526. if( func->objectType )
  3527. paramPos -= AS_PTR_SIZE;
  3528. if( func->DoesReturnOnStack() )
  3529. paramPos -= AS_PTR_SIZE;
  3530. for( v = 0; v < func->parameterTypes.GetLength(); v++ )
  3531. {
  3532. if( var == paramPos )
  3533. {
  3534. calledFunc = func->parameterTypes[v].GetFuncDef();
  3535. break;
  3536. }
  3537. paramPos -= func->parameterTypes[v].GetSizeOnStackDWords();
  3538. }
  3539. }
  3540. break;
  3541. }
  3542. else if( bc == asBC_REFCPY ||
  3543. bc == asBC_COPY )
  3544. {
  3545. // In this case we know there is only 1 pointer on the stack above
  3546. asASSERT( offset == AS_PTR_SIZE );
  3547. return offset + (1 - AS_PTR_SIZE);
  3548. }
  3549. n += asBCTypeSize[asBCInfo[bc].type];
  3550. }
  3551. asASSERT( calledFunc );
  3552. // Count the number of pointers pushed on the stack above the
  3553. // current offset, and then adjust the offset accordingly
  3554. asUINT numPtrs = 0;
  3555. int currOffset = 0;
  3556. if( offset > currOffset && calledFunc->GetObjectType() )
  3557. {
  3558. numPtrs++;
  3559. currOffset += AS_PTR_SIZE;
  3560. }
  3561. if( offset > currOffset && calledFunc->DoesReturnOnStack() )
  3562. {
  3563. numPtrs++;
  3564. currOffset += AS_PTR_SIZE;
  3565. }
  3566. for( asUINT p = 0; p < calledFunc->parameterTypes.GetLength(); p++ )
  3567. {
  3568. if( offset <= currOffset ) break;
  3569. if( !calledFunc->parameterTypes[p].IsPrimitive() ||
  3570. calledFunc->parameterTypes[p].IsReference() )
  3571. {
  3572. // objects and references are passed by pointer
  3573. numPtrs++;
  3574. currOffset += AS_PTR_SIZE;
  3575. // The variable arg ? has an additional 32bit int with the typeid
  3576. if( calledFunc->parameterTypes[p].IsAnyType() )
  3577. currOffset += 1;
  3578. }
  3579. else
  3580. {
  3581. // built-in primitives or enums are passed by value
  3582. asASSERT( calledFunc->parameterTypes[p].IsPrimitive() );
  3583. currOffset += calledFunc->parameterTypes[p].GetSizeOnStackDWords();
  3584. }
  3585. }
  3586. // The get offset must match one of the parameter offsets
  3587. asASSERT( offset == currOffset );
  3588. return offset + numPtrs * (1 - AS_PTR_SIZE);
  3589. }
  3590. void asCWriter::WriteByteCode(asCScriptFunction *func)
  3591. {
  3592. asDWORD *bc = func->scriptData->byteCode.AddressOf();
  3593. size_t length = func->scriptData->byteCode.GetLength();
  3594. // The length cannot be stored, because it is platform dependent,
  3595. // instead we store the number of instructions
  3596. asUINT count = bytecodeNbrByPos[bytecodeNbrByPos.GetLength()-1] + 1;
  3597. WriteEncodedInt64(count);
  3598. asDWORD *startBC = bc;
  3599. while( length )
  3600. {
  3601. asDWORD tmp[4]; // The biggest instructions take up 4 DWORDs
  3602. asDWORD c = *(asBYTE*)bc;
  3603. // Copy the instruction to a temp buffer so we can work on it before saving
  3604. memcpy(tmp, bc, asBCTypeSize[asBCInfo[c].type]*sizeof(asDWORD));
  3605. if( c == asBC_ALLOC ) // PTR_DW_ARG
  3606. {
  3607. // Translate the object type
  3608. asCObjectType *ot = *(asCObjectType**)(tmp+1);
  3609. *(asPWORD*)(tmp+1) = FindObjectTypeIdx(ot);
  3610. // Translate the constructor func id, unless it is 0
  3611. if( *(int*)&tmp[1+AS_PTR_SIZE] != 0 )
  3612. {
  3613. // Increment 1 to the translated function id, as 0 will be reserved for no function
  3614. *(int*)&tmp[1+AS_PTR_SIZE] = 1+FindFunctionIndex(engine->scriptFunctions[*(int*)&tmp[1+AS_PTR_SIZE]]);
  3615. }
  3616. }
  3617. else if( c == asBC_REFCPY || // PTR_ARG
  3618. c == asBC_RefCpyV || // wW_PTR_ARG
  3619. c == asBC_OBJTYPE ) // PTR_ARG
  3620. {
  3621. // Translate object type pointers into indices
  3622. *(asPWORD*)(tmp+1) = FindObjectTypeIdx(*(asCObjectType**)(tmp+1));
  3623. }
  3624. else if( c == asBC_JitEntry ) // PTR_ARG
  3625. {
  3626. // We don't store the JIT argument
  3627. *(asPWORD*)(tmp+1) = 0;
  3628. }
  3629. else if( c == asBC_TYPEID || // DW_ARG
  3630. c == asBC_Cast ) // DW_ARG
  3631. {
  3632. // Translate type ids into indices
  3633. *(int*)(tmp+1) = FindTypeIdIdx(*(int*)(tmp+1));
  3634. }
  3635. else if( c == asBC_ADDSi || // W_DW_ARG
  3636. c == asBC_LoadThisR ) // W_DW_ARG
  3637. {
  3638. // Translate property offsets into indices
  3639. *(((short*)tmp)+1) = (short)FindObjectPropIndex(*(((short*)tmp)+1), *(int*)(tmp+1));
  3640. // Translate type ids into indices
  3641. *(int*)(tmp+1) = FindTypeIdIdx(*(int*)(tmp+1));
  3642. }
  3643. else if( c == asBC_LoadRObjR || // rW_W_DW_ARG
  3644. c == asBC_LoadVObjR ) // rW_W_DW_ARG
  3645. {
  3646. asCObjectType *ot = engine->GetObjectTypeFromTypeId(*(int*)(tmp+2));
  3647. if( ot->flags & asOBJ_LIST_PATTERN )
  3648. {
  3649. // List patterns have a different way of translating the offsets
  3650. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  3651. *(((short*)tmp)+2) = (short)listAdj->AdjustOffset(*(((short*)tmp)+2), ot);
  3652. }
  3653. else
  3654. {
  3655. // Translate property offsets into indices
  3656. // TODO: optimize: Pass the object type directly to the method instead of the type id
  3657. *(((short*)tmp)+2) = (short)FindObjectPropIndex(*(((short*)tmp)+2), *(int*)(tmp+2));
  3658. }
  3659. // Translate type ids into indices
  3660. *(int*)(tmp+2) = FindTypeIdIdx(*(int*)(tmp+2));
  3661. }
  3662. else if( c == asBC_COPY ) // W_DW_ARG
  3663. {
  3664. // Translate type ids into indices
  3665. *(int*)(tmp+1) = FindTypeIdIdx(*(int*)(tmp+1));
  3666. // Update the WORDARG0 to 0, as this will be recalculated on the target platform
  3667. asBC_WORDARG0(tmp) = 0;
  3668. }
  3669. else if( c == asBC_RET ) // W_ARG
  3670. {
  3671. // Save with arg 0, as this will be recalculated on the target platform
  3672. asBC_WORDARG0(tmp) = 0;
  3673. }
  3674. else if( c == asBC_CALL || // DW_ARG
  3675. c == asBC_CALLINTF || // DW_ARG
  3676. c == asBC_CALLSYS ) // DW_ARG
  3677. {
  3678. // Translate the function id
  3679. *(int*)(tmp+1) = FindFunctionIndex(engine->scriptFunctions[*(int*)(tmp+1)]);
  3680. }
  3681. else if( c == asBC_FuncPtr ) // PTR_ARG
  3682. {
  3683. // Translate the function pointer
  3684. *(asPWORD*)(tmp+1) = FindFunctionIndex(*(asCScriptFunction**)(tmp+1));
  3685. }
  3686. else if( c == asBC_STR ) // W_ARG
  3687. {
  3688. // Translate the string constant id
  3689. asWORD *arg = ((asWORD*)tmp)+1;
  3690. *arg = (asWORD)FindStringConstantIndex(*arg);
  3691. }
  3692. else if( c == asBC_CALLBND ) // DW_ARG
  3693. {
  3694. // Translate the function id
  3695. int funcId = tmp[1];
  3696. for( asUINT n = 0; n < module->bindInformations.GetLength(); n++ )
  3697. if( module->bindInformations[n]->importedFunctionSignature->id == funcId )
  3698. {
  3699. funcId = n;
  3700. break;
  3701. }
  3702. tmp[1] = funcId;
  3703. }
  3704. else if( c == asBC_PGA || // PTR_ARG
  3705. c == asBC_PshGPtr || // PTR_ARG
  3706. c == asBC_LDG || // PTR_ARG
  3707. c == asBC_PshG4 || // PTR_ARG
  3708. c == asBC_LdGRdR4 || // wW_PTR_ARG
  3709. c == asBC_CpyGtoV4 || // wW_PTR_ARG
  3710. c == asBC_CpyVtoG4 || // rW_PTR_ARG
  3711. c == asBC_SetG4 ) // PTR_DW_ARG
  3712. {
  3713. // Translate global variable pointers into indices
  3714. *(asPWORD*)(tmp+1) = FindGlobalPropPtrIndex(*(void**)(tmp+1));
  3715. }
  3716. else if( c == asBC_JMP || // DW_ARG
  3717. c == asBC_JZ ||
  3718. c == asBC_JNZ ||
  3719. c == asBC_JLowZ ||
  3720. c == asBC_JLowNZ ||
  3721. c == asBC_JS ||
  3722. c == asBC_JNS ||
  3723. c == asBC_JP ||
  3724. c == asBC_JNP ) // The JMPP instruction doesn't need modification
  3725. {
  3726. // Get the DWORD offset from arg
  3727. int offset = *(int*)(tmp+1);
  3728. // Determine instruction number for next instruction and destination
  3729. int bcSeqNum = bytecodeNbrByPos[bc - startBC] + 1;
  3730. asDWORD *targetBC = bc + 2 + offset;
  3731. int targetBcSeqNum = bytecodeNbrByPos[targetBC - startBC];
  3732. // Set the offset in number of instructions
  3733. *(int*)(tmp+1) = targetBcSeqNum - bcSeqNum;
  3734. }
  3735. else if( c == asBC_GETOBJ || // W_ARG
  3736. c == asBC_GETOBJREF ||
  3737. c == asBC_GETREF )
  3738. {
  3739. // Adjust the offset according to the function call that comes after
  3740. asBC_WORDARG0(tmp) = (asWORD)AdjustGetOffset(asBC_WORDARG0(tmp), func, asDWORD(bc - startBC));
  3741. }
  3742. else if( c == asBC_AllocMem )
  3743. {
  3744. // It's not necessary to store the size of the list buffer, as it will be recalculated in the reader
  3745. asBC_DWORDARG(tmp) = 0;
  3746. // Determine the type of the list pattern from the variable
  3747. short var = asBC_WORDARG0(tmp);
  3748. asCObjectType *ot = func->GetObjectTypeOfLocalVar(var);
  3749. // Create this helper object to adjust the offset of the elements accessed in the buffer
  3750. listAdjusters.PushLast(asNEW(SListAdjuster)(ot));
  3751. }
  3752. else if( c == asBC_FREE ) // wW_PTR_ARG
  3753. {
  3754. // Translate object type pointers into indices
  3755. asCObjectType *ot = *(asCObjectType**)(tmp+1);
  3756. *(asPWORD*)(tmp+1) = FindObjectTypeIdx(ot);
  3757. // Pop and destroy the list adjuster helper that was created with asBC_AllocMem
  3758. if( ot && (ot->flags & asOBJ_LIST_PATTERN) )
  3759. {
  3760. SListAdjuster *list = listAdjusters.PopLast();
  3761. asDELETE(list, SListAdjuster);
  3762. }
  3763. }
  3764. else if( c == asBC_SetListSize )
  3765. {
  3766. // Adjust the offset in the initialization list
  3767. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  3768. tmp[1] = listAdj->AdjustOffset(tmp[1], listAdj->patternType);
  3769. // Tell the adjuster how many repeated values there are
  3770. listAdj->SetRepeatCount(tmp[2]);
  3771. }
  3772. else if( c == asBC_PshListElmnt ) // W_DW_ARG
  3773. {
  3774. // Adjust the offset in the initialization list
  3775. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  3776. tmp[1] = listAdj->AdjustOffset(tmp[1], listAdj->patternType);
  3777. }
  3778. else if( c == asBC_SetListType )
  3779. {
  3780. // Adjust the offset in the initialization list
  3781. SListAdjuster *listAdj = listAdjusters[listAdjusters.GetLength()-1];
  3782. tmp[1] = listAdj->AdjustOffset(tmp[1], listAdj->patternType);
  3783. // Inform the adjuster of the type id of the next element
  3784. listAdj->SetNextType(tmp[2]);
  3785. // Translate the type id
  3786. tmp[2] = FindTypeIdIdx(tmp[2]);
  3787. }
  3788. // Adjust the variable offsets
  3789. switch( asBCInfo[c].type )
  3790. {
  3791. case asBCTYPE_wW_ARG:
  3792. case asBCTYPE_rW_DW_ARG:
  3793. case asBCTYPE_wW_QW_ARG:
  3794. case asBCTYPE_rW_ARG:
  3795. case asBCTYPE_wW_DW_ARG:
  3796. case asBCTYPE_wW_W_ARG:
  3797. case asBCTYPE_rW_QW_ARG:
  3798. case asBCTYPE_rW_W_DW_ARG:
  3799. case asBCTYPE_rW_DW_DW_ARG:
  3800. {
  3801. asBC_SWORDARG0(tmp) = (short)AdjustStackPosition(asBC_SWORDARG0(tmp));
  3802. }
  3803. break;
  3804. case asBCTYPE_wW_rW_ARG:
  3805. case asBCTYPE_wW_rW_DW_ARG:
  3806. case asBCTYPE_rW_rW_ARG:
  3807. {
  3808. asBC_SWORDARG0(tmp) = (short)AdjustStackPosition(asBC_SWORDARG0(tmp));
  3809. asBC_SWORDARG1(tmp) = (short)AdjustStackPosition(asBC_SWORDARG1(tmp));
  3810. }
  3811. break;
  3812. case asBCTYPE_wW_rW_rW_ARG:
  3813. {
  3814. asBC_SWORDARG0(tmp) = (short)AdjustStackPosition(asBC_SWORDARG0(tmp));
  3815. asBC_SWORDARG1(tmp) = (short)AdjustStackPosition(asBC_SWORDARG1(tmp));
  3816. asBC_SWORDARG2(tmp) = (short)AdjustStackPosition(asBC_SWORDARG2(tmp));
  3817. }
  3818. break;
  3819. default:
  3820. // The other types don't treat variables so won't be modified
  3821. break;
  3822. }
  3823. // TODO: bytecode: Must make sure that floats and doubles are always stored the same way regardless of platform.
  3824. // Some platforms may not use the IEEE 754 standard, in which case it is necessary to encode the values
  3825. // Now store the instruction in the smallest possible way
  3826. switch( asBCInfo[c].type )
  3827. {
  3828. case asBCTYPE_NO_ARG:
  3829. {
  3830. // Just write 1 byte
  3831. asBYTE b = (asBYTE)c;
  3832. WriteData(&b, 1);
  3833. }
  3834. break;
  3835. case asBCTYPE_W_ARG:
  3836. case asBCTYPE_wW_ARG:
  3837. case asBCTYPE_rW_ARG:
  3838. {
  3839. // Write the instruction code
  3840. asBYTE b = (asBYTE)c;
  3841. WriteData(&b, 1);
  3842. // Write the argument
  3843. short w = *(((short*)tmp)+1);
  3844. WriteEncodedInt64(w);
  3845. }
  3846. break;
  3847. case asBCTYPE_rW_DW_ARG:
  3848. case asBCTYPE_wW_DW_ARG:
  3849. case asBCTYPE_W_DW_ARG:
  3850. {
  3851. // Write the instruction code
  3852. asBYTE b = (asBYTE)c;
  3853. WriteData(&b, 1);
  3854. // Write the word argument
  3855. short w = *(((short*)tmp)+1);
  3856. WriteEncodedInt64(w);
  3857. // Write the dword argument
  3858. WriteEncodedInt64((int)tmp[1]);
  3859. }
  3860. break;
  3861. case asBCTYPE_DW_ARG:
  3862. {
  3863. // Write the instruction code
  3864. asBYTE b = (asBYTE)c;
  3865. WriteData(&b, 1);
  3866. // Write the argument
  3867. WriteEncodedInt64((int)tmp[1]);
  3868. }
  3869. break;
  3870. case asBCTYPE_DW_DW_ARG:
  3871. {
  3872. // Write the instruction code
  3873. asBYTE b = (asBYTE)c;
  3874. WriteData(&b, 1);
  3875. // Write the dword argument
  3876. WriteEncodedInt64((int)tmp[1]);
  3877. // Write the dword argument
  3878. WriteEncodedInt64((int)tmp[2]);
  3879. }
  3880. break;
  3881. case asBCTYPE_wW_rW_rW_ARG:
  3882. {
  3883. // Write the instruction code
  3884. asBYTE b = (asBYTE)c;
  3885. WriteData(&b, 1);
  3886. // Write the first argument
  3887. short w = *(((short*)tmp)+1);
  3888. WriteEncodedInt64(w);
  3889. // Write the second argument
  3890. w = *(((short*)tmp)+2);
  3891. WriteEncodedInt64(w);
  3892. // Write the third argument
  3893. w = *(((short*)tmp)+3);
  3894. WriteEncodedInt64(w);
  3895. }
  3896. break;
  3897. case asBCTYPE_wW_rW_ARG:
  3898. case asBCTYPE_rW_rW_ARG:
  3899. case asBCTYPE_wW_W_ARG:
  3900. {
  3901. // Write the instruction code
  3902. asBYTE b = (asBYTE)c;
  3903. WriteData(&b, 1);
  3904. // Write the first argument
  3905. short w = *(((short*)tmp)+1);
  3906. WriteEncodedInt64(w);
  3907. // Write the second argument
  3908. w = *(((short*)tmp)+2);
  3909. WriteEncodedInt64(w);
  3910. }
  3911. break;
  3912. case asBCTYPE_wW_rW_DW_ARG:
  3913. case asBCTYPE_rW_W_DW_ARG:
  3914. {
  3915. // Write the instruction code
  3916. asBYTE b = (asBYTE)c;
  3917. WriteData(&b, 1);
  3918. // Write the first argument
  3919. short w = *(((short*)tmp)+1);
  3920. WriteEncodedInt64(w);
  3921. // Write the second argument
  3922. w = *(((short*)tmp)+2);
  3923. WriteEncodedInt64(w);
  3924. // Write the third argument
  3925. int dw = tmp[2];
  3926. WriteEncodedInt64(dw);
  3927. }
  3928. break;
  3929. case asBCTYPE_QW_ARG:
  3930. {
  3931. // Write the instruction code
  3932. asBYTE b = (asBYTE)c;
  3933. WriteData(&b, 1);
  3934. // Write the argument
  3935. asQWORD qw = *(asQWORD*)&tmp[1];
  3936. WriteEncodedInt64(qw);
  3937. }
  3938. break;
  3939. case asBCTYPE_QW_DW_ARG:
  3940. {
  3941. // Write the instruction code
  3942. asBYTE b = (asBYTE)c;
  3943. WriteData(&b, 1);
  3944. // Write the argument
  3945. asQWORD qw = *(asQWORD*)&tmp[1];
  3946. WriteEncodedInt64(qw);
  3947. // Write the second argument
  3948. int dw = tmp[3];
  3949. WriteEncodedInt64(dw);
  3950. }
  3951. break;
  3952. case asBCTYPE_rW_QW_ARG:
  3953. case asBCTYPE_wW_QW_ARG:
  3954. {
  3955. // Write the instruction code
  3956. asBYTE b = (asBYTE)c;
  3957. WriteData(&b, 1);
  3958. // Write the first argument
  3959. short w = *(((short*)tmp)+1);
  3960. WriteEncodedInt64(w);
  3961. // Write the argument
  3962. asQWORD qw = *(asQWORD*)&tmp[1];
  3963. WriteEncodedInt64(qw);
  3964. }
  3965. break;
  3966. case asBCTYPE_rW_DW_DW_ARG:
  3967. {
  3968. // Write the instruction code
  3969. asBYTE b = (asBYTE)c;
  3970. WriteData(&b, 1);
  3971. // Write the short argument
  3972. short w = *(((short*)tmp)+1);
  3973. WriteEncodedInt64(w);
  3974. // Write the dword argument
  3975. WriteEncodedInt64((int)tmp[1]);
  3976. // Write the dword argument
  3977. WriteEncodedInt64((int)tmp[2]);
  3978. }
  3979. break;
  3980. default:
  3981. {
  3982. // This should never happen
  3983. asASSERT(false);
  3984. // Store the bc as is
  3985. for( int n = 0; n < asBCTypeSize[asBCInfo[c].type]; n++ )
  3986. WriteData(&tmp[n], 4);
  3987. }
  3988. }
  3989. // Move to the next instruction
  3990. bc += asBCTypeSize[asBCInfo[c].type];
  3991. length -= asBCTypeSize[asBCInfo[c].type];
  3992. }
  3993. }
  3994. asCWriter::SListAdjuster::SListAdjuster(asCObjectType *ot) : patternType(ot), repeatCount(0), entries(0), lastOffset(-1), nextTypeId(-1)
  3995. {
  3996. asASSERT( ot && (ot->flags & asOBJ_LIST_PATTERN) );
  3997. // Find the first expected value in the list
  3998. asSListPatternNode *node = ot->engine->scriptFunctions[patternType->templateSubTypes[0].GetBehaviour()->listFactory]->listPattern;
  3999. asASSERT( node && node->type == asLPT_START );
  4000. patternNode = node->next;
  4001. }
  4002. int asCWriter::SListAdjuster::AdjustOffset(int offset, asCObjectType *listPatternType)
  4003. {
  4004. // TODO: cleanup: The listPatternType parameter is not needed
  4005. asASSERT( patternType == listPatternType );
  4006. UNUSED_VAR(listPatternType);
  4007. asASSERT( offset >= lastOffset );
  4008. // If it is the same offset being accessed again, just return the same adjusted value
  4009. if( offset == lastOffset )
  4010. return entries-1;
  4011. lastOffset = offset;
  4012. // What is being expected at this position?
  4013. if( patternNode->type == asLPT_REPEAT )
  4014. {
  4015. // Don't move the patternNode yet because the caller must make a call to SetRepeatCount too
  4016. return entries++;
  4017. }
  4018. else if( patternNode->type == asLPT_TYPE )
  4019. {
  4020. const asCDataType &dt = reinterpret_cast<asSListPatternDataTypeNode*>(patternNode)->dataType;
  4021. if( dt.GetTokenType() == ttQuestion )
  4022. {
  4023. // The bytecode need to inform the type that will
  4024. // come next and then adjust that position too before
  4025. // we can move to the next node
  4026. if( nextTypeId != -1 )
  4027. {
  4028. if( repeatCount > 0 )
  4029. repeatCount--;
  4030. // Only move the patternNode if we're not expecting any more repeated entries
  4031. if( repeatCount == 0 )
  4032. patternNode = patternNode->next;
  4033. nextTypeId = -1;
  4034. }
  4035. }
  4036. else
  4037. {
  4038. if( repeatCount > 0 )
  4039. repeatCount--;
  4040. // Only move the patternNode if we're not expecting any more repeated entries
  4041. if( repeatCount == 0 )
  4042. patternNode = patternNode->next;
  4043. }
  4044. return entries++;
  4045. }
  4046. else if( patternNode->type == asLPT_START )
  4047. {
  4048. if( repeatCount > 0 )
  4049. repeatCount--;
  4050. SInfo info = {repeatCount, patternNode};
  4051. stack.PushLast(info);
  4052. repeatCount = 0;
  4053. patternNode = patternNode->next;
  4054. lastOffset--;
  4055. return AdjustOffset(offset, listPatternType);
  4056. }
  4057. else if( patternNode->type == asLPT_END )
  4058. {
  4059. SInfo info = stack.PopLast();
  4060. repeatCount = info.repeatCount;
  4061. if( repeatCount )
  4062. patternNode = info.startNode;
  4063. else
  4064. patternNode = patternNode->next;
  4065. lastOffset--;
  4066. return AdjustOffset(offset, listPatternType);
  4067. }
  4068. else
  4069. {
  4070. // Something is wrong with the pattern list declaration
  4071. asASSERT( false );
  4072. }
  4073. return 0;
  4074. }
  4075. void asCWriter::SListAdjuster::SetRepeatCount(asUINT rc)
  4076. {
  4077. // Make sure the list is expecting a repeat at this location
  4078. asASSERT( patternNode->type == asLPT_REPEAT );
  4079. // Now move to the next patternNode
  4080. patternNode = patternNode->next;
  4081. repeatCount = rc;
  4082. }
  4083. void asCWriter::SListAdjuster::SetNextType(int typeId)
  4084. {
  4085. // Make sure the list is expecting a type at this location
  4086. asASSERT( patternNode->type == asLPT_TYPE &&
  4087. reinterpret_cast<asSListPatternDataTypeNode*>(patternNode)->dataType.GetTokenType() == ttQuestion );
  4088. // Inform the type id for the next adjustment
  4089. nextTypeId = typeId;
  4090. }
  4091. void asCWriter::WriteUsedTypeIds()
  4092. {
  4093. asUINT count = (asUINT)usedTypeIds.GetLength();
  4094. WriteEncodedInt64(count);
  4095. for( asUINT n = 0; n < count; n++ )
  4096. {
  4097. asCDataType dt = engine->GetDataTypeFromTypeId(usedTypeIds[n]);
  4098. WriteDataType(&dt);
  4099. }
  4100. }
  4101. int asCWriter::FindGlobalPropPtrIndex(void *ptr)
  4102. {
  4103. int i = usedGlobalProperties.IndexOf(ptr);
  4104. if( i >= 0 ) return i;
  4105. usedGlobalProperties.PushLast(ptr);
  4106. return (int)usedGlobalProperties.GetLength()-1;
  4107. }
  4108. void asCWriter::WriteUsedGlobalProps()
  4109. {
  4110. int c = (int)usedGlobalProperties.GetLength();
  4111. WriteEncodedInt64(c);
  4112. for( int n = 0; n < c; n++ )
  4113. {
  4114. asPWORD *p = (asPWORD*)usedGlobalProperties[n];
  4115. // First search for the global in the module
  4116. char moduleProp = 0;
  4117. asCGlobalProperty *prop = 0;
  4118. asCSymbolTable<asCGlobalProperty>::iterator it = module->scriptGlobals.List();
  4119. for( ; it; it++ )
  4120. {
  4121. if( p == (*it)->GetAddressOfValue() )
  4122. {
  4123. prop = (*it);
  4124. moduleProp = 1;
  4125. break;
  4126. }
  4127. }
  4128. // If it is not in the module, it must be an application registered property
  4129. if( !prop )
  4130. {
  4131. asCSymbolTable<asCGlobalProperty>::iterator it = engine->registeredGlobalProps.List();
  4132. for( ; it; it++ )
  4133. {
  4134. if( it->GetAddressOfValue() == p )
  4135. {
  4136. prop = *it;
  4137. break;
  4138. }
  4139. }
  4140. }
  4141. asASSERT(prop);
  4142. // Store the name and type of the property so we can find it again on loading
  4143. WriteString(&prop->name);
  4144. WriteString(&prop->nameSpace->name);
  4145. WriteDataType(&prop->type);
  4146. // Also store whether the property is a module property or a registered property
  4147. WriteData(&moduleProp, 1);
  4148. }
  4149. }
  4150. void asCWriter::WriteUsedObjectProps()
  4151. {
  4152. int c = (int)usedObjectProperties.GetLength();
  4153. WriteEncodedInt64(c);
  4154. for( asUINT n = 0; n < usedObjectProperties.GetLength(); n++ )
  4155. {
  4156. asCObjectType *objType = usedObjectProperties[n].objType;
  4157. WriteObjectType(objType);
  4158. // Find the property name
  4159. for( asUINT p = 0; p < objType->properties.GetLength(); p++ )
  4160. {
  4161. if( objType->properties[p]->byteOffset == usedObjectProperties[n].offset )
  4162. {
  4163. WriteString(&objType->properties[p]->name);
  4164. break;
  4165. }
  4166. }
  4167. }
  4168. }
  4169. int asCWriter::FindObjectPropIndex(short offset, int typeId)
  4170. {
  4171. asCObjectType *objType = engine->GetObjectTypeFromTypeId(typeId);
  4172. for( asUINT n = 0; n < usedObjectProperties.GetLength(); n++ )
  4173. {
  4174. if( usedObjectProperties[n].objType == objType &&
  4175. usedObjectProperties[n].offset == offset )
  4176. return n;
  4177. }
  4178. SObjProp prop = {objType, offset};
  4179. usedObjectProperties.PushLast(prop);
  4180. return (int)usedObjectProperties.GetLength() - 1;
  4181. }
  4182. int asCWriter::FindFunctionIndex(asCScriptFunction *func)
  4183. {
  4184. for( asUINT n = 0; n < usedFunctions.GetLength(); n++ )
  4185. {
  4186. if( usedFunctions[n] == func )
  4187. return n;
  4188. }
  4189. usedFunctions.PushLast(func);
  4190. return (int)usedFunctions.GetLength() - 1;
  4191. }
  4192. int asCWriter::FindTypeIdIdx(int typeId)
  4193. {
  4194. asUINT n;
  4195. for( n = 0; n < usedTypeIds.GetLength(); n++ )
  4196. {
  4197. if( usedTypeIds[n] == typeId )
  4198. return n;
  4199. }
  4200. usedTypeIds.PushLast(typeId);
  4201. return (int)usedTypeIds.GetLength() - 1;
  4202. }
  4203. int asCWriter::FindObjectTypeIdx(asCObjectType *obj)
  4204. {
  4205. asUINT n;
  4206. for( n = 0; n < usedTypes.GetLength(); n++ )
  4207. {
  4208. if( usedTypes[n] == obj )
  4209. return n;
  4210. }
  4211. usedTypes.PushLast(obj);
  4212. return (int)usedTypes.GetLength() - 1;
  4213. }
  4214. #endif // AS_NO_COMPILER
  4215. END_AS_NAMESPACE