as_restore.cpp 143 KB

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