as_restore.cpp 155 KB

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