as_restore.cpp 143 KB

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