as_restore.cpp 140 KB

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