ByteCodeSerializer.cpp 166 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862286328642865286628672868286928702871287228732874287528762877287828792880288128822883288428852886288728882889289028912892289328942895289628972898289929002901290229032904290529062907290829092910291129122913291429152916291729182919292029212922292329242925292629272928292929302931293229332934293529362937293829392940294129422943294429452946294729482949295029512952295329542955295629572958295929602961296229632964296529662967296829692970297129722973297429752976297729782979298029812982298329842985298629872988298929902991299229932994299529962997299829993000300130023003300430053006300730083009301030113012301330143015301630173018301930203021302230233024302530263027302830293030303130323033303430353036303730383039304030413042304330443045304630473048304930503051305230533054305530563057305830593060306130623063306430653066306730683069307030713072307330743075307630773078307930803081308230833084308530863087308830893090309130923093309430953096309730983099310031013102310331043105310631073108310931103111311231133114311531163117311831193120312131223123312431253126312731283129313031313132313331343135313631373138313931403141314231433144314531463147314831493150315131523153315431553156315731583159316031613162316331643165316631673168316931703171317231733174317531763177317831793180318131823183318431853186318731883189319031913192319331943195319631973198319932003201320232033204320532063207320832093210321132123213321432153216321732183219322032213222322332243225322632273228322932303231323232333234323532363237323832393240324132423243324432453246324732483249325032513252325332543255325632573258325932603261326232633264326532663267326832693270327132723273327432753276327732783279328032813282328332843285328632873288328932903291329232933294329532963297329832993300330133023303330433053306330733083309331033113312331333143315331633173318331933203321332233233324332533263327332833293330333133323333333433353336333733383339334033413342334333443345334633473348334933503351335233533354335533563357335833593360336133623363336433653366336733683369337033713372337333743375337633773378337933803381338233833384338533863387338833893390339133923393339433953396339733983399340034013402340334043405340634073408340934103411341234133414341534163417341834193420342134223423342434253426342734283429343034313432343334343435343634373438343934403441344234433444344534463447344834493450345134523453345434553456345734583459346034613462346334643465346634673468346934703471347234733474347534763477347834793480348134823483348434853486348734883489349034913492349334943495349634973498349935003501350235033504350535063507350835093510351135123513351435153516351735183519352035213522352335243525352635273528352935303531353235333534353535363537353835393540354135423543354435453546354735483549355035513552355335543555355635573558355935603561356235633564356535663567356835693570357135723573357435753576357735783579358035813582358335843585358635873588358935903591359235933594359535963597359835993600360136023603360436053606360736083609361036113612361336143615361636173618361936203621362236233624362536263627362836293630363136323633363436353636363736383639364036413642364336443645364636473648364936503651365236533654365536563657365836593660366136623663366436653666366736683669367036713672367336743675367636773678367936803681368236833684368536863687368836893690369136923693369436953696369736983699370037013702370337043705370637073708370937103711371237133714371537163717371837193720372137223723372437253726372737283729373037313732373337343735373637373738373937403741374237433744374537463747374837493750375137523753375437553756375737583759376037613762376337643765376637673768376937703771377237733774377537763777377837793780378137823783378437853786378737883789379037913792379337943795379637973798379938003801380238033804380538063807380838093810381138123813381438153816381738183819382038213822382338243825382638273828382938303831383238333834383538363837383838393840384138423843384438453846384738483849385038513852385338543855385638573858385938603861386238633864386538663867386838693870387138723873387438753876387738783879388038813882388338843885388638873888388938903891389238933894389538963897389838993900390139023903390439053906390739083909391039113912391339143915391639173918391939203921392239233924392539263927392839293930393139323933393439353936393739383939394039413942394339443945394639473948394939503951395239533954395539563957395839593960396139623963396439653966396739683969397039713972397339743975397639773978397939803981398239833984398539863987398839893990399139923993399439953996399739983999400040014002400340044005400640074008400940104011401240134014401540164017401840194020402140224023402440254026402740284029403040314032403340344035403640374038403940404041404240434044404540464047404840494050405140524053405440554056405740584059406040614062406340644065406640674068406940704071407240734074407540764077407840794080408140824083408440854086408740884089409040914092409340944095409640974098409941004101410241034104410541064107410841094110411141124113411441154116411741184119412041214122412341244125412641274128412941304131413241334134413541364137413841394140414141424143414441454146414741484149415041514152415341544155415641574158415941604161416241634164416541664167416841694170417141724173417441754176417741784179418041814182418341844185418641874188418941904191419241934194419541964197419841994200420142024203420442054206420742084209
  1. //-------------------------------------------------------------------------------------------------------
  2. // Copyright (C) Microsoft. All rights reserved.
  3. // Licensed under the MIT license. See LICENSE.txt file in the project root for full license information.
  4. //-------------------------------------------------------------------------------------------------------
  5. #include "RuntimeByteCodePch.h"
  6. #include "RegexCommon.h"
  7. #include "RegexPattern.h"
  8. #include "Library\RegexHelper.h"
  9. #include "DataStructures\Option.h"
  10. #include "DataStructures\ImmutableList.h"
  11. #include "DataStructures\BufferBuilder.h"
  12. #include "ByteCode\OpCodeUtilAsmJs.h"
  13. #include "ByteCode\ByteCodeSerializer.h"
  14. #include "Language\AsmJSModule.h"
  15. #include "Library\ES5Array.h"
  16. void ChakraBinaryBuildDateTimeHash(DWORD * buildDateHash, DWORD * buildTimeHash);
  17. namespace Js
  18. {
  19. const int magicConstant = *(int*)"ChBc";
  20. const int majorVersionConstant = 1;
  21. const int minorVersionConstant = 1;
  22. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  23. // These magic constants can be enabled to bracket and check different sections of the serialization
  24. // file. Turn on BYTE_CODE_MAGIC_CONSTANTS in ByteCodeSerializer.h to enable this.
  25. const int magicStartOfFunctionBody = *(int*)"fun[";
  26. const int magicEndOfFunctionBody = *(int*)"]fun";
  27. const int magicStartOfConstantTable = *(int*)"con[";
  28. const int magicEndOfConstantTable = *(int*)"]con";
  29. const int magicStartStringConstant = *(int*)"str[";
  30. const int magicEndStringConstant = *(int*)"]str";
  31. const int magicStartOfCacheIdToPropIdMap = *(int*)"cid[";
  32. const int magicEndOfCacheIdToPropIdMap = *(int*)"]cid";
  33. const int magicStartOfReferencedPropIdMap = *(int*)"rid[";
  34. const int magicEndOfReferencedPropIdMap = *(int*)"]rid";
  35. const int magicStartOfPropertyIdsForScopeSlotArray = *(int*)"scope[";
  36. const int magicEndOfPropertyIdsForScopeSlotArray = *(int*)"]scope";
  37. const int magicStartOfDebuggerScopes = *(int*)"dbgscope[";
  38. const int magicEndOfDebuggerScopes = *(int*)"]dbgscope";
  39. const int magicStartOfDebuggerScopeProperties = *(int*)"dbgscopeprop[";
  40. const int magicEndOfDebuggerScopeProperties = *(int*)"]dbgscopeprop";
  41. const int magicStartOfAux = *(int*)"aux[";
  42. const int magicEndOfAux = *(int*)"]aux";
  43. const int magicStartOfAuxVarArray = *(int*)"ava[";
  44. const int magicEndOfAuxVarArray = *(int*)"]ava";
  45. const int magicStartOfAuxIntArray = *(int*)"aia[";
  46. const int magicEndOfAuxIntArray = *(int*)"]aia";
  47. const int magicStartOfAuxFltArray = *(int*)"afa[";
  48. const int magicEndOfAuxFltArray = *(int*)"]afa";
  49. const int magicStartOfAuxPropIdArray = *(int*)"api[";
  50. const int magicEndOfAuxPropIdArray = *(int*)"]api";
  51. const int magicStartOfAuxFuncInfoArray = *(int*)"afi[";
  52. const int magicEndOfAuxFuncInfoArray = *(int*)"]afi";
  53. const int magicStartOfAsmJsFuncInfo = *(int*)"asmfuncinfo[";
  54. const int magicEndOfAsmJsFuncInfo = *(int*)"]asmfuncinfo";
  55. const int magicStartOfAsmJsModuleInfo = *(int*)"asmmodinfo[";
  56. const int magicEndOfAsmJsModuleInfo = *(int*)"]asmmodinfo";
  57. #endif
  58. // Serialized files are architecture specific
  59. #ifndef VALIDATE_SERIALIZED_BYTECODE
  60. #if _M_AMD64
  61. const byte magicArchitecture = 64;
  62. #else
  63. const byte magicArchitecture = 32;
  64. #endif
  65. #else
  66. #if _M_AMD64
  67. const int magicArchitecture = *(int*)"amd";
  68. #elif _M_IA64
  69. const int magicArchitecture = *(int*)"ia64";
  70. #elif _M_ARM
  71. const int magicArchitecture = *(int*)"arm";
  72. #elif _M_ARM_64
  73. const int magicArchitecture = *(int*)"arm64";
  74. #else
  75. const int magicArchitecture = *(int*)"x86";
  76. #endif
  77. #endif
  78. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  79. // Byte Code Serializer Versioning scheme
  80. // Version number is a GUID (128 bits). There are two versioning modes--Engineering and Release. Engineering mode is for day-to-day development. Every time chakra.dll is built a
  81. // fresh new version is generated by hashing the build date and time. This means that a byte code file saved to disk is exactly tied to the binary that generated it. This works
  82. // well for QA test runs and buddy tests because there is no chance of effects between runs.
  83. //
  84. // Release mode is used when chakra.dll is close to public release where there are actual changes to chakra. The GUID is a fixed number from build-to-build. This number will stay
  85. // the same for releases where there is no change to chakra.dll. The reason for this is that we don't want to invalidate compatible byte code that has already been cached.
  86. enum FileVersionScheme : byte
  87. {
  88. // Currently Chakra and ChakraCore versioning scheme is different.
  89. // Same version number for Chakra and ChakraCore doesn't mean they are the same.
  90. // Give the versioning scheme different value, so that byte code generate from one won't be use in the other.
  91. #ifdef NTBUILD
  92. EngineeringVersioningScheme = 10,
  93. ReleaseVersioningScheme = 20,
  94. #else
  95. EngineeringVersioningScheme = 11,
  96. ReleaseVersioningScheme = 21,
  97. #endif
  98. #if (defined(NTBUILD) && CHAKRA_VERSION_RELEASE) || (!defined(NTBUILD) && CHAKRA_CORE_VERSION_RELEASE)
  99. CurrentFileVersionScheme = ReleaseVersioningScheme
  100. #else
  101. CurrentFileVersionScheme = EngineeringVersioningScheme
  102. #endif
  103. };
  104. // it should be in separate file for testing
  105. #include "byteCodeCacheReleaseFileVersion.h"
  106. // Used for selective serialization of Function Body fields to make the representation compact
  107. #define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) bool has_##name : 1
  108. #define DECLARE_MANUAL_SERIALIZABLE_FIELD(type, name, serializableType, deserializeHere) bool has_##name: 1
  109. #define DEFINE_ALL_FIELDS
  110. struct SerializedFieldList {
  111. #include "SerializableFunctionFields.h"
  112. bool has_m_lineNumber: 1;
  113. bool has_m_columnNumber: 1;
  114. };
  115. C_ASSERT(sizeof(GUID)==sizeof(DWORD)*4);
  116. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  117. // Holds a buffer and size for use by the serializer
  118. struct ByteBuffer
  119. {
  120. uint32 byteCount;
  121. union
  122. {
  123. void * pv;
  124. const wchar_t * s16;
  125. const char * s8;
  126. };
  127. public:
  128. ByteBuffer(uint32 byteCount, void * pv)
  129. : byteCount(byteCount), pv(pv)
  130. { }
  131. };
  132. template<>
  133. struct DefaultComparer<ByteBuffer*>
  134. {
  135. static bool Equals(ByteBuffer const * str1, ByteBuffer const * str2)
  136. {
  137. if (str1->byteCount != str2->byteCount)
  138. {
  139. return false;
  140. }
  141. return memcmp(str1->pv, str2->pv, str1->byteCount)==0;
  142. }
  143. static hash_t GetHashCode(ByteBuffer const * str)
  144. {
  145. return JsUtil::CharacterBuffer<char>::StaticGetHashCode(str->s8, str->byteCount);
  146. }
  147. };
  148. struct IndexEntry
  149. {
  150. BufferBuilderByte* isPropertyRecord;
  151. int id;
  152. };
  153. #pragma pack(push, 1)
  154. struct StringIndexRecord
  155. {
  156. int offset;
  157. bool isPropertyRecord;
  158. };
  159. #pragma pack(pop)
  160. typedef JsUtil::BaseDictionary<ByteBuffer*, IndexEntry, ArenaAllocator, PrimeSizePolicy, DefaultComparer> TString16ToId;
  161. // Boolean flags on the FunctionBody
  162. enum FunctionFlags
  163. {
  164. ffIsDeclaration = 0x0001,
  165. ffHasImplicitArgsIn = 0x0002,
  166. ffIsAccessor = 0x0004,
  167. ffIsGlobalFunc = 0x0008,
  168. ffDontInline = 0x0010,
  169. ffIsFuncRegistered = 0x0020,
  170. ffIsStaticNameFunction = 0x0040,
  171. ffIsStrictMode = 0x0080,
  172. ffDoBackendArgumentsOptimization = 0x0100,
  173. ffIsEval = 0x0200,
  174. ffIsDynamicFunction = 0x0400,
  175. ffhasAllNonLocalReferenced = 0x0800,
  176. ffhasSetIsObject = 0x1000,
  177. ffhasSetCallsEval = 0x2000,
  178. ffIsNameIdentifierRef = 0x4000,
  179. ffChildCallsEval = 0x8000,
  180. ffHasReferenceableBuiltInArguments = 0x10000,
  181. ffIsNamedFunctionExpression = 0x20000,
  182. ffIsAsmJsMode = 0x40000,
  183. ffIsAsmJsFunction = 0x80000
  184. };
  185. // Kinds of constant
  186. enum ConstantType : byte
  187. {
  188. ctInt = 1,
  189. ctString16 = 2,
  190. ctNull = 3,
  191. ctUndefined = 4,
  192. ctNumber = 5,
  193. ctNullDisplay = 6,
  194. ctStrictNullDisplay = 7,
  195. ctTrue = 8,
  196. ctFalse = 9,
  197. ctStringTemplateCallsite = 10
  198. };
  199. // Try to convert from size_t to uint32. May overflow (and return false) on 64-bit.
  200. bool TryConvertToUInt32(size_t size, uint32 * out)
  201. {
  202. *out = (uint32)size;
  203. if (sizeof(size) == sizeof(uint32))
  204. {
  205. return true;
  206. }
  207. Assert(sizeof(size_t) == sizeof(uint64));
  208. if((uint64)(*out) == size)
  209. {
  210. return true;
  211. }
  212. AssertMsg(false, "Is it really an offset greater than 32 bits?"); // More likely a bug somewhere.
  213. return false;
  214. }
  215. #if VARIABLE_INT_ENCODING
  216. template <typename T>
  217. static const byte * ReadVariableInt(const byte * buffer, size_t remainingBytes, T * value)
  218. {
  219. Assert(remainingBytes >= sizeof(byte));
  220. byte firstByte = *(byte*) buffer;
  221. if (firstByte >= MIN_SENTINEL)
  222. {
  223. Assert(remainingBytes >= sizeof(uint16));
  224. const byte* locationOfValue = buffer + 1;
  225. if (firstByte == TWO_BYTE_SENTINEL)
  226. {
  227. uint16 twoByteValue = *((serialization_alignment uint16*) locationOfValue);
  228. Assert(twoByteValue > ONE_BYTE_MAX);
  229. *value = twoByteValue;
  230. PHASE_PRINT_TESTTRACE1(Js::VariableIntEncodingPhase, L"TestTrace: VariableIntEncoding (decode)- 2 bytes, value %u\n", *value);
  231. return buffer + sizeof(uint16) +SENTINEL_BYTE_COUNT;
  232. }
  233. else
  234. {
  235. Assert(remainingBytes >= sizeof(T));
  236. Assert(firstByte == FOUR_BYTE_SENTINEL);
  237. *value = *((serialization_alignment T*) locationOfValue);
  238. Assert(*value > TWO_BYTE_MAX || *value <= 0);
  239. PHASE_PRINT_TESTTRACE1(Js::VariableIntEncodingPhase, L"TestTrace: VariableIntEncoding (decode) - 4 bytes, value %u\n", *value);
  240. return buffer + sizeof(T) +SENTINEL_BYTE_COUNT;
  241. }
  242. }
  243. else
  244. {
  245. *value = (T) firstByte;
  246. PHASE_PRINT_TESTTRACE1(Js::VariableIntEncodingPhase, L"TestTrace: VariableIntEncoding (decode) - 1 byte, value %u\n", *value);
  247. return buffer + sizeof(byte);
  248. }
  249. }
  250. #endif
  251. // Compile-time-check some invariants that the file format depends on
  252. C_ASSERT(sizeof(PropertyId)==sizeof(int32));
  253. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  254. // Byte Code File Header Layout
  255. // Offset Size Name Value
  256. // 0 4 Magic Number "ChBc"
  257. // 4 4 Total File Size
  258. // 8 1 File Version Scheme 10 for engineering 20 for release
  259. // 9 4 Version DWORD 1 jscript minor version GUID quad part 1
  260. // 13 4 Version DWORD 2 jscript major version GUID quad part 2
  261. // 17 4 Version DWORD 3 hash of __DATE__ GUID quad part 3
  262. // 21 4 Version DWORD 4 hash of __TIME__ GUID quad part 4
  263. // 25 4 Expected Architecture "amd"0, "ia64", "arm"0 or "x86"0
  264. // 29 4 Expected Function Body Size
  265. // 33 4 Expected Built In PropertyCount
  266. // 37 4 Expected Op Code Count
  267. // 41 4 Size of Original Source Code
  268. // 45 4 Count of Auxiliary Structures
  269. // 49 4 Smallest Literal Object ID
  270. // 53 4 Largest Literal Object ID
  271. // 57 4 Offset from start of this file
  272. // to Strings Table
  273. // 61 4 Offset to Source Spans
  274. // 65 4 Count of Functions
  275. // 69 4 Offset to Functions
  276. // 73 4 Offset to Auxiliary Structures
  277. // 77 4 Count of Strings
  278. // --------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
  279. // This is the serializer
  280. class ByteCodeBufferBuilder
  281. {
  282. // Begin File Layout -------------------------------
  283. ConstantSizedBufferBuilderOf<int32> magic;
  284. ConstantSizedBufferBuilderOf<int32> totalSize; // The size is unknown when the offsets are calculated so just reserve 4 bytes for this for now to avoid doing two passes to calculate the offsets
  285. BufferBuilderByte fileVersionKind; // Engineering or Release
  286. ConstantSizedBufferBuilderOf<int32> V1; // V1-V4 are the parts of the version. It is a fixed version GUID or a per-build version.
  287. ConstantSizedBufferBuilderOf<int32> V2;
  288. ConstantSizedBufferBuilderOf<int32> V3;
  289. ConstantSizedBufferBuilderOf<int32> V4;
  290. BufferBuilderInt32 architecture;
  291. BufferBuilderInt32 expectedFunctionBodySize;
  292. BufferBuilderInt32 expectedBuildInPropertyCount;
  293. BufferBuilderInt32 expectedOpCodeCount;
  294. BufferBuilderInt32 originalSourceSize;
  295. BufferBuilderInt32 originalCharLength;
  296. BufferBuilderRelativeOffset string16sOffset;
  297. BufferBuilderRelativeOffset sourceSpansOffset;
  298. BufferBuilderRelativeOffset lineInfoCacheOffset;
  299. BufferBuilderRelativeOffset functionsOffset;
  300. BufferBuilderInt32 string16Count;
  301. BufferBuilderList string16IndexTable;
  302. BufferBuilderList string16Table;
  303. BufferBuilderAligned alignedString16Table;
  304. BufferBuilderList sourceSpans;
  305. BufferBuilderInt32 lineInfoCacheCount;
  306. BufferBuilderRaw lineInfoCache;
  307. BufferBuilderInt32 functionCount;
  308. BufferBuilderList functionsTable;
  309. // End File Layout ---------------------------------
  310. ArenaAllocator * alloc;
  311. TString16ToId * string16ToId;
  312. int nextString16Id;
  313. int topFunctionId;
  314. LPCUTF8 utf8Source;
  315. ScriptContext * scriptContext;
  316. BufferBuilder * startOfCachedScopeAuxBlock;
  317. DWORD dwFlags;
  318. DWORD dwFunctionTableLength;
  319. BYTE *functionTable;
  320. //Instead of referencing TotalNumberOfBuiltInProperties directly; or PropertyIds::_countJSOnlyProperty we use this.
  321. //For library code this will be set to _countJSOnlyProperty and for normal bytecode this will be TotalNumberOfBuiltInProperties
  322. int builtInPropertyCount;
  323. bool GenerateLibraryByteCode() const
  324. {
  325. return (dwFlags & GENERATE_BYTE_CODE_BUFFER_LIBRARY) != 0;
  326. }
  327. bool OmitFunction(int serializationIndex) const
  328. {
  329. return functionTable && ((serializationIndex >= (int)dwFunctionTableLength) || !functionTable[serializationIndex]);
  330. }
  331. bool GenerateByteCodeForNative(int serializationIndex) const
  332. {
  333. return (dwFlags & GENERATE_BYTE_CODE_FOR_NATIVE) != 0;
  334. }
  335. public:
  336. ByteCodeBufferBuilder(uint32 sourceSize, uint32 sourceCharLength, LPCUTF8 utf8Source, DWORD dwFunctionTableLength, BYTE * functionTable, Utf8SourceInfo* sourceInfo, ScriptContext * scriptContext, ArenaAllocator * alloc, DWORD dwFlags, int builtInPropertyCount)
  337. : magic(L"Magic", magicConstant),
  338. totalSize(L"Total Size", 0),
  339. fileVersionKind(L"FileVersionKind", 0),
  340. V1(L"V1", 0),
  341. V2(L"V2", 0),
  342. V3(L"V3", 0),
  343. V4(L"V4", 0),
  344. architecture(L"Expected Architecture", magicArchitecture),
  345. expectedFunctionBodySize(L"Expected Function Body Size", sizeof(unaligned FunctionBody)),
  346. expectedBuildInPropertyCount(L"Expected Built-in Properties", builtInPropertyCount),
  347. expectedOpCodeCount(L"Expected Number of OpCodes", (int)OpCode::Count),
  348. originalSourceSize(L"Source Size", sourceSize),
  349. originalCharLength(L"Source Char Length", sourceCharLength),
  350. string16sOffset(L"Offset of String16s", &string16Count),
  351. sourceSpansOffset(L"Offset of Source Spans", &sourceSpans),
  352. lineInfoCacheOffset(L"Offset of Source Spans", &lineInfoCacheCount),
  353. functionCount(L"Function Count", 0),
  354. functionsOffset(L"Offset of Functions", &functionCount),
  355. string16Count(L"String16 Count", 0),
  356. string16IndexTable(L"String16 Indexes"),
  357. string16Table(L"String16 Table"),
  358. alignedString16Table(L"Alignment for String16 Table", &string16Table, sizeof(wchar_t)),
  359. sourceSpans(L"Source Spans"),
  360. lineInfoCacheCount(L"Line Info Cache", sourceInfo->GetLineOffsetCache()->GetLineCount()),
  361. lineInfoCache(L"Line Info Cache", lineInfoCacheCount.value * sizeof(JsUtil::LineOffsetCache<Recycler>::LineOffsetCacheItem), (byte *)sourceInfo->GetLineOffsetCache()->GetItems()),
  362. functionsTable(L"Functions"),
  363. nextString16Id(builtInPropertyCount), // Reserve the built-in property ids
  364. topFunctionId(0),
  365. utf8Source(utf8Source),
  366. scriptContext(scriptContext),
  367. startOfCachedScopeAuxBlock(nullptr),
  368. alloc(alloc),
  369. dwFlags(dwFlags),
  370. builtInPropertyCount(builtInPropertyCount),
  371. dwFunctionTableLength(dwFunctionTableLength),
  372. functionTable(functionTable)
  373. {
  374. if (GenerateLibraryByteCode())
  375. {
  376. expectedFunctionBodySize.value = 0;
  377. expectedOpCodeCount.value = 0;
  378. }
  379. // library alaways use the release versioning scheme
  380. byte actualFileVersionScheme = GenerateLibraryByteCode()? ReleaseVersioningScheme : CurrentFileVersionScheme;
  381. #if ENABLE_DEBUG_CONFIG_OPTIONS
  382. if (Js::Configuration::Global.flags.ForceSerializedBytecodeVersionSchema)
  383. {
  384. actualFileVersionScheme = (byte)Js::Configuration::Global.flags.ForceSerializedBytecodeVersionSchema;
  385. }
  386. #endif
  387. fileVersionKind.value = actualFileVersionScheme;
  388. if (actualFileVersionScheme != ReleaseVersioningScheme)
  389. {
  390. Assert(!GenerateLibraryByteCode());
  391. Assert(actualFileVersionScheme == EngineeringVersioningScheme);
  392. DWORD jscriptMajor, jscriptMinor, buildDateHash, buildTimeHash;
  393. Js::VerifyOkCatastrophic(AutoSystemInfo::GetJscriptFileVersion(&jscriptMajor, &jscriptMinor, &buildDateHash, &buildTimeHash));
  394. V1.value = jscriptMajor;
  395. V2.value = jscriptMinor;
  396. V3.value = buildDateHash;
  397. V4.value = buildTimeHash;
  398. }
  399. else
  400. {
  401. auto guidDWORDs = (DWORD*)(&byteCodeCacheReleaseFileVersion);
  402. V1.value = guidDWORDs[0];
  403. V2.value = guidDWORDs[1];
  404. V3.value = guidDWORDs[2];
  405. V4.value = guidDWORDs[3];
  406. }
  407. #if ENABLE_DEBUG_CONFIG_OPTIONS
  408. if (Js::Configuration::Global.flags.ForceSerializedBytecodeMajorVersion)
  409. {
  410. V1.value = Js::Configuration::Global.flags.ForceSerializedBytecodeMajorVersion;
  411. V2.value = 0;
  412. V3.value = 0;
  413. V4.value = 0;
  414. }
  415. #endif
  416. string16ToId = Anew(alloc, TString16ToId, alloc);
  417. }
  418. HRESULT Create(bool allocateBuffer, byte ** buffer, DWORD * bufferBytes)
  419. {
  420. BufferBuilderList all(L"Final");
  421. // Reverse the lists
  422. string16IndexTable.list = string16IndexTable.list->ReverseCurrentList();
  423. string16Table.list = string16Table.list->ReverseCurrentList();
  424. // Prepend all sections (in reverse order because of prepend)
  425. all.list = all.list->Prepend(&functionsTable, alloc);
  426. all.list = all.list->Prepend(&functionCount, alloc);
  427. all.list = all.list->Prepend(&lineInfoCache, alloc);
  428. all.list = all.list->Prepend(&lineInfoCacheCount, alloc);
  429. all.list = all.list->Prepend(&alignedString16Table, alloc);
  430. all.list = all.list->Prepend(&string16IndexTable, alloc);
  431. all.list = all.list->Prepend(&string16Count, alloc);
  432. all.list = all.list->Prepend(&functionsOffset, alloc);
  433. all.list = all.list->Prepend(&sourceSpansOffset, alloc);
  434. all.list = all.list->Prepend(&lineInfoCacheOffset, alloc);
  435. all.list = all.list->Prepend(&string16sOffset, alloc);
  436. all.list = all.list->Prepend(&originalCharLength, alloc);
  437. all.list = all.list->Prepend(&originalSourceSize, alloc);
  438. all.list = all.list->Prepend(&expectedOpCodeCount, alloc);
  439. all.list = all.list->Prepend(&expectedBuildInPropertyCount, alloc);
  440. all.list = all.list->Prepend(&expectedFunctionBodySize, alloc);
  441. all.list = all.list->Prepend(&architecture, alloc);
  442. all.list = all.list->Prepend(&V4, alloc);
  443. all.list = all.list->Prepend(&V3, alloc);
  444. all.list = all.list->Prepend(&V2, alloc);
  445. all.list = all.list->Prepend(&V1, alloc);
  446. all.list = all.list->Prepend(&fileVersionKind, alloc);
  447. all.list = all.list->Prepend(&totalSize, alloc);
  448. all.list = all.list->Prepend(&magic, alloc);
  449. // Get the string count.
  450. string16Count.value = nextString16Id - this->builtInPropertyCount;
  451. // Figure out the size and set all individual offsets
  452. DWORD size = all.FixOffset(0);
  453. totalSize.value = size;
  454. // Allocate the bytes
  455. if (allocateBuffer)
  456. {
  457. *bufferBytes = size;
  458. *buffer = (byte*)CoTaskMemAlloc(*bufferBytes);
  459. if (*buffer == nullptr)
  460. {
  461. return E_OUTOFMEMORY;
  462. }
  463. }
  464. if (size > *bufferBytes)
  465. {
  466. *bufferBytes = size;
  467. return *buffer == nullptr ? S_OK : E_INVALIDARG;
  468. }
  469. else
  470. {
  471. // Write into the buffer
  472. all.Write(*buffer, *bufferBytes);
  473. *bufferBytes = size;
  474. DebugOnly(Output::Flush()); // Flush trace
  475. return S_OK;
  476. }
  477. }
  478. bool isBuiltinProperty(PropertyId pid) {
  479. if (pid < this->builtInPropertyCount || pid==/*nil*/0xffffffff)
  480. {
  481. return true;
  482. }
  483. return false;
  484. };
  485. PropertyId encodeNonBuiltinPropertyId(PropertyId id) {
  486. const PropertyRecord * propertyValue = nullptr;
  487. Assert(id >= this->builtInPropertyCount); // Shouldn't have gotten a builtin property id
  488. propertyValue = scriptContext->GetPropertyName(id);
  489. id = GetIdOfPropertyRecord(propertyValue) - this->builtInPropertyCount;
  490. return id ^ SERIALIZER_OBSCURE_NONBUILTIN_PROPERTY_ID;
  491. };
  492. PropertyId encodePossiblyBuiltInPropertyId(PropertyId id) {
  493. const PropertyRecord * propertyValue = nullptr;
  494. if(id >= this->builtInPropertyCount)
  495. {
  496. propertyValue = scriptContext->GetPropertyName(id);
  497. id = GetIdOfPropertyRecord(propertyValue);
  498. }
  499. return id ^ SERIALIZER_OBSCURE_PROPERTY_ID;
  500. };
  501. int GetString16Id(ByteBuffer * bb, bool isPropertyRecord = false)
  502. {
  503. IndexEntry indexEntry;
  504. if (!string16ToId->TryGetValue(bb, &indexEntry))
  505. {
  506. auto sizeInBytes = bb->byteCount;
  507. auto stringEntry = Anew(alloc, BufferBuilderRaw, L"String16", sizeInBytes, (const byte *)bb->pv); // Writing the terminator even though it is computable so that this memory can be used as-is when deserialized
  508. string16Table.list = string16Table.list->Prepend(stringEntry, alloc);
  509. if (string16IndexTable.list == nullptr)
  510. {
  511. // First item in the list is the first string.
  512. auto stringIndexEntry = Anew(alloc, BufferBuilderRelativeOffset, L"First String16 Index", stringEntry);
  513. string16IndexTable.list = string16IndexTable.list->Prepend(stringIndexEntry, alloc);
  514. PrependByte(string16IndexTable, L"isPropertyRecord", (BYTE)isPropertyRecord);
  515. }
  516. // Get a pointer to the previous entry of isPropertyRecord
  517. indexEntry.isPropertyRecord = static_cast<BufferBuilderByte*>(string16IndexTable.list->First());
  518. // Subsequent strings indexes point one past the end. This way, the size is always computable by subtracting indexes.
  519. auto stringIndexEntry = Anew(alloc, BufferBuilderRelativeOffset, L"String16 Index", stringEntry, sizeInBytes);
  520. string16IndexTable.list = string16IndexTable.list->Prepend(stringIndexEntry, alloc);
  521. // By default, mark the next string to be not a property record.
  522. PrependByte(string16IndexTable, L"isPropertyRecord", (BYTE)false);
  523. indexEntry.id = nextString16Id;
  524. string16ToId->Add(bb, indexEntry);
  525. ++nextString16Id;
  526. }
  527. // A string might start off as not being a property record and later becoming one. Hence,
  528. // we set only if the transition is from false => true. Once it is a property record, it cannot go back.
  529. if(isPropertyRecord)
  530. {
  531. indexEntry.isPropertyRecord->value = isPropertyRecord;
  532. }
  533. return indexEntry.id;
  534. }
  535. uint32 PrependRelativeOffset(BufferBuilderList & builder, LPCWSTR clue, BufferBuilder * pointedTo)
  536. {
  537. auto entry = Anew(alloc, BufferBuilderRelativeOffset, clue, pointedTo, 0);
  538. builder.list = builder.list->Prepend(entry, alloc);
  539. return sizeof(int32);
  540. }
  541. uint32 PrependInt16(BufferBuilderList & builder, LPCWSTR clue, int16 value, BufferBuilderInt16 ** entryOut = nullptr)
  542. {
  543. auto entry = Anew(alloc, BufferBuilderInt16, clue, value);
  544. builder.list = builder.list->Prepend(entry, alloc);
  545. if (entryOut)
  546. {
  547. *entryOut = entry;
  548. }
  549. return sizeof(int16);
  550. }
  551. uint32 PrependInt32(BufferBuilderList & builder, LPCWSTR clue, int value, BufferBuilderInt32 ** entryOut = nullptr)
  552. {
  553. auto entry = Anew(alloc, BufferBuilderInt32, clue, value);
  554. builder.list = builder.list->Prepend(entry, alloc);
  555. if (entryOut)
  556. {
  557. *entryOut = entry;
  558. }
  559. return sizeof(int32);
  560. }
  561. uint32 PrependConstantInt16(BufferBuilderList & builder, LPCWSTR clue, int16 value, ConstantSizedBufferBuilderOf<int16> ** entryOut = nullptr)
  562. {
  563. auto entry = Anew(alloc, ConstantSizedBufferBuilderOf<int16>, clue, value);
  564. builder.list = builder.list->Prepend(entry, alloc);
  565. if (entryOut)
  566. {
  567. *entryOut = entry;
  568. }
  569. return sizeof(int16);
  570. }
  571. uint32 PrependConstantInt32(BufferBuilderList & builder, LPCWSTR clue, int value, ConstantSizedBufferBuilderOf<int> ** entryOut = nullptr)
  572. {
  573. auto entry = Anew(alloc, ConstantSizedBufferBuilderOf<int>, clue, value);
  574. builder.list = builder.list->Prepend(entry, alloc);
  575. if (entryOut)
  576. {
  577. *entryOut = entry;
  578. }
  579. return sizeof(int32);
  580. }
  581. uint32 PrependConstantInt64(BufferBuilderList & builder, LPCWSTR clue, int64 value, ConstantSizedBufferBuilderOf<int64> ** entryOut = nullptr)
  582. {
  583. auto entry = Anew(alloc, ConstantSizedBufferBuilderOf<int64>, clue, value);
  584. builder.list = builder.list->Prepend(entry, alloc);
  585. if (entryOut)
  586. {
  587. *entryOut = entry;
  588. }
  589. return sizeof(int64);
  590. }
  591. uint32 PrependByte(BufferBuilderList & builder, LPCWSTR clue, byte value)
  592. {
  593. auto entry = Anew(alloc, BufferBuilderByte, clue, value);
  594. builder.list = builder.list->Prepend(entry, alloc);
  595. return sizeof(byte);
  596. }
  597. uint32 PrependFunctionBodyFlags(BufferBuilderList & builder, LPCWSTR clue, FunctionBody::FunctionBodyFlags value)
  598. {
  599. return PrependByte(builder, clue, (byte) value);
  600. }
  601. uint32 PrependBool(BufferBuilderList & builder, LPCWSTR clue, bool value)
  602. {
  603. return PrependByte(builder, clue, (byte) value);
  604. }
  605. uint32 PrependFloat(BufferBuilderList & builder, LPCWSTR clue, float value)
  606. {
  607. auto entry = Anew(alloc, BufferBuilderFloat, clue, value);
  608. builder.list = builder.list->Prepend(entry, alloc);
  609. return sizeof(float);
  610. }
  611. uint32 PrependDouble(BufferBuilderList & builder, LPCWSTR clue, double value)
  612. {
  613. auto entry = Anew(alloc, BufferBuilderDouble, clue, value);
  614. builder.list = builder.list->Prepend(entry, alloc);
  615. return sizeof(double);
  616. }
  617. uint32 PrependSIMDValue(BufferBuilderList & builder, LPCWSTR clue, SIMDValue value)
  618. {
  619. auto entry = Anew(alloc, BufferBuilderSIMD, clue, value);
  620. builder.list = builder.list->Prepend(entry, alloc);
  621. return sizeof(SIMDValue);
  622. }
  623. uint32 PrependString16(__in BufferBuilderList & builder, __in_nz LPCWSTR clue, __in_bcount_opt(byteLength) LPCWSTR sz, __in uint32 byteLength)
  624. {
  625. if (sz != nullptr)
  626. {
  627. auto bb = Anew(alloc, ByteBuffer, byteLength, (void*)sz); // Includes trailing null
  628. return PrependInt32(builder, clue, GetString16Id(bb));
  629. }
  630. else
  631. {
  632. return PrependInt32(builder, clue, 0xffffffff);
  633. }
  634. }
  635. uint32 PrependByteBuffer(BufferBuilderList & builder, LPCWSTR clue, ByteBuffer * bb)
  636. {
  637. auto id = GetString16Id(bb);
  638. return PrependInt32(builder, clue, id);
  639. }
  640. int GetIdOfPropertyRecord(const PropertyRecord * propertyRecord)
  641. {
  642. AssertMsg(!propertyRecord->IsSymbol(), "bytecode serializer does not currently handle non-built-in symbol PropertyRecords");
  643. size_t byteCount = ((size_t)propertyRecord->GetLength() + 1) * sizeof(wchar_t);
  644. if (byteCount > UINT_MAX)
  645. {
  646. // We should never see property record that big
  647. Js::Throw::InternalError();
  648. }
  649. auto buffer = propertyRecord->GetBuffer();
  650. #if DBG
  651. const PropertyRecord * propertyRecordCheck;
  652. scriptContext->FindPropertyRecord(buffer, propertyRecord->GetLength(), &propertyRecordCheck);
  653. Assert(propertyRecordCheck == propertyRecord);
  654. #endif
  655. auto bb = Anew(alloc, ByteBuffer, (uint32)byteCount, (void*)buffer);
  656. return GetString16Id(bb, /*isPropertyRecord=*/ true);
  657. }
  658. template<typename TLayout>
  659. unaligned TLayout * DuplicateLayout(unaligned const TLayout * in)
  660. {
  661. auto sizeOfLayout = sizeof(unaligned TLayout);
  662. auto newLayout = AnewArray(alloc, byte, sizeOfLayout);
  663. js_memcpy_s(newLayout, sizeOfLayout, in, sizeOfLayout);
  664. return (unaligned TLayout * )newLayout;
  665. }
  666. template<typename T>
  667. uint32 Prepend(BufferBuilderList & builder, LPCWSTR clue, T * t)
  668. {
  669. auto block = Anew(alloc, BufferBuilderRaw, clue, sizeof(serialization_alignment T), (const byte*)t);
  670. builder.list = builder.list->Prepend(block, alloc);
  671. return sizeof(serialization_alignment T);
  672. }
  673. struct AuxRecord
  674. {
  675. SerializedAuxiliaryKind kind;
  676. uint offset;
  677. };
  678. #ifndef TEMP_DISABLE_ASMJS
  679. HRESULT RewriteAsmJsByteCodesInto(BufferBuilderList & builder, LPCWSTR clue, FunctionBody * function, ByteBlock * byteBlock)
  680. {
  681. SListCounted<AuxRecord> auxRecords(alloc);
  682. Assert(!OmitFunction(function->GetSerializationIndex()));
  683. auto finalSize = Anew(alloc, BufferBuilderInt32, L"Final Byte Code Size", 0); // Initially set to zero
  684. builder.list = builder.list->Prepend(finalSize, alloc);
  685. ByteCodeReader reader;
  686. reader.Create(function);
  687. uint32 size = 0;
  688. const byte * opStart = nullptr;
  689. bool cantGenerate = false;
  690. auto saveBlock = [&]() {
  691. uint32 byteCount;
  692. if (TryConvertToUInt32(reader.GetIP() - opStart, &byteCount))
  693. {
  694. if (!GenerateByteCodeForNative(function->GetSerializationIndex()))
  695. {
  696. auto block = Anew(alloc, BufferBuilderRaw, clue, byteCount, (const byte*)opStart);
  697. builder.list = builder.list->Prepend(block, alloc);
  698. size += byteCount;
  699. }
  700. }
  701. else
  702. {
  703. AssertMsg(false, "Unlikely: byte code size overflows 32 bits");
  704. cantGenerate = true;
  705. }
  706. };
  707. Assert(!function->HasCachedScopePropIds());
  708. while (!cantGenerate)
  709. {
  710. opStart = reader.GetIP();
  711. opStart; // For prefast. It can't figure out that opStart is captured in saveBlock above.
  712. LayoutSize layoutSize;
  713. OpCodeAsmJs op = (OpCodeAsmJs)reader.ReadOp(layoutSize);
  714. if (op == OpCodeAsmJs::EndOfBlock)
  715. {
  716. saveBlock();
  717. break;
  718. }
  719. OpLayoutTypeAsmJs layoutType = OpCodeUtilAsmJs::GetOpCodeLayout(op);
  720. switch (layoutType)
  721. {
  722. #define DEFAULT_LAYOUT(op) \
  723. case OpLayoutTypeAsmJs::##op: { \
  724. Assert(layoutSize == SmallLayout); \
  725. reader.##op(); \
  726. saveBlock(); \
  727. break; }
  728. #define DEFAULT_LAYOUT_WITH_ONEBYTE(op) \
  729. case OpLayoutTypeAsmJs::##op: { \
  730. switch (layoutSize) \
  731. { \
  732. case SmallLayout: \
  733. reader.##op##_Small(); \
  734. break; \
  735. case MediumLayout: \
  736. reader.##op##_Medium(); \
  737. break; \
  738. case LargeLayout: \
  739. reader.##op##_Large(); \
  740. break; \
  741. default: \
  742. Assume(UNREACHED); \
  743. } \
  744. saveBlock(); \
  745. break; }
  746. DEFAULT_LAYOUT(Empty);
  747. DEFAULT_LAYOUT(StartCall);
  748. DEFAULT_LAYOUT_WITH_ONEBYTE(ElementSlot);
  749. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmTypedArr);
  750. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmCall);
  751. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmReg1);
  752. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmReg2);
  753. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmReg3);
  754. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmReg4);
  755. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmReg5);
  756. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmReg6);
  757. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmReg7);
  758. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmReg2IntConst1);
  759. DEFAULT_LAYOUT_WITH_ONEBYTE(Int1Double1);
  760. DEFAULT_LAYOUT_WITH_ONEBYTE(Int1Float1);
  761. DEFAULT_LAYOUT_WITH_ONEBYTE(Double1Int1);
  762. DEFAULT_LAYOUT_WITH_ONEBYTE(Double1Float1);
  763. DEFAULT_LAYOUT_WITH_ONEBYTE(Double1Reg1);
  764. DEFAULT_LAYOUT_WITH_ONEBYTE(Float1Reg1);
  765. DEFAULT_LAYOUT_WITH_ONEBYTE(Int1Reg1);
  766. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg1Double1);
  767. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg1Float1);
  768. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg1Int1);
  769. DEFAULT_LAYOUT_WITH_ONEBYTE(Int1Double2);
  770. DEFAULT_LAYOUT_WITH_ONEBYTE(Int1Float2);
  771. DEFAULT_LAYOUT_WITH_ONEBYTE(Int2);
  772. DEFAULT_LAYOUT_WITH_ONEBYTE(Int1Const1);
  773. DEFAULT_LAYOUT_WITH_ONEBYTE(Int3);
  774. DEFAULT_LAYOUT_WITH_ONEBYTE(Double2);
  775. DEFAULT_LAYOUT_WITH_ONEBYTE(Float2);
  776. DEFAULT_LAYOUT_WITH_ONEBYTE(Float3);
  777. DEFAULT_LAYOUT_WITH_ONEBYTE(Float1Double1);
  778. DEFAULT_LAYOUT_WITH_ONEBYTE(Float1Int1);
  779. DEFAULT_LAYOUT_WITH_ONEBYTE(Double3);
  780. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmUnsigned1);
  781. DEFAULT_LAYOUT(AsmBr);
  782. DEFAULT_LAYOUT_WITH_ONEBYTE(BrInt1);
  783. DEFAULT_LAYOUT_WITH_ONEBYTE(BrInt2);
  784. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_2);
  785. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_3);
  786. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_4);
  787. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_1Float4);
  788. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_2Int4);
  789. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_3Int4);
  790. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_1Float1);
  791. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_2Float1);
  792. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_1Float64x2_1);
  793. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_1Int32x4_1);
  794. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_1Int32x4_1Float32x4_2);
  795. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg1Float32x4_1);
  796. DEFAULT_LAYOUT_WITH_ONEBYTE(Int1Float32x4_1);
  797. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_2);
  798. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_3);
  799. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_4);
  800. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_1Int1);
  801. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_1Int4);
  802. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_2Int4);
  803. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_3Int4);
  804. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_2Int1);
  805. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_2Int2);
  806. DEFAULT_LAYOUT_WITH_ONEBYTE(Int1Int32x4_1Int1);
  807. DEFAULT_LAYOUT_WITH_ONEBYTE(Float32x4_2Int1Float1);
  808. DEFAULT_LAYOUT_WITH_ONEBYTE(Float1Float32x4_1Int1);
  809. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg1Int32x4_1);
  810. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_1Float64x2_1);
  811. DEFAULT_LAYOUT_WITH_ONEBYTE(Int32x4_1Float32x4_1);
  812. DEFAULT_LAYOUT_WITH_ONEBYTE(Int1Int32x4_1);
  813. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_2);
  814. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_3);
  815. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_4);
  816. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_1Double2);
  817. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_1Double1);
  818. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_2Double1);
  819. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_2Int2);
  820. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_3Int2);
  821. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_1Float32x4_1);
  822. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_1Int32x4_1);
  823. DEFAULT_LAYOUT_WITH_ONEBYTE(Float64x2_1Int32x4_1Float64x2_2);
  824. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg1Float64x2_1);
  825. DEFAULT_LAYOUT_WITH_ONEBYTE(Int1Float64x2_1);
  826. DEFAULT_LAYOUT_WITH_ONEBYTE(AsmSimdTypedArr);
  827. #undef DEFAULT_LAYOUT
  828. #undef DEFAULT_LAYOUT_WITH_ONEBYTE
  829. default:
  830. AssertMsg(false, "Unknown OpLayout");
  831. cantGenerate = true;
  832. break;
  833. }
  834. }
  835. if (cantGenerate)
  836. {
  837. return ByteCodeSerializer::CantGenerate;
  838. }
  839. if (size != byteBlock->GetLength() && !GenerateByteCodeForNative(function->GetSerializationIndex()))
  840. {
  841. Assert(size == byteBlock->GetLength());
  842. return ByteCodeSerializer::CantGenerate;
  843. }
  844. finalSize->value = size;
  845. RewriteAuxiliaryInto(builder, auxRecords, reader, function);
  846. return S_OK;
  847. }
  848. #endif
  849. HRESULT RewriteByteCodesInto(BufferBuilderList & builder, LPCWSTR clue, FunctionBody * function, ByteBlock * byteBlock)
  850. {
  851. SListCounted<AuxRecord> auxRecords(alloc);
  852. Assert(!OmitFunction(function->GetSerializationIndex()));
  853. auto finalSize = Anew(alloc, BufferBuilderInt32, L"Final Byte Code Size", 0); // Initially set to zero
  854. builder.list = builder.list->Prepend(finalSize, alloc);
  855. ByteCodeReader reader;
  856. reader.Create(function);
  857. uint32 size = 0;
  858. const byte * opStart = nullptr;
  859. bool cantGenerate = false;
  860. auto saveBlock = [&]() {
  861. uint32 byteCount;
  862. if (TryConvertToUInt32(reader.GetIP()-opStart, &byteCount))
  863. {
  864. if (!GenerateByteCodeForNative(function->GetSerializationIndex()))
  865. {
  866. auto block = Anew(alloc, BufferBuilderRaw, clue, byteCount, (const byte*) opStart);
  867. builder.list = builder.list->Prepend(block, alloc);
  868. size += byteCount;
  869. }
  870. }
  871. else
  872. {
  873. AssertMsg(false, "Unlikely: byte code size overflows 32 bits");
  874. cantGenerate = true;
  875. }
  876. };
  877. if (function->HasCachedScopePropIds())
  878. {
  879. AuxRecord record = { sakPropertyIdArrayForCachedScope, 0 };
  880. auxRecords.Prepend(record);
  881. }
  882. while(!cantGenerate)
  883. {
  884. opStart = reader.GetIP();
  885. opStart; // For prefast. It can't figure out that opStart is captured in saveBlock above.
  886. LayoutSize layoutSize;
  887. OpCode op = reader.ReadOp(layoutSize);
  888. if (op == OpCode::EndOfBlock)
  889. {
  890. saveBlock();
  891. break;
  892. }
  893. OpLayoutType layoutType = OpCodeUtil::GetOpCodeLayout(op);
  894. switch (layoutType)
  895. {
  896. #define DEFAULT_LAYOUT(op) \
  897. case OpLayoutType::##op: { \
  898. Assert(layoutSize == SmallLayout); \
  899. reader.##op(); \
  900. saveBlock(); \
  901. break; }
  902. #define DEFAULT_LAYOUT_WITH_ONEBYTE(op) \
  903. case OpLayoutType::##op: { \
  904. switch (layoutSize) \
  905. { \
  906. case SmallLayout: \
  907. reader.##op##_Small(); \
  908. break; \
  909. case MediumLayout: \
  910. reader.##op##_Medium(); \
  911. break; \
  912. case LargeLayout: \
  913. reader.##op##_Large(); \
  914. break; \
  915. default: \
  916. Assert(false); \
  917. __assume(false); \
  918. } \
  919. saveBlock(); \
  920. break; }
  921. #define DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(op) \
  922. DEFAULT_LAYOUT_WITH_ONEBYTE(op); \
  923. DEFAULT_LAYOUT_WITH_ONEBYTE(Profiled##op)
  924. DEFAULT_LAYOUT(Empty);
  925. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg1);
  926. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(Reg2);
  927. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(Reg2WithICIndex);
  928. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(Reg3);
  929. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg4);
  930. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg5);
  931. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg3C);
  932. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(Arg);
  933. DEFAULT_LAYOUT_WITH_ONEBYTE(ArgNoSrc);
  934. DEFAULT_LAYOUT(Br);
  935. #ifdef BYTECODE_BRANCH_ISLAND
  936. DEFAULT_LAYOUT(BrLong);
  937. #endif
  938. DEFAULT_LAYOUT(BrS);
  939. DEFAULT_LAYOUT_WITH_ONEBYTE(BrReg1);
  940. DEFAULT_LAYOUT_WITH_ONEBYTE(BrReg2);
  941. DEFAULT_LAYOUT(StartCall);
  942. DEFAULT_LAYOUT_WITH_ONEBYTE(Profiled2CallI);
  943. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(CallI);
  944. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(CallIFlags);
  945. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(CallIWithICIndex);
  946. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(CallIFlagsWithICIndex);
  947. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(ElementI);
  948. DEFAULT_LAYOUT_WITH_ONEBYTE(ElementUnsigned1);
  949. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(ElementSlot);
  950. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(ElementSlotI1);
  951. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(ElementSlotI2);
  952. DEFAULT_LAYOUT(W1);
  953. DEFAULT_LAYOUT(Reg1Int2);
  954. DEFAULT_LAYOUT_WITH_ONEBYTE_AND_PROFILED(Reg1Unsigned1);
  955. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg2Int1);
  956. DEFAULT_LAYOUT_WITH_ONEBYTE(Unsigned1);
  957. DEFAULT_LAYOUT_WITH_ONEBYTE(ElementCP);
  958. DEFAULT_LAYOUT_WITH_ONEBYTE(ElementRootCP);
  959. DEFAULT_LAYOUT_WITH_ONEBYTE(ElementP);
  960. DEFAULT_LAYOUT_WITH_ONEBYTE(ElementPIndexed);
  961. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg2B1);
  962. DEFAULT_LAYOUT_WITH_ONEBYTE(Reg3B1);
  963. DEFAULT_LAYOUT_WITH_ONEBYTE(Class);
  964. DEFAULT_LAYOUT_WITH_ONEBYTE(ElementU);
  965. DEFAULT_LAYOUT_WITH_ONEBYTE(ElementRootU);
  966. DEFAULT_LAYOUT(BrProperty);
  967. DEFAULT_LAYOUT(BrEnvProperty);
  968. DEFAULT_LAYOUT(BrLocalProperty);
  969. DEFAULT_LAYOUT_WITH_ONEBYTE(ElementC2);
  970. DEFAULT_LAYOUT_WITH_ONEBYTE(ElementC);
  971. #undef DEFAULT_LAYOUT
  972. #undef DEFAULT_LAYOUT_WITH_ONEBYTE
  973. case OpLayoutType::AuxNoReg:
  974. switch (op)
  975. {
  976. case OpCode::InitCachedFuncs:
  977. {
  978. auto layout = reader.AuxNoReg();
  979. AuxRecord record = { sakFuncInfoArray, layout->Offset };
  980. auxRecords.Prepend(record);
  981. saveBlock();
  982. break;
  983. }
  984. case OpCode::CommitScope:
  985. {
  986. // The propertyId array should be saved by the InitCacheScope
  987. auto layout = reader.AuxNoReg();
  988. Assert(layout);
  989. saveBlock();
  990. break;
  991. }
  992. default:
  993. AssertMsg(false, "Unknown OpCode for OpLayoutType::AuxNoReg");
  994. cantGenerate = true;
  995. break;
  996. }
  997. break;
  998. case OpLayoutType::Auxiliary:
  999. switch (op)
  1000. {
  1001. case OpCode::NewScObjectLiteral:
  1002. {
  1003. auto layout = reader.Auxiliary();
  1004. AuxRecord record = { sakPropertyIdArray, layout->Offset };
  1005. auxRecords.Prepend(record);
  1006. saveBlock();
  1007. break;
  1008. }
  1009. case OpCode::LdPropIds:
  1010. {
  1011. auto layout = reader.Auxiliary();
  1012. AuxRecord record = { sakPropertyIdArray, layout->Offset };
  1013. auxRecords.Prepend(record);
  1014. saveBlock();
  1015. break;
  1016. }
  1017. case OpCode::StArrSegItem_A:
  1018. {
  1019. auto layout = reader.Auxiliary();
  1020. AuxRecord record = { sakVarArrayIntCount, layout->Offset };
  1021. auxRecords.Prepend(record);
  1022. saveBlock();
  1023. break;
  1024. }
  1025. case OpCode::NewScObject_A:
  1026. {
  1027. auto layout = reader.Auxiliary();
  1028. AuxRecord record = { sakVarArrayVarCount, layout->Offset };
  1029. auxRecords.Prepend(record);
  1030. saveBlock();
  1031. break;
  1032. }
  1033. case OpCode::NewScIntArray:
  1034. {
  1035. auto layout = reader.Auxiliary();
  1036. AuxRecord record = { sakIntArray, layout->Offset };
  1037. auxRecords.Prepend(record);
  1038. saveBlock();
  1039. break;
  1040. }
  1041. case OpCode::NewScFltArray:
  1042. {
  1043. auto layout = reader.Auxiliary();
  1044. AuxRecord record = { sakFloatArray, layout->Offset };
  1045. auxRecords.Prepend(record);
  1046. saveBlock();
  1047. break;
  1048. }
  1049. default:
  1050. AssertMsg(false, "Unknown OpCode for OpLayoutType::Auxiliary");
  1051. cantGenerate = true;
  1052. break;
  1053. }
  1054. break;
  1055. case OpLayoutType::ProfiledAuxiliary:
  1056. switch (op)
  1057. {
  1058. case OpCode::ProfiledNewScIntArray:
  1059. {
  1060. auto layout = reader.ProfiledAuxiliary();
  1061. AuxRecord record = { sakIntArray, layout->Offset };
  1062. auxRecords.Prepend(record);
  1063. saveBlock();
  1064. break;
  1065. }
  1066. case OpCode::ProfiledNewScFltArray:
  1067. {
  1068. auto layout = reader.ProfiledAuxiliary();
  1069. AuxRecord record = { sakFloatArray, layout->Offset };
  1070. auxRecords.Prepend(record);
  1071. saveBlock();
  1072. break;
  1073. }
  1074. default:
  1075. AssertMsg(false, "Unknown OpCode for OpLayoutType::ProfiledAuxiliary");
  1076. cantGenerate = true;
  1077. break;
  1078. }
  1079. break;
  1080. case OpLayoutType::Reg2Aux:
  1081. switch (op)
  1082. {
  1083. case OpCode::SpreadArrayLiteral:
  1084. {
  1085. auto layout = reader.Reg2Aux();
  1086. AuxRecord record = { sakIntArray, layout->Offset };
  1087. auxRecords.Prepend(record);
  1088. saveBlock();
  1089. break;
  1090. }
  1091. default:
  1092. AssertMsg(false, "Unknown OpCode for OpLayoutType::Reg2Aux");
  1093. cantGenerate = true;
  1094. break;
  1095. }
  1096. break;
  1097. #define STORE_SPREAD_AUX_ARGS \
  1098. if (!(layout->Options & CallIExtended_SpreadArgs)) \
  1099. { \
  1100. break; \
  1101. } \
  1102. AuxRecord record = { sakIntArray, layout->SpreadAuxOffset }; \
  1103. auxRecords.Prepend(record)
  1104. #define CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(op) \
  1105. case OpLayoutType::##op: \
  1106. { \
  1107. switch (layoutSize) \
  1108. { \
  1109. case SmallLayout: \
  1110. { \
  1111. auto layout = reader.##op##_Small(); \
  1112. STORE_SPREAD_AUX_ARGS; \
  1113. break; \
  1114. } \
  1115. case MediumLayout: \
  1116. { \
  1117. auto layout = reader.##op##_Medium(); \
  1118. STORE_SPREAD_AUX_ARGS; \
  1119. break; \
  1120. } \
  1121. case LargeLayout: \
  1122. { \
  1123. auto layout = reader.##op##_Large(); \
  1124. STORE_SPREAD_AUX_ARGS; \
  1125. break; \
  1126. } \
  1127. default: \
  1128. Assert(false); \
  1129. __assume(false); \
  1130. } \
  1131. saveBlock(); \
  1132. break; \
  1133. }
  1134. CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(CallIExtended)
  1135. CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(CallIExtendedFlags)
  1136. CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(ProfiledCallIExtended)
  1137. CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(ProfiledCallIExtendedFlags)
  1138. CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(Profiled2CallIExtended)
  1139. CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(ProfiledCallIExtendedWithICIndex)
  1140. CALLIEXTENDED_LAYOUT_WITH_ONEBYTE(ProfiledCallIExtendedFlagsWithICIndex)
  1141. default:
  1142. AssertMsg(false, "Unknown OpLayout");
  1143. cantGenerate = true;
  1144. break;
  1145. }
  1146. }
  1147. if (cantGenerate)
  1148. {
  1149. return ByteCodeSerializer::CantGenerate;
  1150. }
  1151. if (size != byteBlock->GetLength() && !GenerateByteCodeForNative(function->GetSerializationIndex()))
  1152. {
  1153. Assert(size == byteBlock->GetLength());
  1154. return ByteCodeSerializer::CantGenerate;
  1155. }
  1156. finalSize->value = size;
  1157. RewriteAuxiliaryInto(builder, auxRecords, reader, function);
  1158. return S_OK;
  1159. }
  1160. void RewriteAuxiliaryInto(BufferBuilderList& builder, SListCounted<AuxRecord> const& auxRecordList,
  1161. ByteCodeReader& reader, FunctionBody * functionBody)
  1162. {
  1163. uint count = auxRecordList.Count();
  1164. PrependInt32(builder, L"Auxiliary Structure Count", count);
  1165. if (count == 0)
  1166. {
  1167. return;
  1168. }
  1169. auto writeAuxVarArray = [&](uint offset, bool isVarCount, int count, const Var * elements) {
  1170. typedef serialization_alignment SerializedVarArray T;
  1171. T header(offset, isVarCount, count);
  1172. auto block = Anew(alloc, ConstantSizedBufferBuilderOf<T>, L"Var Array", header);
  1173. builder.list = builder.list->Prepend(block, alloc);
  1174. for (int i=0;i<count; i++)
  1175. {
  1176. auto var = elements[i];
  1177. PrependVarConstant(builder, var);
  1178. }
  1179. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1180. PrependInt32(builder, L"Magic end of aux var array", magicEndOfAuxVarArray);
  1181. PrependInt32(builder, L"Magic end of aux", magicEndOfAux);
  1182. #endif
  1183. };
  1184. auto writeAuxVarArrayIntCount = [&](uint offset) {
  1185. const AuxArray<Var> * varArray = reader.ReadAuxArray<Var>(offset, functionBody);
  1186. int count = varArray->count;
  1187. const Var * elements = varArray->elements;
  1188. writeAuxVarArray(offset, false, count, elements);
  1189. };
  1190. auto writeAuxVarArrayVarCount = [&](uint offset) {
  1191. const VarArrayVarCount * varArray = reader.ReadVarArrayVarCount(offset, functionBody);
  1192. int count = Js::TaggedInt::ToInt32(varArray->count);
  1193. const Var * elements = varArray->elements;
  1194. writeAuxVarArray(offset, true, count, elements);
  1195. };
  1196. auto writeAuxIntArray = [&](uint offset) -> BufferBuilder* {
  1197. const AuxArray<int32> *ints = reader.ReadAuxArray<int32>(offset, functionBody);
  1198. int count = ints->count;
  1199. const int32 * elements = ints->elements;
  1200. typedef serialization_alignment SerializedIntArray T;
  1201. T header(offset, count);
  1202. auto block = Anew(alloc, ConstantSizedBufferBuilderOf<T>, L"Int Array", header);
  1203. builder.list = builder.list->Prepend(block, alloc);
  1204. for (int i=0;i<count; i++)
  1205. {
  1206. auto value = elements[i];
  1207. PrependConstantInt32(builder, L"Integer Constant Value", value);
  1208. }
  1209. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1210. PrependInt32(builder, L"Magic end of aux int array", magicEndOfAuxIntArray);
  1211. PrependInt32(builder, L"Magic end of aux", magicEndOfAux);
  1212. #endif
  1213. return block;
  1214. };
  1215. auto writeAuxFloatArray = [&](uint offset) -> BufferBuilder* {
  1216. const AuxArray<double> *doubles = reader.ReadAuxArray<double>(offset, functionBody);
  1217. int count = doubles->count;
  1218. const double * elements = doubles->elements;
  1219. typedef serialization_alignment SerializedFloatArray T;
  1220. T header(offset, count);
  1221. auto block = Anew(alloc, ConstantSizedBufferBuilderOf<T>, L"Float Array", header);
  1222. builder.list = builder.list->Prepend(block, alloc);
  1223. for (int i=0;i<count; i++)
  1224. {
  1225. auto value = elements[i];
  1226. PrependDouble(builder, L"Number Constant Value", value);
  1227. }
  1228. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1229. PrependInt32(builder, L"Magic end of aux float array", magicEndOfAuxFltArray);
  1230. PrependInt32(builder, L"Magic end of aux", magicEndOfAux);
  1231. #endif
  1232. return block;
  1233. };
  1234. auto writeAuxPropertyIdArray = [&](uint offset, uint32 extraSlots) -> BufferBuilder* {
  1235. const PropertyIdArray * propIds = reader.ReadPropertyIdArray(offset, functionBody, extraSlots);
  1236. typedef serialization_alignment SerializedPropertyIdArray T;
  1237. T header(offset, propIds->count, extraSlots, propIds->hadDuplicates, propIds->has__proto__);
  1238. auto block = Anew(alloc, ConstantSizedBufferBuilderOf<T>, L"Property Id Array", header);
  1239. builder.list = builder.list->Prepend(block, alloc);
  1240. for (uint32 i=0; i<propIds->count; i++)
  1241. {
  1242. auto original = propIds->elements[i];
  1243. auto encoded = encodePossiblyBuiltInPropertyId(original);
  1244. PrependConstantInt32(builder, L"Encoded Property Id", encoded);
  1245. }
  1246. auto slots = propIds->elements + propIds->count;
  1247. for(uint32 i=0; i<extraSlots; i++)
  1248. {
  1249. PrependConstantInt32(builder, L"Extra Slot", slots[i]);
  1250. }
  1251. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1252. PrependInt32(builder, L"Magic end of aux section", magicEndOfAuxPropIdArray);
  1253. PrependInt32(builder, L"Magic end of aux", magicEndOfAux);
  1254. #endif
  1255. return block;
  1256. };
  1257. auto writeAuxFuncInfoArray = [&](uint offset) -> BufferBuilder* {
  1258. const FuncInfoArray * funcInfos = reader.ReadAuxArray<FuncInfoEntry>(offset, functionBody);
  1259. typedef serialization_alignment SerializedFuncInfoArray T;
  1260. T header(offset, funcInfos->count);
  1261. auto block = Anew(alloc, ConstantSizedBufferBuilderOf<T>, L"Funcinfo Array", header);
  1262. builder.list = builder.list->Prepend(block, alloc);
  1263. for (uint32 i=0; i<funcInfos->count; i++)
  1264. {
  1265. auto funcInfo = funcInfos->elements[i];
  1266. PrependConstantInt32(builder, L"FuncInfo nestedIndex", funcInfo.nestedIndex);
  1267. PrependConstantInt32(builder, L"FuncInfo scopeSlot", funcInfo.scopeSlot);
  1268. }
  1269. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1270. PrependInt32(builder, L"Magic end of aux section", magicEndOfAuxFuncInfoArray);
  1271. PrependInt32(builder, L"Magic end of aux", magicEndOfAux);
  1272. #endif
  1273. return block;
  1274. };
  1275. PrependInt32(builder, L"Auxiliary Size",
  1276. functionBody->GetAuxiliaryData()? functionBody->GetAuxiliaryData()->GetLength() : 0);
  1277. PrependInt32(builder, L"Auxiliary Context Size",
  1278. functionBody->GetAuxiliaryContextData()? functionBody->GetAuxiliaryContextData()->GetLength() : 0);
  1279. auxRecordList.Map([&](AuxRecord const& auxRecord)
  1280. {
  1281. switch (auxRecord.kind)
  1282. {
  1283. default:
  1284. AssertMsg(false, "Unexpected auxiliary kind");
  1285. Throw::FatalInternalError();
  1286. break;
  1287. case sakVarArrayIntCount:
  1288. writeAuxVarArrayIntCount(auxRecord.offset);
  1289. break;
  1290. case sakVarArrayVarCount:
  1291. writeAuxVarArrayVarCount(auxRecord.offset);
  1292. break;
  1293. case sakIntArray:
  1294. writeAuxIntArray(auxRecord.offset);
  1295. break;
  1296. case sakFloatArray:
  1297. writeAuxFloatArray(auxRecord.offset);
  1298. break;
  1299. case sakPropertyIdArray:
  1300. writeAuxPropertyIdArray(auxRecord.offset, 0);
  1301. break;
  1302. case sakPropertyIdArrayForCachedScope:
  1303. writeAuxPropertyIdArray(auxRecord.offset, ActivationObjectEx::ExtraSlotCount());
  1304. break;
  1305. case sakFuncInfoArray:
  1306. writeAuxFuncInfoArray(auxRecord.offset);
  1307. break;
  1308. };
  1309. });
  1310. }
  1311. uint32 PrependStringConstant(BufferBuilderList & builder, Var var)
  1312. {
  1313. auto str = JavascriptString::FromVar(var);
  1314. uint32 size = 0;
  1315. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1316. size += PrependInt32(builder, L"Start String Constant", magicStartStringConstant);
  1317. #endif
  1318. auto bb = Anew(alloc, ByteBuffer, (str->GetLength() + 1) * sizeof(wchar_t), (void*)str->GetSz());
  1319. size += PrependByteBuffer(builder, L"String Constant 16 Value", bb);
  1320. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1321. size += PrependInt32(builder, L"End String Constant", magicEndStringConstant);
  1322. #endif
  1323. return size;
  1324. }
  1325. uint32 PrependStringTemplateCallsiteConstant(BufferBuilderList & builder, Var var)
  1326. {
  1327. ES5Array* callsite = ES5Array::FromVar(var);
  1328. Var element = nullptr;
  1329. auto size = PrependInt32(builder, L"String Template Callsite Constant String Count", (int)callsite->GetLength());
  1330. for (uint32 i = 0; i < callsite->GetLength(); i++)
  1331. {
  1332. callsite->DirectGetItemAt(i, &element);
  1333. size += PrependStringConstant(builder, element);
  1334. }
  1335. Var rawVar = JavascriptOperators::OP_GetProperty(callsite, Js::PropertyIds::raw, callsite->GetScriptContext());
  1336. ES5Array* rawArray = ES5Array::FromVar(rawVar);
  1337. for (uint32 i = 0; i < rawArray->GetLength(); i++)
  1338. {
  1339. rawArray->DirectGetItemAt(i, &element);
  1340. size += PrependStringConstant(builder, element);
  1341. }
  1342. return size;
  1343. }
  1344. uint32 PrependVarConstant(BufferBuilderList & builder, Var var)
  1345. {
  1346. if (var == (Js::Var)&Js::NullFrameDisplay)
  1347. {
  1348. return PrependByte(builder, L"Null Frame Display", ctNullDisplay);
  1349. }
  1350. else if (var == (Js::Var)&Js::StrictNullFrameDisplay)
  1351. {
  1352. return PrependByte(builder, L"Strict Null Frame Display", ctStrictNullDisplay);
  1353. }
  1354. auto typeId = JavascriptOperators::GetTypeId(var);
  1355. switch (typeId)
  1356. {
  1357. case TypeIds_Undefined:
  1358. return PrependByte(builder, L"Undefined Constant", ctUndefined);
  1359. case TypeIds_Null:
  1360. return PrependByte(builder, L"Null Constant", ctNull);
  1361. case TypeIds_Boolean:
  1362. return PrependByte(builder, L"Boolean Constant", JavascriptBoolean::FromVar(var)->GetValue()? ctTrue : ctFalse);
  1363. case TypeIds_Number:
  1364. {
  1365. auto size = PrependByte(builder, L"Number Constant", ctNumber);
  1366. return size + PrependDouble(builder, L"Number Constant Value", JavascriptNumber::GetValue(var));
  1367. }
  1368. case TypeIds_Integer:
  1369. {
  1370. auto size = PrependByte(builder, L"Integer Constant", ctInt);
  1371. return size + PrependConstantInt32(builder, L"Integer Constant Value", TaggedInt::ToInt32(var));
  1372. }
  1373. case TypeIds_String:
  1374. {
  1375. auto size = PrependByte(builder, L"String Constant 16", ctString16);
  1376. return size + PrependStringConstant(builder, var);
  1377. }
  1378. case TypeIds_ES5Array:
  1379. {
  1380. // ES5Array objects in the constant table are always string template callsite objects.
  1381. // If we later put other ES5Array objects in the constant table, we'll need another way
  1382. // to decide the constant type.
  1383. auto size = PrependByte(builder, L"String Template Callsite Constant", ctStringTemplateCallsite);
  1384. return size + PrependStringTemplateCallsiteConstant(builder, var);
  1385. }
  1386. default:
  1387. AssertMsg(UNREACHED, "Unexpected object type in AddConstantTable");
  1388. Throw::FatalInternalError();
  1389. }
  1390. }
  1391. #ifndef TEMP_DISABLE_ASMJS
  1392. uint32 AddAsmJsConstantTable(BufferBuilderList & builder, FunctionBody * function)
  1393. {
  1394. uint32 size = 0;
  1395. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1396. size += PrependInt32(builder, L"Start Constant Table", magicStartOfConstantTable);
  1397. #endif
  1398. uint32 intConstCount = function->GetAsmJsFunctionInfo()->GetIntConstCount();
  1399. uint32 floatConstCount = function->GetAsmJsFunctionInfo()->GetFloatConstCount();
  1400. uint32 doubleConstCount = function->GetAsmJsFunctionInfo()->GetDoubleConstCount();
  1401. Js::Var * constTable = static_cast<Js::Var *>(function->GetConstTable());
  1402. int * intConstTable = reinterpret_cast<int *>(constTable + Js::AsmJsFunctionMemory::RequiredVarConstants - 1);
  1403. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < intConstCount; ++reg)
  1404. {
  1405. PrependConstantInt32(builder, L"Integer Constant Value", intConstTable[reg]);
  1406. }
  1407. float * floatConstTable = reinterpret_cast<float *>(intConstTable + intConstCount);
  1408. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < floatConstCount; ++reg)
  1409. {
  1410. PrependFloat(builder, L"Float Constant Value", floatConstTable[reg]);
  1411. }
  1412. double * doubleConstTable = reinterpret_cast<double *>(floatConstTable + floatConstCount);
  1413. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < doubleConstCount; ++reg)
  1414. {
  1415. PrependDouble(builder, L"Double Constant Value", doubleConstTable[reg]);
  1416. }
  1417. uint32 simdConstCount = function->GetAsmJsFunctionInfo()->GetSimdConstCount();
  1418. AsmJsSIMDValue *simdConstTable = reinterpret_cast<AsmJsSIMDValue *>(doubleConstTable + doubleConstCount);
  1419. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < simdConstCount; ++reg)
  1420. {
  1421. PrependSIMDValue(builder, L"SIMD Constant Value", simdConstTable[reg]);
  1422. }
  1423. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1424. size += PrependInt32(builder, L"End Constant Table", magicEndOfConstantTable);
  1425. #endif
  1426. return size;
  1427. }
  1428. #endif
  1429. uint32 AddConstantTable(BufferBuilderList & builder, FunctionBody * function)
  1430. {
  1431. uint32 size = 0;
  1432. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1433. size += PrependInt32(builder, L"Start Constant Table", magicStartOfConstantTable);
  1434. #endif
  1435. for (auto reg = FunctionBody::FirstRegSlot + 1; reg < function->m_constCount; reg++) // Ignore first slot, it is always global object or module root object
  1436. {
  1437. auto var = function->GetConstantVar(reg);
  1438. Assert(var != nullptr);
  1439. size += PrependVarConstant(builder, var);
  1440. }
  1441. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1442. size += PrependInt32(builder, L"End Constant Table", magicEndOfConstantTable);
  1443. #endif
  1444. return size;
  1445. }
  1446. uint32 AddPropertyIdsForScopeSlotArray(BufferBuilderList & builder, FunctionBody * function)
  1447. {
  1448. if (function->scopeSlotArraySize == 0)
  1449. {
  1450. return 0;
  1451. }
  1452. uint32 size = 0;
  1453. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1454. size += PrependInt32(builder, L"Start PropertyIdsForScopeSlotsArray", magicStartOfPropertyIdsForScopeSlotArray);
  1455. #endif
  1456. for (uint i = 0; i < function->scopeSlotArraySize; i++)
  1457. {
  1458. PropertyId propertyId = encodePossiblyBuiltInPropertyId(function->propertyIdsForScopeSlotArray[i]);
  1459. size += PrependInt32(builder, L"PropertyIdsForScopeSlots", propertyId);
  1460. }
  1461. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1462. size += PrependInt32(builder, L"End PropertyIdsForScopeSlotsArray", magicEndOfPropertyIdsForScopeSlotArray);
  1463. #endif
  1464. return size;
  1465. }
  1466. // Gets the number of debugger slot array scopes there are in the function body's scope chain list.
  1467. uint32 GetDebuggerScopeSlotArrayCount(FunctionBody * function)
  1468. {
  1469. Assert(function);
  1470. uint debuggerScopeSlotArraySize = 0;
  1471. if (function->GetScopeObjectChain())
  1472. {
  1473. debuggerScopeSlotArraySize = function->GetScopeObjectChain()->pScopeChain->CountWhere([&](DebuggerScope* scope)
  1474. {
  1475. return scope->IsSlotScope();
  1476. });
  1477. }
  1478. return debuggerScopeSlotArraySize;
  1479. }
  1480. // Adds the debugger scopes that are slot array type to the serialized bytecode.
  1481. // This is to ensure that block scope slot array properties are captured along with
  1482. // function level slot array properties.
  1483. uint32 AddSlotArrayDebuggerScopeProperties(BufferBuilderList & builder, DebuggerScope* debuggerScope, uint propertiesCount)
  1484. {
  1485. Assert(debuggerScope);
  1486. if (propertiesCount == 0)
  1487. {
  1488. return 0u;
  1489. }
  1490. uint32 size = 0u;
  1491. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1492. size += PrependInt32(builder, L"Start SlotArrayDebuggerScopeProperties", magicStartOfDebuggerScopeProperties);
  1493. #endif // BYTE_CODE_MAGIC_CONSTANTS
  1494. AssertMsg(debuggerScope->HasProperties(), "Properties should exist.");
  1495. Assert(debuggerScope->scopeProperties->Count() >= 0);
  1496. AssertMsg((uint)debuggerScope->scopeProperties->Count() == propertiesCount, "Property counts should match.");
  1497. for (uint i = 0u; i < propertiesCount; ++i)
  1498. {
  1499. DebuggerScopeProperty scopeProperty = debuggerScope->scopeProperties->Item(i);
  1500. size += PrependInt32(builder, L"SlotIndexesForDebuggerScopeSlots", scopeProperty.location);
  1501. PropertyId propertyId = encodePossiblyBuiltInPropertyId(scopeProperty.propId);
  1502. size += PrependInt32(builder, L"PropertyIdsForDebuggerScopeSlots", propertyId);
  1503. }
  1504. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1505. size += PrependInt32(builder, L"End SlotArrayDebuggerScopeProperties", magicEndOfDebuggerScopeProperties);
  1506. #endif // BYTE_CODE_MAGIC_CONSTANTS
  1507. return size;
  1508. }
  1509. // Adds the debugger scopes that are slot array type to the serialized bytecode.
  1510. // This is to ensure that block scope slot array properties are captured along with
  1511. // function level slot array properties.
  1512. uint32 AddSlotArrayDebuggerScopes(BufferBuilderList & builder, FunctionBody* function, uint debuggerScopeSlotArraySize)
  1513. {
  1514. Assert(function);
  1515. if (function->GetScopeObjectChain() == nullptr || debuggerScopeSlotArraySize == 0)
  1516. {
  1517. return 0u;
  1518. }
  1519. uint32 size = 0u;
  1520. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1521. size += PrependInt32(builder, L"Start SlotArrayDebuggerScopes", magicStartOfDebuggerScopes);
  1522. #endif // BYTE_CODE_MAGIC_CONSTANTS
  1523. uint slotArrayCount = 0;
  1524. for (uint i = 0u; i < static_cast<uint>(function->GetScopeObjectChain()->pScopeChain->Count()); ++i)
  1525. {
  1526. DebuggerScope* debuggerScope = function->GetScopeObjectChain()->pScopeChain->Item(i);
  1527. if (debuggerScope->IsSlotScope())
  1528. {
  1529. // Only add slot scope debugger scopes (store the index of the scope).
  1530. size += PrependInt32(builder, L"SlotArrayDebuggerScope", i);
  1531. // Store the count of properties for the scope.
  1532. int propertiesCount = debuggerScope->HasProperties() ? debuggerScope->scopeProperties->Count() : 0u;
  1533. size += PrependInt32(builder, L"Debugger Scope Slot Array Property Count", propertiesCount);
  1534. size += AddSlotArrayDebuggerScopeProperties(builder, debuggerScope, propertiesCount);
  1535. slotArrayCount++;
  1536. }
  1537. }
  1538. Assert(debuggerScopeSlotArraySize == slotArrayCount);
  1539. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1540. size += PrependInt32(builder, L"End SlotArrayDebuggerScopes", magicEndOfDebuggerScopes);
  1541. #endif // BYTE_CODE_MAGIC_CONSTANTS
  1542. return size;
  1543. }
  1544. uint32 AddCacheIdToPropertyIdMap(BufferBuilderList & builder, FunctionBody * function)
  1545. {
  1546. uint count = function->GetInlineCacheCount();
  1547. if (count == 0)
  1548. {
  1549. return 0;
  1550. }
  1551. uint32 size = 0;
  1552. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1553. PrependInt32(builder, L"Start CacheId-to-PropertyId map", magicStartOfCacheIdToPropIdMap);
  1554. #endif
  1555. for (uint i = 0; i < count; i++)
  1556. {
  1557. PropertyId propertyId = encodePossiblyBuiltInPropertyId(function->GetPropertyIdFromCacheId(i));
  1558. size += PrependInt32(builder, L"CacheIdToPropertyId", propertyId);
  1559. }
  1560. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1561. size += PrependInt32(builder, L"End CacheId-to-PropertyId map", magicEndOfCacheIdToPropIdMap);
  1562. #endif
  1563. return size;
  1564. }
  1565. uint32 AddReferencedPropertyIdMap(BufferBuilderList & builder, FunctionBody * function)
  1566. {
  1567. uint count = function->GetReferencedPropertyIdCount();
  1568. if (count == 0)
  1569. {
  1570. return 0;
  1571. }
  1572. uint32 size = 0;
  1573. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1574. PrependInt32(builder, L"Start Referenced-PropertyId map", magicStartOfReferencedPropIdMap);
  1575. #endif
  1576. for (uint i = 0; i < count; i++)
  1577. {
  1578. PropertyId propertyId = encodeNonBuiltinPropertyId(function->GetReferencedPropertyIdWithMapIndex(i));
  1579. size += PrependInt32(builder, L"ReferencedPropertyId", propertyId);
  1580. }
  1581. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1582. size += PrependInt32(builder, L"End Referenced-PropertyId map", magicEndOfReferencedPropIdMap);
  1583. #endif
  1584. return size;
  1585. }
  1586. uint32 PrependByteArray(BufferBuilderList & builder, int length, byte * buffer)
  1587. {
  1588. int size = 0;
  1589. for (int i = 0; i<length; ++i)
  1590. {
  1591. size += PrependByte(builder, L"Byte Array Element", buffer[i]);
  1592. }
  1593. return size;
  1594. }
  1595. uint32 PrependUInt32Array(BufferBuilderList & builder, int length, uint32 * buffer)
  1596. {
  1597. int size = 0;
  1598. for(int i=0;i<length;++i)
  1599. {
  1600. size += PrependConstantInt32(builder, L"UInt32 Array Element", buffer[i]);
  1601. }
  1602. return size;
  1603. }
  1604. uint32 PrependGrowingUint32Array(BufferBuilderList & builder, LPCWSTR clue, JsUtil::GrowingUint32HeapArray * arr)
  1605. {
  1606. if (arr == nullptr || arr->Count() == 0 || arr->GetLength() == 0 || arr->GetBuffer() == nullptr)
  1607. {
  1608. return PrependInt32(builder, clue, 0);
  1609. }
  1610. auto size = PrependInt32(builder, clue, arr->Count());
  1611. size += PrependUInt32Array(builder, arr->Count(), arr->GetBuffer());
  1612. return size;
  1613. }
  1614. uint32 PrependSmallSpanSequence(BufferBuilderList & builder, LPCWSTR clue, SmallSpanSequence * spanSequence)
  1615. {
  1616. auto size = PrependInt32(builder, clue, spanSequence->baseValue);
  1617. size += PrependGrowingUint32Array(builder, L"Statement Buffer", spanSequence->pStatementBuffer);
  1618. size += PrependGrowingUint32Array(builder, L"Actual Offset List", spanSequence->pActualOffsetList);
  1619. return size;
  1620. }
  1621. template <typename TStructType>
  1622. uint32 PrependStruct(BufferBuilderList & builder, LPWSTR clue, TStructType * value)
  1623. {
  1624. auto entry = Anew(alloc, ConstantSizedBufferBuilderOf<TStructType>, clue, *value);
  1625. builder.list = builder.list->Prepend(entry, alloc);
  1626. return sizeof(serialization_alignment TStructType);
  1627. }
  1628. #ifndef TEMP_DISABLE_ASMJS
  1629. uint32 AddAsmJsFunctionInfo(BufferBuilderList & builder, FunctionBody * function)
  1630. {
  1631. uint32 size = 0;
  1632. AsmJsFunctionInfo* funcInfo = function->GetAsmJsFunctionInfo();
  1633. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1634. PrependInt32(builder, L"Start Asm.js Function Info", magicStartOfAsmJsFuncInfo);
  1635. #endif
  1636. size += PrependInt32(builder, L"ReturnType", funcInfo->GetReturnType().which());
  1637. size += PrependInt32(builder, L"IntConstCount", funcInfo->GetIntConstCount());
  1638. size += PrependInt32(builder, L"DoubleConstCount", funcInfo->GetDoubleConstCount());
  1639. size += PrependInt32(builder, L"FloatConstCount", funcInfo->GetFloatConstCount());
  1640. size += PrependInt16(builder, L"ArgCount", funcInfo->GetArgCount());
  1641. size += PrependInt16(builder, L"ArgSize", funcInfo->GetArgByteSize());
  1642. size += PrependInt32(builder, L"IntVarCount", funcInfo->GetIntVarCount());
  1643. size += PrependInt32(builder, L"DoubleVarCount", funcInfo->GetDoubleVarCount());
  1644. size += PrependInt32(builder, L"FloatVarCount", funcInfo->GetFloatVarCount());
  1645. size += PrependInt32(builder, L"IntTmpCount", funcInfo->GetIntTmpCount());
  1646. size += PrependInt32(builder, L"DoubleTmpCount", funcInfo->GetDoubleTmpCount());
  1647. size += PrependInt32(builder, L"FloatTmpCount", funcInfo->GetFloatTmpCount());
  1648. size += PrependInt16(builder, L"ArgSizeArrayLength", funcInfo->GetArgSizeArrayLength());
  1649. size += PrependUInt32Array(builder, funcInfo->GetArgSizeArrayLength(), funcInfo->GetArgsSizesArray());
  1650. size += PrependByteArray(builder, funcInfo->GetArgCount(), (byte*)funcInfo->GetArgTypeArray());
  1651. size += PrependInt32(builder, L"IntByteOffset", funcInfo->GetIntByteOffset());
  1652. size += PrependInt32(builder, L"DoubleByteOffset", funcInfo->GetDoubleByteOffset());
  1653. size += PrependInt32(builder, L"FloatByteOffset", funcInfo->GetFloatByteOffset());
  1654. size += PrependByte(builder, L"IsHeapBufferConst", funcInfo->IsHeapBufferConst());
  1655. size += PrependByte(builder, L"UsesHeapBuffer", funcInfo->UsesHeapBuffer());
  1656. size += PrependInt32(builder, L"SIMDConstCount", funcInfo->GetSimdConstCount());
  1657. size += PrependInt32(builder, L"SIMDVarCount", funcInfo->GetSimdVarCount());
  1658. size += PrependInt32(builder, L"SIMDTmpCount", funcInfo->GetSimdTmpCount());
  1659. size += PrependInt32(builder, L"SIMDByteOffset", funcInfo->GetSimdByteOffset());
  1660. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1661. size += PrependInt32(builder, L"End Asm.js Function Info", magicEndOfAsmJsFuncInfo);
  1662. #endif
  1663. return size;
  1664. }
  1665. uint32 AddAsmJsModuleInfo(BufferBuilderList & builder, FunctionBody * function)
  1666. {
  1667. uint32 size = 0;
  1668. AsmJsModuleInfo * moduleInfo = function->GetAsmJsModuleInfo();
  1669. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1670. PrependInt32(builder, L"Start Asm.js Module Info", magicStartOfAsmJsModuleInfo);
  1671. #endif
  1672. size += PrependInt32(builder, L"ArgInCount", moduleInfo->GetArgInCount());
  1673. size += PrependInt32(builder, L"ExportsCount", moduleInfo->GetExportsCount());
  1674. size += PrependInt32(builder, L"SlotsCount", moduleInfo->GetSlotsCount());
  1675. size += PrependInt32(builder, L"SIMDRegCount", moduleInfo->GetSimdRegCount());
  1676. if (moduleInfo->GetExportsCount() > 0)
  1677. {
  1678. PropertyIdArray * propArray = moduleInfo->GetExportsIdArray();
  1679. size += PrependByte(builder, L"ExportsIdArrayDups", propArray->hadDuplicates);
  1680. size += PrependByte(builder, L"ExportsIdArray__proto__", propArray->has__proto__);
  1681. size += PrependInt32(builder, L"ExportsIdArrayLength", propArray->count);
  1682. for (uint i = 0; i < propArray->count; i++)
  1683. {
  1684. PropertyId propertyId = encodePossiblyBuiltInPropertyId(propArray->elements[i]);
  1685. size += PrependInt32(builder, L"ExportsIdArrayElem", propertyId);
  1686. }
  1687. size += PrependUInt32Array(builder, moduleInfo->GetExportsCount(), moduleInfo->GetExportsFunctionLocation());
  1688. }
  1689. size += PrependInt32(builder, L"ExportFunctionIndex", moduleInfo->GetExportFunctionIndex());
  1690. size += PrependInt32(builder, L"VarCount", moduleInfo->GetVarCount());
  1691. for (int i = 0; i < moduleInfo->GetVarCount(); i++)
  1692. {
  1693. size += PrependStruct(builder, L"ModuleVar", &moduleInfo->GetVar(i));
  1694. }
  1695. size += PrependInt32(builder, L"VarImportCount", moduleInfo->GetVarImportCount());
  1696. for (int i = 0; i < moduleInfo->GetVarImportCount(); i++)
  1697. {
  1698. auto import = moduleInfo->GetVarImport(i);
  1699. size += PrependInt32(builder, L"ImportLocation", import.location);
  1700. size += PrependByte(builder, L"ImportType", import.type);
  1701. PropertyId propertyId = encodePossiblyBuiltInPropertyId(import.field);
  1702. size += PrependInt32(builder, L"ImportId", propertyId);
  1703. }
  1704. size += PrependInt32(builder, L"FunctionImportCount", moduleInfo->GetFunctionImportCount());
  1705. for (int i = 0; i < moduleInfo->GetFunctionImportCount(); i++)
  1706. {
  1707. auto import = moduleInfo->GetFunctionImport(i);
  1708. size += PrependInt32(builder, L"ImportLocation", import.location);
  1709. PropertyId propertyId = encodePossiblyBuiltInPropertyId(import.field);
  1710. size += PrependInt32(builder, L"ImportId", propertyId);
  1711. }
  1712. size += PrependInt32(builder, L"FunctionCount", moduleInfo->GetFunctionCount());
  1713. for (int i = 0; i < moduleInfo->GetFunctionCount(); i++)
  1714. {
  1715. auto func = moduleInfo->GetFunction(i);
  1716. size += PrependInt32(builder, L"FuncLocation", func.location);
  1717. }
  1718. size += PrependInt32(builder, L"FunctionTableCount", moduleInfo->GetFunctionTableCount());
  1719. for (int i = 0; i < moduleInfo->GetFunctionTableCount(); i++)
  1720. {
  1721. auto table = moduleInfo->GetFunctionTable(i);
  1722. size += PrependInt32(builder, L"FuncTableSize", table.size);
  1723. PrependUInt32Array(builder, table.size, table.moduleFunctionIndex);
  1724. }
  1725. size += PrependStruct<AsmJsModuleMemory>(builder, L"ModuleMemory", &moduleInfo->GetModuleMemory());
  1726. size += PrependInt32(builder, L"AsmJsSlotMapCount", moduleInfo->GetAsmJsSlotMap()->Count());
  1727. auto slotIter = moduleInfo->GetAsmJsSlotMap()->GetIterator();
  1728. while (slotIter.IsValid())
  1729. {
  1730. PropertyId propertyId = encodePossiblyBuiltInPropertyId(slotIter.CurrentKey());
  1731. size += PrependInt32(builder, L"AsmJsSlotPropId", propertyId);
  1732. size += PrependStruct(builder, L"AsmJsSlotValue", slotIter.CurrentValue());
  1733. slotIter.MoveNext();
  1734. }
  1735. size += PrependStruct(builder, L"MathBuiltinBV", &moduleInfo->GetAsmMathBuiltinUsed());
  1736. size += PrependStruct(builder, L"ArrayBuiltinBV", &moduleInfo->GetAsmArrayBuiltinUsed());
  1737. size += PrependStruct(builder, L"SIMDBuiltinBV", &moduleInfo->GetAsmSimdBuiltinUsed());
  1738. size += PrependInt32(builder, L"MaxHeapAccess", moduleInfo->GetMaxHeapAccess());
  1739. size += PrependByte(builder, L"UsesChangeHeap", moduleInfo->GetUsesChangeHeap());
  1740. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1741. size += PrependInt32(builder, L"End Asm.js Module Info", magicEndOfAsmJsModuleInfo);
  1742. #endif
  1743. return size;
  1744. }
  1745. #endif
  1746. HRESULT AddFunctionBody(BufferBuilderList & builder, FunctionBody * function, SRCINFO const * srcInfo, int *serializationIndex)
  1747. {
  1748. SerializedFieldList definedFields = { 0 };
  1749. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1750. PrependInt32(builder, L"Start Function Table", magicStartOfFunctionBody);
  1751. #endif
  1752. function->SetSerializationIndex((*serializationIndex)++);
  1753. uint32 sourceDiff = 0;
  1754. if (!TryConvertToUInt32(function->StartOffset(), &sourceDiff))
  1755. {
  1756. Assert(0); // Likely a bug
  1757. return ByteCodeSerializer::CantGenerate;
  1758. }
  1759. PrependString16(builder, L"Display Name", function->m_displayName, (function->m_displayNameLength +1)* sizeof(wchar_t));
  1760. if (function->m_lineNumber != 0)
  1761. {
  1762. definedFields.has_m_lineNumber = true;
  1763. PrependInt32(builder, L"Line Number", function->m_lineNumber);
  1764. }
  1765. if (function->m_columnNumber != 0)
  1766. {
  1767. definedFields.has_m_columnNumber = true;
  1768. PrependInt32(builder, L"Column Number", function->m_columnNumber);
  1769. }
  1770. // FunctionBody Details
  1771. DWORD bitFlags =
  1772. (function->m_isDeclaration ? ffIsDeclaration : 0)
  1773. | (function->m_hasImplicitArgIns ? ffHasImplicitArgsIn : 0)
  1774. | (function->m_isAccessor ? ffIsAccessor : 0)
  1775. | (function->m_isStaticNameFunction ? ffIsStaticNameFunction : 0)
  1776. | (function->m_isNamedFunctionExpression ? ffIsNamedFunctionExpression : 0)
  1777. | (function->m_isNameIdentifierRef ? ffIsNameIdentifierRef : 0)
  1778. | (function->m_isGlobalFunc ? ffIsGlobalFunc : 0)
  1779. | (function->m_dontInline ? ffDontInline : 0)
  1780. | (function->m_isFuncRegistered ? ffIsFuncRegistered : 0)
  1781. | (function->m_isStrictMode ? ffIsStrictMode : 0)
  1782. | (function->m_doBackendArgumentsOptimization ? ffDoBackendArgumentsOptimization : 0)
  1783. | (function->m_isEval ? ffIsEval : 0)
  1784. | (function->m_isDynamicFunction ? ffIsDynamicFunction : 0)
  1785. | (function->m_hasAllNonLocalReferenced ? ffhasAllNonLocalReferenced : 0)
  1786. | (function->m_hasSetIsObject ? ffhasSetIsObject : 0)
  1787. | (function->m_CallsEval ? ffhasSetCallsEval : 0)
  1788. | (function->m_ChildCallsEval ? ffChildCallsEval : 0)
  1789. | (function->m_hasReferenceableBuiltInArguments ? ffHasReferenceableBuiltInArguments : 0)
  1790. #ifndef TEMP_DISABLE_ASMJS
  1791. | (function->m_isAsmjsMode ? ffIsAsmJsMode : 0)
  1792. | (function->m_isAsmJsFunction ? ffIsAsmJsFunction : 0)
  1793. #endif
  1794. ;
  1795. PrependInt32(builder, L"BitFlags", bitFlags);
  1796. PrependInt32(builder, L"Relative Function ID", function->functionId - topFunctionId); // Serialized function ids are relative to the top function ID
  1797. PrependInt32(builder, L"Serialization ID", function->GetSerializationIndex());
  1798. PrependInt32(builder, L"Attributes", function->GetAttributes());
  1799. AssertMsg((function->GetAttributes() &
  1800. ~(FunctionInfo::Attributes::ErrorOnNew
  1801. | FunctionInfo::Attributes::SuperReference
  1802. | FunctionInfo::Attributes::Lambda
  1803. | FunctionInfo::Attributes::Async
  1804. | FunctionInfo::Attributes::CapturesThis
  1805. | FunctionInfo::Attributes::Generator
  1806. | FunctionInfo::Attributes::ClassConstructor
  1807. | FunctionInfo::Attributes::ClassMethod)) == 0,
  1808. "Only the ErrorOnNew|SuperReference|Lambda|CapturesThis|Generator|ClassConstructor|Async|ClassMember attributes should be set on a serialized function");
  1809. PrependInt32(builder, L"Offset Into Source", sourceDiff);
  1810. if (function->GetNestedCount() > 0)
  1811. {
  1812. definedFields.has_m_nestedCount = true;
  1813. PrependInt32(builder, L"Nested count", function->GetNestedCount());
  1814. }
  1815. // This field should always be non-zero
  1816. Assert(function->m_constCount != 0);
  1817. #define PrependArgSlot PrependInt16
  1818. #define PrependRegSlot PrependInt32
  1819. #define PrependCharCount PrependInt32
  1820. #define PrependULong PrependInt32
  1821. #define PrependUInt16 PrependInt16
  1822. #define PrependUInt32 PrependInt32
  1823. #define DEFINE_FUNCTION_PROXY_FIELDS 1
  1824. #define DEFINE_PARSEABLE_FUNCTION_INFO_FIELDS 1
  1825. #define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) \
  1826. if (function->##name != 0) { \
  1827. definedFields.has_##name = true; \
  1828. Prepend##serializableType(builder, L#name, function->##name); \
  1829. }
  1830. #define DECLARE_MANUAL_SERIALIZABLE_FIELD(type, name, serializableType, serializeHere) \
  1831. if (function->##name != 0 && serializeHere) { \
  1832. definedFields.has_##name = true; \
  1833. Prepend##serializableType(builder, L#name, function->##name); \
  1834. }
  1835. #include "SerializableFunctionFields.h"
  1836. if (!OmitFunction(function->GetSerializationIndex()))
  1837. {
  1838. #define DEFINE_FUNCTION_BODY_FIELDS 1
  1839. #define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) \
  1840. if (function->##name != 0) { \
  1841. definedFields.has_##name = true; \
  1842. Prepend##serializableType(builder, L#name, function->##name); \
  1843. }
  1844. #define DECLARE_MANUAL_SERIALIZABLE_FIELD(type, name, serializableType, serializeHere) \
  1845. if (function->##name != 0 && serializeHere) { \
  1846. definedFields.has_##name = true; \
  1847. Prepend##serializableType(builder, L#name, function->##name); \
  1848. }
  1849. #include "SerializableFunctionFields.h"
  1850. }
  1851. if (!OmitFunction(function->GetSerializationIndex()))
  1852. {
  1853. if (function->loopHeaderArray)
  1854. {
  1855. PrependByte(builder, L"Loop Header Array Exists", 1);
  1856. for (uint i = 0; i < function->loopCount; ++i)
  1857. {
  1858. PrependInt32(builder, L"Loop Header Start", function->loopHeaderArray[i].startOffset);
  1859. PrependInt32(builder, L"Loop Header End", function->loopHeaderArray[i].endOffset);
  1860. }
  1861. }
  1862. else
  1863. {
  1864. PrependByte(builder, L"Loop Header Array Exists", 0);
  1865. }
  1866. #ifndef TEMP_DISABLE_ASMJS
  1867. if (function->GetAsmJsFunctionInfo())
  1868. {
  1869. PrependByte(builder, L"Asm.js Info Exists", 1);
  1870. AddAsmJsFunctionInfo(builder, function);
  1871. }
  1872. else if (function->GetIsAsmjsMode())
  1873. {
  1874. PrependByte(builder, L"Asm.js Info Exists", 2);
  1875. AddAsmJsModuleInfo(builder, function);
  1876. }
  1877. else
  1878. #endif
  1879. {
  1880. PrependByte(builder, L"Asm.js Info Exists", 0);
  1881. }
  1882. #ifndef TEMP_DISABLE_ASMJS
  1883. if (function->GetIsAsmJsFunction())
  1884. {
  1885. AddAsmJsConstantTable(builder, function);
  1886. auto hr = RewriteAsmJsByteCodesInto(builder, L"Rewritten Byte Code", function, function->byteCodeBlock);
  1887. if (FAILED(hr))
  1888. {
  1889. return hr;
  1890. }
  1891. }
  1892. else
  1893. #endif
  1894. {
  1895. AddConstantTable(builder, function);
  1896. auto hr = RewriteByteCodesInto(builder, L"Rewritten Byte Code", function, function->byteCodeBlock);
  1897. if (FAILED(hr))
  1898. {
  1899. return hr;
  1900. }
  1901. }
  1902. AddCacheIdToPropertyIdMap(builder, function);
  1903. AddReferencedPropertyIdMap(builder, function);
  1904. AddPropertyIdsForScopeSlotArray(builder, function);
  1905. uint debuggerScopeSlotArraySize = GetDebuggerScopeSlotArrayCount(function);
  1906. PrependInt32(builder, L"Debugger Scope Slot Array Size", debuggerScopeSlotArraySize);
  1907. AddSlotArrayDebuggerScopes(builder, function, debuggerScopeSlotArraySize);
  1908. // Literal regexes
  1909. for (uint i = 0; i < function->literalRegexCount; ++i)
  1910. {
  1911. const auto literalRegex = function->GetLiteralRegex(i);
  1912. if (!literalRegex)
  1913. {
  1914. PrependInt32(builder, L"Literal regex source length", -1);
  1915. continue;
  1916. }
  1917. const auto source = literalRegex->GetSource();
  1918. PrependInt32(builder, L"Literal regex source length", source.GetLength());
  1919. PrependString16(builder, L"Literal regex source", source.GetBuffer(), (source.GetLength() + 1)* sizeof(wchar_t));
  1920. PrependByte(builder, L"Literal regex flags", literalRegex->GetFlags());
  1921. }
  1922. // Write the SourceInfo stuff
  1923. PrependSmallSpanSequence(builder, L"Span Sequence", function->m_sourceInfo.pSpanSequence);
  1924. }
  1925. // Lastly, write each of the lexically enclosed functions
  1926. if (function->GetNestedCount())
  1927. {
  1928. auto nestedBodyList = Anew(alloc, BufferBuilderList, L"Nest Function Bodies");
  1929. for(uint32 i = 0; i<function->GetNestedCount(); ++i)
  1930. {
  1931. auto nestedFunctionBody = function->GetNestedFunc(i)->GetFunctionBody();
  1932. if (nestedFunctionBody==nullptr)
  1933. {
  1934. PrependInt32(builder, L"Empty Nested Function", 0);
  1935. }
  1936. else
  1937. {
  1938. auto nestedFunctionBuilder = Anew(alloc, BufferBuilderList, L"Nested Function");
  1939. nestedBodyList->list = nestedBodyList->list->Prepend(nestedFunctionBuilder, alloc);
  1940. auto offsetToNested = Anew(alloc, BufferBuilderRelativeOffset, L"Offset To Nested Function", nestedFunctionBuilder);
  1941. builder.list = builder.list->Prepend(offsetToNested, alloc);
  1942. AddFunctionBody(*nestedFunctionBuilder, nestedFunctionBody, srcInfo, serializationIndex);
  1943. }
  1944. }
  1945. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1946. PrependInt32(builder, L"End Function Body", magicEndOfFunctionBody);
  1947. #endif
  1948. builder.list = builder.list->Prepend(nestedBodyList, alloc);
  1949. }
  1950. else
  1951. {
  1952. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  1953. PrependInt32(builder, L"End Function Body", magicEndOfFunctionBody);
  1954. #endif
  1955. }
  1956. // Increment the function count
  1957. ++functionCount.value;
  1958. // Reverse to put prepended items in correct order
  1959. builder.list = builder.list->ReverseCurrentList();
  1960. PrependStruct<SerializedFieldList>(builder, L"Serialized Field List", &definedFields);
  1961. return S_OK;
  1962. }
  1963. HRESULT AddTopFunctionBody(FunctionBody * function, SRCINFO const * srcInfo)
  1964. {
  1965. topFunctionId = function->functionId;
  1966. int serializationIndex = 0;
  1967. return AddFunctionBody(functionsTable, function, srcInfo, &serializationIndex);
  1968. }
  1969. };
  1970. class ByteCodeBufferReader
  1971. {
  1972. public:
  1973. ScriptContext * scriptContext;
  1974. byte * raw;
  1975. int magic;
  1976. int totalSize;
  1977. byte fileVersionScheme;
  1978. int V1;
  1979. int V2;
  1980. int V3;
  1981. int V4;
  1982. byte architecture;
  1983. int expectedFunctionBodySize;
  1984. int expectedBuildInPropertyCount;
  1985. int expectedOpCodeCount;
  1986. int firstFunctionId;
  1987. int functionCount;
  1988. const byte * string16s;
  1989. int string16Count;
  1990. const unaligned StringIndexRecord * string16IndexTable;
  1991. const byte * string16Table;
  1992. const byte * sourceSpans;
  1993. int lineInfoCacheCount;
  1994. const byte * lineInfoCaches;
  1995. const JsUtil::LineOffsetCache<Recycler>::LineOffsetCacheItem * lineInfoCache;
  1996. const byte * functions;
  1997. int sourceSize;
  1998. int sourceCharLength;
  1999. Utf8SourceInfo *utf8SourceInfo;
  2000. uint sourceIndex;
  2001. bool const isLibraryCode;
  2002. public:
  2003. ByteCodeBufferReader(ScriptContext * scriptContext, byte * raw, bool isLibraryCode, int builtInPropertyCount)
  2004. : scriptContext(scriptContext), raw(raw), utf8SourceInfo(nullptr), isLibraryCode(isLibraryCode),
  2005. expectedFunctionBodySize(sizeof(unaligned FunctionBody)),
  2006. expectedBuildInPropertyCount(builtInPropertyCount),
  2007. expectedOpCodeCount((int)OpCode::Count)
  2008. {
  2009. if (isLibraryCode)
  2010. {
  2011. expectedFunctionBodySize = 0;
  2012. expectedOpCodeCount = 0;
  2013. }
  2014. }
  2015. static const byte* ReadFunctionBodyFlags(const byte * buffer, size_t remainingBytes, FunctionBody::FunctionBodyFlags * value)
  2016. {
  2017. Assert(remainingBytes >= sizeof(FunctionBody::FunctionBodyFlags));
  2018. *value = *(FunctionBody::FunctionBodyFlags*) buffer;
  2019. return buffer + sizeof(FunctionBody::FunctionBodyFlags);
  2020. }
  2021. const byte* ReadFunctionBodyFlags(const byte * buffer, FunctionBody::FunctionBodyFlags * value)
  2022. {
  2023. auto remainingBytes = (raw + totalSize) - buffer;
  2024. return ReadFunctionBodyFlags(buffer, remainingBytes, value);
  2025. }
  2026. const byte* ReadBool(const byte * buffer, bool * value)
  2027. {
  2028. auto remainingBytes = (raw + totalSize) - buffer;
  2029. Assert(remainingBytes >= sizeof(bool));
  2030. *value = *buffer ? true : false;
  2031. return buffer + sizeof(bool);
  2032. }
  2033. static const byte * ReadByte(const byte * buffer, size_t remainingBytes, byte * value)
  2034. {
  2035. Assert(remainingBytes>=sizeof(byte));
  2036. *value = *(byte*)buffer;
  2037. return buffer + sizeof(byte);
  2038. }
  2039. const byte * ReadByte(const byte * buffer, byte * value)
  2040. {
  2041. auto remainingBytes = (raw + totalSize) - buffer;
  2042. return ReadByte(buffer, remainingBytes, value);
  2043. }
  2044. static const byte * ReadInt16(const byte * buffer, size_t remainingBytes, int16 * value)
  2045. {
  2046. #if VARIABLE_INT_ENCODING
  2047. return ReadVariableInt<int16>(buffer, remainingBytes, value);
  2048. #else
  2049. Assert(remainingBytes>=sizeof(int16));
  2050. *value = *(int16 *) buffer;
  2051. return buffer + sizeof(int16);
  2052. #endif
  2053. }
  2054. const byte * ReadInt16(const byte * buffer, int16 * value)
  2055. {
  2056. auto remainingBytes = (raw + totalSize) - buffer;
  2057. return ReadInt16(buffer, remainingBytes, value);
  2058. }
  2059. static const byte * ReadConstantSizedInt64(const byte * buffer, size_t remainingBytes, int64 * value)
  2060. {
  2061. Assert(remainingBytes >= sizeof(int64));
  2062. *value = *(int64 *)buffer;
  2063. return buffer + sizeof(int64);
  2064. }
  2065. const byte * ReadConstantSizedInt64(const byte * buffer, int64 * value)
  2066. {
  2067. auto remainingBytes = (raw + totalSize) - buffer;
  2068. return ReadConstantSizedInt64(buffer, remainingBytes, value);
  2069. }
  2070. static const byte * ReadConstantSizedInt32(const byte * buffer, size_t remainingBytes, int * value)
  2071. {
  2072. Assert(remainingBytes >= sizeof(int));
  2073. *value = *(int *) buffer;
  2074. return buffer + sizeof(int);
  2075. }
  2076. const byte * ReadConstantSizedInt32(const byte * buffer, int * value)
  2077. {
  2078. auto remainingBytes = (raw + totalSize) - buffer;
  2079. return ReadConstantSizedInt32(buffer, remainingBytes, value);
  2080. }
  2081. static const byte * ReadInt32(const byte * buffer, size_t remainingBytes, int * value)
  2082. {
  2083. #if VARIABLE_INT_ENCODING
  2084. return ReadVariableInt<int>(buffer, remainingBytes, value);
  2085. #else
  2086. Assert(remainingBytes >= sizeof(int));
  2087. return ReadConstantSizedInt32(buffer, remainingBytes, value);
  2088. #endif
  2089. }
  2090. const byte * ReadInt32(const byte * buffer, int * value)
  2091. {
  2092. auto remainingBytes = (raw + totalSize) - buffer;
  2093. return ReadInt32(buffer, remainingBytes, value);
  2094. }
  2095. const byte * ReadCharCount(const byte * buffer, size_t remainingBytes, charcount_t * value)
  2096. {
  2097. Assert(remainingBytes>=sizeof(charcount_t));
  2098. #if VARIABLE_INT_ENCODING
  2099. return ReadVariableInt<charcount_t>(buffer, remainingBytes, value);
  2100. #else
  2101. *value = *(charcount_t *) buffer;
  2102. return buffer + sizeof(charcount_t);
  2103. #endif
  2104. }
  2105. const byte * ReadCharCount(const byte * buffer, charcount_t * value)
  2106. {
  2107. auto remainingBytes = (raw + totalSize) - buffer;
  2108. return ReadCharCount(buffer, remainingBytes, value);
  2109. }
  2110. static const byte * ReadFloat(const byte * buffer, size_t remainingBytes, float * value)
  2111. {
  2112. Assert(remainingBytes >= sizeof(float));
  2113. *value = *(float *)buffer;
  2114. return buffer + sizeof(float);
  2115. }
  2116. const byte * ReadFloat(const byte * buffer, float * value)
  2117. {
  2118. auto remainingBytes = (raw + totalSize) - buffer;
  2119. return ReadFloat(buffer, remainingBytes, value);
  2120. }
  2121. static const byte * ReadDouble(const byte * buffer, size_t remainingBytes, double * value)
  2122. {
  2123. Assert(remainingBytes>=sizeof(double));
  2124. *value = *(double *)buffer;
  2125. return buffer + sizeof(double);
  2126. }
  2127. const byte * ReadDouble(const byte * buffer, double * value)
  2128. {
  2129. auto remainingBytes = (raw + totalSize) - buffer;
  2130. return ReadDouble(buffer, remainingBytes, value);
  2131. }
  2132. static const byte * ReadSIMDValue(const byte * buffer, size_t remainingBytes, SIMDValue * value)
  2133. {
  2134. Assert(remainingBytes >= sizeof(SIMDValue));
  2135. *value = *(SIMDValue *)buffer;
  2136. return buffer + sizeof(SIMDValue);
  2137. }
  2138. const byte * ReadSIMDValue(const byte * buffer, SIMDValue * value)
  2139. {
  2140. auto remainingBytes = (raw + totalSize) - buffer;
  2141. return ReadSIMDValue(buffer, remainingBytes, value);
  2142. }
  2143. const byte * ReadUInt16(const byte * buffer, uint16 * value)
  2144. {
  2145. auto remainingBytes = (raw + totalSize) - buffer;
  2146. return ReadInt16(buffer, remainingBytes, (int16*)value);
  2147. }
  2148. const byte * ReadUInt32(const byte * buffer, unsigned int * value)
  2149. {
  2150. auto remainingBytes = (raw + totalSize) - buffer;
  2151. return ReadInt32(buffer, remainingBytes, (int*)value);
  2152. }
  2153. const byte * ReadULong(const byte * buffer, ulong * value)
  2154. {
  2155. auto remainingBytes = (raw + totalSize) - buffer;
  2156. return ReadInt32(buffer, remainingBytes, (int*)value);
  2157. }
  2158. const byte * ReadRegSlot(const byte * buffer, RegSlot * value)
  2159. {
  2160. auto remainingBytes = (raw + totalSize) - buffer;
  2161. return ReadInt32(buffer, remainingBytes, (int*)value);
  2162. }
  2163. const byte * ReadArgSlot(const byte * buffer, ArgSlot * value)
  2164. {
  2165. auto remainingBytes = (raw + totalSize) - buffer;
  2166. return ReadInt32(buffer, remainingBytes, (int*)value);
  2167. }
  2168. const byte * ReadConstantSizedInt32NoSize(const byte * buffer, int * value)
  2169. {
  2170. *value = *(int *)buffer;
  2171. return buffer + sizeof(int);
  2172. }
  2173. const byte * ReadOffsetAsPointer(const byte * buffer, byte const ** value)
  2174. {
  2175. int offset;
  2176. auto next = ReadConstantSizedInt32(buffer, &offset);
  2177. if (offset == 0)
  2178. {
  2179. *value = nullptr;
  2180. return next;
  2181. }
  2182. *value = raw + offset;
  2183. return next;
  2184. }
  2185. const byte * ReadByteBlock(const byte * buffer, WriteBarrierPtr<ByteBlock>* byteBlock)
  2186. {
  2187. int contentLength;
  2188. buffer = ReadInt32(buffer, &contentLength);
  2189. if (contentLength == 0)
  2190. {
  2191. *byteBlock = nullptr;
  2192. }
  2193. else
  2194. {
  2195. // TODO: Abstract this out to ByteBlock::New
  2196. *byteBlock = RecyclerNewLeaf(scriptContext->GetRecycler(), ByteBlock, contentLength, (byte*)buffer);
  2197. }
  2198. return buffer + contentLength;
  2199. }
  2200. const byte * ReadAuxiliary(const byte * buffer, FunctionBody * functionBody)
  2201. {
  2202. const byte * current = buffer;
  2203. uint32 countOfAuxiliaryStructure;
  2204. current = ReadUInt32(current, &countOfAuxiliaryStructure);
  2205. if (countOfAuxiliaryStructure == 0)
  2206. {
  2207. return current;
  2208. }
  2209. uint32 sizeOfAuxiliaryBlock;
  2210. uint32 sizeOfAuxiliaryContextBlock;
  2211. current = ReadUInt32(current, &sizeOfAuxiliaryBlock);
  2212. current = ReadUInt32(current, &sizeOfAuxiliaryContextBlock);
  2213. ByteBlock * auxBlock = sizeOfAuxiliaryBlock?
  2214. ByteBlock::New(scriptContext->GetRecycler(), nullptr, sizeOfAuxiliaryBlock) : nullptr;
  2215. ByteBlock * auxContextBlock = sizeOfAuxiliaryContextBlock?
  2216. ByteBlock::New(scriptContext->GetRecycler(), nullptr, sizeOfAuxiliaryContextBlock) : nullptr;
  2217. for (uint i = 0; i < countOfAuxiliaryStructure; i++)
  2218. {
  2219. typedef serialization_alignment const SerializedAuxiliary TBase;
  2220. auto part = (serialization_alignment const SerializedAuxiliary * )current;
  2221. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2222. Assert(part->auxMagic == magicStartOfAux);
  2223. #endif
  2224. switch(part->kind)
  2225. {
  2226. default:
  2227. AssertMsg(false, "Unexpected auxiliary kind");
  2228. Throw::FatalInternalError();
  2229. break;
  2230. case sakVarArrayIntCount:
  2231. current = DeserializeVarArray<VarArray>(scriptContext, current, auxBlock);
  2232. break;
  2233. case sakVarArrayVarCount:
  2234. current = DeserializeVarArray<VarArrayVarCount>(scriptContext, current, auxContextBlock);
  2235. break;
  2236. case sakIntArray:
  2237. current = DeserializeIntArray(scriptContext, current, auxBlock);
  2238. break;
  2239. case sakFloatArray:
  2240. current = DeserializeFloatArray(scriptContext, current, auxBlock);
  2241. break;
  2242. case sakPropertyIdArray:
  2243. current = DeserializePropertyIdArray(scriptContext, current, auxBlock, functionBody);
  2244. break;
  2245. case sakFuncInfoArray:
  2246. current = DeserializeFuncInfoArray(scriptContext, current, auxBlock);
  2247. break;
  2248. }
  2249. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2250. int magicEnd;
  2251. current = ReadInt32(current, &magicEnd);
  2252. Assert(magicEnd == magicEndOfAux);
  2253. #endif
  2254. }
  2255. functionBody->auxBlock = auxBlock;
  2256. functionBody->auxContextBlock = auxContextBlock;
  2257. return current;
  2258. }
  2259. LPCWSTR GetString16ById(int id, bool* isPropertyRecord = nullptr)
  2260. {
  2261. if (id == 0xffffffff)
  2262. {
  2263. return nullptr;
  2264. }
  2265. if(!(id >= this->expectedBuildInPropertyCount && id <= string16Count + this->expectedBuildInPropertyCount))
  2266. {
  2267. Assert(false);
  2268. }
  2269. const unaligned StringIndexRecord* record = string16IndexTable + (id - this->expectedBuildInPropertyCount);
  2270. if(isPropertyRecord)
  2271. {
  2272. *isPropertyRecord = record->isPropertyRecord;
  2273. }
  2274. auto offset = record->offset;
  2275. auto addressOfString = raw + offset;
  2276. return (LPCWSTR)addressOfString;
  2277. }
  2278. uint32 GetString16LengthById(int id)
  2279. {
  2280. if(!(id >= this->expectedBuildInPropertyCount && id<=string16Count + this->expectedBuildInPropertyCount))
  2281. {
  2282. Assert(false);
  2283. }
  2284. LPCWSTR s1 = GetString16ById(id);
  2285. LPCWSTR s2 = GetString16ById(id + 1);
  2286. auto result = s2 - s1 - 1;
  2287. Assert(result <= UINT_MAX);
  2288. return (uint32)result;
  2289. }
  2290. HRESULT ReadHeader()
  2291. {
  2292. auto current = ReadConstantSizedInt32NoSize(raw, &magic);
  2293. if (magic != magicConstant)
  2294. {
  2295. AssertMsg(false, "Unrecognized magic constant in byte code file header. Is this really a bytecode file?");
  2296. return E_FAIL;
  2297. }
  2298. current = ReadConstantSizedInt32NoSize(current, &totalSize);
  2299. current = ReadByte(current, &fileVersionScheme);
  2300. byte expectedFileVersionScheme = isLibraryCode? ReleaseVersioningScheme : CurrentFileVersionScheme;
  2301. #if ENABLE_DEBUG_CONFIG_OPTIONS
  2302. if (Js::Configuration::Global.flags.ForceSerializedBytecodeVersionSchema)
  2303. {
  2304. expectedFileVersionScheme = (byte)Js::Configuration::Global.flags.ForceSerializedBytecodeVersionSchema;
  2305. }
  2306. #endif
  2307. // Ignore the version scheme check if it is library code
  2308. if (!isLibraryCode && fileVersionScheme != expectedFileVersionScheme)
  2309. {
  2310. // File version scheme is incompatible.
  2311. return ByteCodeSerializer::InvalidByteCode;
  2312. }
  2313. DWORD expectedV1 = 0;
  2314. DWORD expectedV2 = 0;
  2315. DWORD expectedV3 = 0;
  2316. DWORD expectedV4 = 0;
  2317. if (expectedFileVersionScheme != ReleaseVersioningScheme)
  2318. {
  2319. Js::VerifyCatastrophic(!isLibraryCode);
  2320. Js::VerifyCatastrophic(expectedFileVersionScheme == EngineeringVersioningScheme);
  2321. Js::VerifyOkCatastrophic(AutoSystemInfo::GetJscriptFileVersion(&expectedV1, &expectedV2, &expectedV3, &expectedV4));
  2322. }
  2323. else
  2324. {
  2325. auto guidDWORDs = (DWORD*)(&byteCodeCacheReleaseFileVersion);
  2326. expectedV1 = guidDWORDs[0];
  2327. expectedV2 = guidDWORDs[1];
  2328. expectedV3 = guidDWORDs[2];
  2329. expectedV4 = guidDWORDs[3];
  2330. }
  2331. #if ENABLE_DEBUG_CONFIG_OPTIONS
  2332. if (Js::Configuration::Global.flags.ForceSerializedBytecodeMajorVersion)
  2333. {
  2334. expectedV1 = Js::Configuration::Global.flags.ForceSerializedBytecodeMajorVersion;
  2335. expectedV2 = 0;
  2336. expectedV3 = 0;
  2337. expectedV4 = 0;
  2338. }
  2339. #endif
  2340. current = ReadConstantSizedInt32(current, &V1);
  2341. if ((DWORD)V1!=expectedV1)
  2342. {
  2343. // Incompatible major version
  2344. return ByteCodeSerializer::InvalidByteCode;
  2345. }
  2346. // Library code is serialized with one build of the engine and then included into a subsequent build, so can't have match
  2347. // on the build timestamp hash. Also want to share the generated bytecode between x86/ARM and debug/release, so skip the extra
  2348. // checking. Will rework this validation entirely under TFS 555060
  2349. current = ReadConstantSizedInt32(current, &V2);
  2350. if ((DWORD)V2 != expectedV2)
  2351. {
  2352. // Incompatible minor version
  2353. return ByteCodeSerializer::InvalidByteCode;
  2354. }
  2355. current = ReadConstantSizedInt32(current, &V3);
  2356. if ((DWORD)V3 != expectedV3)
  2357. {
  2358. // Incompatible 3rd version part
  2359. return ByteCodeSerializer::InvalidByteCode;
  2360. }
  2361. current = ReadConstantSizedInt32(current, &V4);
  2362. if ((DWORD)V4 != expectedV4)
  2363. {
  2364. // Incompatible 4th version part
  2365. return ByteCodeSerializer::InvalidByteCode;
  2366. }
  2367. current = ReadByte(current, &architecture);
  2368. if (architecture!=magicArchitecture)
  2369. {
  2370. // This byte cache file was created with against a chakra running under a different architecture. It is incompatible.
  2371. return ByteCodeSerializer::InvalidByteCode;
  2372. }
  2373. int functionBodySize, buildInPropertyCount, opCodeCount;
  2374. current = ReadInt32(current, &functionBodySize);
  2375. if (functionBodySize != expectedFunctionBodySize)
  2376. {
  2377. // The size of function body didn't match. It is incompatible.
  2378. return ByteCodeSerializer::InvalidByteCode;
  2379. }
  2380. current = ReadInt32(current, &buildInPropertyCount);
  2381. if (buildInPropertyCount!=expectedBuildInPropertyCount)
  2382. {
  2383. // This byte cache file was created with against a chakra that has a different number of built in properties. It is incompatible.
  2384. return ByteCodeSerializer::InvalidByteCode;
  2385. }
  2386. current = ReadInt32(current, &opCodeCount);
  2387. if (opCodeCount != expectedOpCodeCount)
  2388. {
  2389. // This byte cache file was created with against a chakra that has a different number of built in properties. It is incompatible.
  2390. return ByteCodeSerializer::InvalidByteCode;
  2391. }
  2392. current = ReadInt32(current, &sourceSize);
  2393. current = ReadInt32(current, &sourceCharLength);
  2394. current = ReadOffsetAsPointer(current, &string16s);
  2395. current = ReadOffsetAsPointer(current, &lineInfoCaches);
  2396. current = ReadOffsetAsPointer(current, &sourceSpans);
  2397. current = ReadOffsetAsPointer(current, &functions);
  2398. // Read strings header
  2399. string16IndexTable = (StringIndexRecord*)ReadInt32(string16s, &string16Count);
  2400. lineInfoCache = (JsUtil::LineOffsetCache<Recycler>::LineOffsetCacheItem *)ReadInt32(lineInfoCaches, &lineInfoCacheCount);
  2401. string16Table = (byte*)(string16IndexTable + string16Count + 1);
  2402. // string16Table is aligned to 2-bytes
  2403. uint32 string16TableOffset = (uint32)(string16Table - raw);
  2404. string16TableOffset = ::Math::Align(string16TableOffset, (uint32)sizeof(wchar_t));
  2405. string16Table = raw + string16TableOffset;
  2406. return S_OK;
  2407. }
  2408. const byte* ReadStringConstant(const byte* current, FunctionBody* function, LPCWSTR& string, uint32& len)
  2409. {
  2410. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2411. int constant;
  2412. current = ReadInt32(current, &constant);
  2413. Assert(constant == magicStartStringConstant);
  2414. #endif
  2415. int stringId;
  2416. current = ReadInt32(current, &stringId);
  2417. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2418. current = ReadInt32(current, &constant);
  2419. Assert(constant == magicEndStringConstant);
  2420. #endif
  2421. string = GetString16ById(stringId);
  2422. len = GetString16LengthById(stringId);
  2423. return current;
  2424. }
  2425. const byte* ReadStringTemplateCallsiteConstant(const byte* current, FunctionBody* function, Var& var)
  2426. {
  2427. int arrayLength = 0;
  2428. current = ReadInt32(current, &arrayLength);
  2429. ScriptContext* scriptContext = function->GetScriptContext();
  2430. ENTER_PINNED_SCOPE(Js::JavascriptArray, callsite);
  2431. callsite = scriptContext->GetLibrary()->CreateArray(arrayLength);
  2432. LPCWSTR string;
  2433. uint32 len;
  2434. uint32 rawlen = 0;
  2435. for (int i = 0; i < arrayLength; i++)
  2436. {
  2437. current = ReadStringConstant(current, function, string, len);
  2438. JavascriptString* str = JavascriptString::NewCopyBuffer(string, len, scriptContext);
  2439. callsite->SetItemWithAttributes(i, str, PropertyEnumerable);
  2440. }
  2441. JavascriptArray* rawArray = scriptContext->GetLibrary()->CreateArray(arrayLength);
  2442. for (int i = 0; i < arrayLength; i++)
  2443. {
  2444. current = ReadStringConstant(current, function, string, len);
  2445. rawlen += len;
  2446. JavascriptString* str = JavascriptString::NewCopyBuffer(string, len, scriptContext);
  2447. rawArray->SetItemWithAttributes(i, str, PropertyEnumerable);
  2448. }
  2449. rawArray->Freeze();
  2450. callsite->SetPropertyWithAttributes(Js::PropertyIds::raw, rawArray, PropertyNone, nullptr);
  2451. callsite->Freeze();
  2452. JavascriptLibrary* library = scriptContext->GetLibrary();
  2453. var = library->TryGetStringTemplateCallsiteObject(callsite);
  2454. if (var == nullptr)
  2455. {
  2456. library->AddStringTemplateCallsiteObject(callsite);
  2457. var = callsite;
  2458. }
  2459. LEAVE_PINNED_SCOPE();
  2460. return current;
  2461. }
  2462. #ifndef TEMP_DISABLE_ASMJS
  2463. const byte * ReadAsmJsConstantsTable(const byte * current, FunctionBody * function)
  2464. {
  2465. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2466. int constant;
  2467. current = ReadInt32(current, &constant);
  2468. Assert(constant == magicStartOfConstantTable);
  2469. #endif
  2470. function->CreateConstantTable();
  2471. uint32 intConstCount = function->GetAsmJsFunctionInfo()->GetIntConstCount();
  2472. uint32 floatConstCount = function->GetAsmJsFunctionInfo()->GetFloatConstCount();
  2473. uint32 doubleConstCount = function->GetAsmJsFunctionInfo()->GetDoubleConstCount();
  2474. Js::Var * constTable = static_cast<Js::Var *>(function->GetConstTable());
  2475. int * intConstTable = reinterpret_cast<int *>(constTable + Js::AsmJsFunctionMemory::RequiredVarConstants - 1);
  2476. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < intConstCount; ++reg)
  2477. {
  2478. current = ReadConstantSizedInt32(current, &intConstTable[reg]);
  2479. }
  2480. float * floatConstTable = reinterpret_cast<float *>(intConstTable + intConstCount);
  2481. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < floatConstCount; ++reg)
  2482. {
  2483. current = ReadFloat(current, &floatConstTable[reg]);
  2484. }
  2485. double * doubleConstTable = reinterpret_cast<double *>(floatConstTable + floatConstCount);
  2486. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < doubleConstCount; ++reg)
  2487. {
  2488. current = ReadDouble(current, &doubleConstTable[reg]);
  2489. }
  2490. uint32 simdConstCount = function->GetAsmJsFunctionInfo()->GetSimdConstCount();
  2491. AsmJsSIMDValue *simdConstTable = reinterpret_cast<AsmJsSIMDValue *>(doubleConstTable + doubleConstCount);
  2492. for (Js::RegSlot reg = Js::FunctionBody::FirstRegSlot; reg < simdConstCount; ++reg)
  2493. {
  2494. current = ReadSIMDValue(current, &simdConstTable[reg]);
  2495. }
  2496. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2497. current = ReadInt32(current, &constant);
  2498. Assert(constant == magicEndOfConstantTable);
  2499. #endif
  2500. return current;
  2501. }
  2502. #endif
  2503. const byte * ReadConstantsTable(const byte * current, FunctionBody * function)
  2504. {
  2505. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2506. int constant;
  2507. current = ReadInt32(current, &constant);
  2508. Assert(constant == magicStartOfConstantTable);
  2509. #endif
  2510. function->CreateConstantTable();
  2511. for (auto reg = FunctionBody::FirstRegSlot + 1; reg < function->m_constCount; reg++) // Ignore first slot, it is always global or module root and has been preinitialized.
  2512. {
  2513. byte ct;
  2514. current = ReadByte(current, &ct);
  2515. switch(ct)
  2516. {
  2517. case ctString16:
  2518. {
  2519. LPCWSTR string;
  2520. uint32 len;
  2521. current = ReadStringConstant(current, function, string, len);
  2522. function->RecordStrConstant(reg, string, len);
  2523. break;
  2524. }
  2525. case ctStringTemplateCallsite:
  2526. {
  2527. Var callsite;
  2528. current = ReadStringTemplateCallsiteConstant(current, function, callsite);
  2529. function->RecordConstant(reg, callsite);
  2530. break;
  2531. }
  2532. case ctInt:
  2533. {
  2534. int value;
  2535. current = ReadConstantSizedInt32(current, &value);
  2536. function->RecordIntConstant(reg, value);
  2537. break;
  2538. }
  2539. case ctNull:
  2540. function->RecordNullObject(reg);
  2541. break;
  2542. case ctUndefined:
  2543. function->RecordUndefinedObject(reg);
  2544. break;
  2545. case ctNumber:
  2546. {
  2547. double value;
  2548. current = ReadDouble(current, &value);
  2549. function->RecordFloatConstant(reg, value);
  2550. break;
  2551. }
  2552. case ctNullDisplay:
  2553. function->RecordNullDisplayConstant(reg);
  2554. break;
  2555. case ctStrictNullDisplay:
  2556. function->RecordStrictNullDisplayConstant(reg);
  2557. break;
  2558. case ctTrue:
  2559. function->RecordTrueObject(reg);
  2560. break;
  2561. case ctFalse:
  2562. function->RecordFalseObject(reg);
  2563. break;
  2564. default:
  2565. AssertMsg(UNREACHED, "Unexpected object type in ReadConstantsTable");
  2566. break;
  2567. }
  2568. }
  2569. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2570. current = ReadInt32(current, &constant);
  2571. Assert(constant == magicEndOfConstantTable);
  2572. #endif
  2573. return current;
  2574. }
  2575. const byte * ReadPropertyIdsForScopeSlotArray(const byte * current, FunctionBody * function)
  2576. {
  2577. if (function->scopeSlotArraySize == 0)
  2578. {
  2579. return current;
  2580. }
  2581. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2582. int constant;
  2583. current = ReadInt32(current, &constant);
  2584. Assert(constant == magicStartOfPropertyIdsForScopeSlotArray);
  2585. #endif
  2586. function->propertyIdsForScopeSlotArray = RecyclerNewArrayLeaf(scriptContext->GetRecycler(), Js::PropertyId, function->scopeSlotArraySize);
  2587. for (uint i = 0; i < function->scopeSlotArraySize; i++)
  2588. {
  2589. int value;
  2590. current = ReadInt32(current, &value);
  2591. PropertyId propertyId = function->GetByteCodeCache()->LookupPropertyId(value);
  2592. function->propertyIdsForScopeSlotArray[i] = propertyId;
  2593. }
  2594. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2595. current = ReadInt32(current, &constant);
  2596. Assert(constant == magicEndOfPropertyIdsForScopeSlotArray);
  2597. #endif
  2598. return current;
  2599. }
  2600. const byte * ReadSlotArrayDebuggerScopeProperties(const byte * current, FunctionBody* function, DebuggerScope* debuggerScope, uint propertyCount)
  2601. {
  2602. Assert(function);
  2603. Assert(debuggerScope);
  2604. if (propertyCount == 0)
  2605. {
  2606. return current;
  2607. }
  2608. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2609. int constant;
  2610. current = ReadInt32(current, &constant);
  2611. Assert(constant == magicStartOfDebuggerScopeProperties);
  2612. #endif // BYTE_CODE_MAGIC_CONSTANTS
  2613. for (uint i = 0u; i < propertyCount; ++i)
  2614. {
  2615. // Read the slot array index and property ID for each property (for heap enum to use). The remaining properties
  2616. // are needed for the debugger and will be filled in when generating byte code.
  2617. int value;
  2618. current = ReadInt32(current, &value);
  2619. RegSlot slotIndex = value;
  2620. current = ReadInt32(current, &value);
  2621. PropertyId propertyId = function->GetByteCodeCache()->LookupPropertyId(value);
  2622. debuggerScope->AddProperty(slotIndex, propertyId, DebuggerScopePropertyFlags_None);
  2623. }
  2624. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2625. current = ReadInt32(current, &constant);
  2626. Assert(constant == magicEndOfDebuggerScopeProperties);
  2627. #endif // BYTE_CODE_MAGIC_CONSTANTS
  2628. return current;
  2629. }
  2630. const byte * ReadSlotArrayDebuggerScopes(const byte * current, FunctionBody * function, uint debuggerScopeCount)
  2631. {
  2632. Assert(function);
  2633. if (debuggerScopeCount == 0)
  2634. {
  2635. return current;
  2636. }
  2637. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2638. int constant;
  2639. current = ReadInt32(current, &constant);
  2640. Assert(constant == magicStartOfDebuggerScopes);
  2641. #endif // BYTE_CODE_MAGIC_CONSTANTS
  2642. AssertMsg(function->GetScopeObjectChain() == nullptr, "Scope chain should not exist before deserialization.");
  2643. function->SetScopeObjectChain(RecyclerNew(scriptContext->GetRecycler(), ScopeObjectChain, scriptContext->GetRecycler()));
  2644. int currentScopeOffset = 0;
  2645. for (uint i = 0u; i < debuggerScopeCount; i++)
  2646. {
  2647. int scopeIndex;
  2648. current = ReadInt32(current, &scopeIndex);
  2649. DebuggerScope* slotArrayDebuggerScope = nullptr;
  2650. AssertMsg(currentScopeOffset <= scopeIndex, "Scope indices were not inserted into the serialized byte code in ascending order.");
  2651. while (currentScopeOffset <= scopeIndex)
  2652. {
  2653. // Fill the chain with dummy scopes until we reach the slot array scope we're on.
  2654. // These non-slot array scopes are only needed for the debugger and will be filled in
  2655. // properly during byte code generation (when attaching).
  2656. // We also don't need to worry about the parenting/sibling chain, as this will be built when
  2657. // generating bytecode as well.
  2658. slotArrayDebuggerScope = function->AddScopeObject(Js::DiagUnknownScope, 0, Constants::NoRegister);
  2659. ++currentScopeOffset;
  2660. }
  2661. Assert(slotArrayDebuggerScope);
  2662. // Create the slot array properties.
  2663. int propertyCount;
  2664. current = ReadInt32(current, &propertyCount);
  2665. current = ReadSlotArrayDebuggerScopeProperties(current, function, slotArrayDebuggerScope, propertyCount);
  2666. }
  2667. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2668. current = ReadInt32(current, &constant);
  2669. Assert(constant == magicEndOfDebuggerScopes);
  2670. #endif // BYTE_CODE_MAGIC_CONSTANTS
  2671. return current;
  2672. }
  2673. const byte * ReadCacheIdToPropertyIdMap(const byte * current, FunctionBody * function)
  2674. {
  2675. uint count = function->GetInlineCacheCount();
  2676. if (count == 0)
  2677. {
  2678. return current;
  2679. }
  2680. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2681. int constant;
  2682. current = ReadInt32(current, &constant);
  2683. Assert(constant == magicStartOfCacheIdToPropIdMap);
  2684. #endif
  2685. function->CreateCacheIdToPropertyIdMap();
  2686. for (uint i = 0; i < count; i++)
  2687. {
  2688. int value;
  2689. current = ReadInt32(current, &value);
  2690. PropertyId propertyId = function->GetByteCodeCache()->LookupPropertyId(value);
  2691. function->SetPropertyIdForCacheId(i, propertyId);
  2692. }
  2693. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2694. current = ReadInt32(current, &constant);
  2695. Assert(constant == magicEndOfCacheIdToPropIdMap);
  2696. #endif
  2697. #if DBG
  2698. function->VerifyCacheIdToPropertyIdMap();
  2699. #endif
  2700. return current;
  2701. }
  2702. const byte * ReadReferencedPropertyIdMap(const byte * current, FunctionBody * function)
  2703. {
  2704. uint count = function->GetReferencedPropertyIdCount();
  2705. if (count == 0)
  2706. {
  2707. return current;
  2708. }
  2709. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2710. int constant;
  2711. current = ReadInt32(current, &constant);
  2712. Assert(constant == magicStartOfReferencedPropIdMap);
  2713. #endif
  2714. function->CreateReferencedPropertyIdMap();
  2715. for (uint i = 0; i < count; i++)
  2716. {
  2717. int value;
  2718. current = ReadInt32(current, &value);
  2719. PropertyId propertyId = function->GetByteCodeCache()->LookupNonBuiltinPropertyId(value);
  2720. function->SetReferencedPropertyIdWithMapIndex(i, propertyId);
  2721. }
  2722. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2723. current = ReadInt32(current, &constant);
  2724. Assert(constant == magicEndOfReferencedPropIdMap);
  2725. #endif
  2726. #if DBG
  2727. function->VerifyReferencedPropertyIdMap();
  2728. #endif
  2729. return current;
  2730. }
  2731. // Read a growing Uint32 array
  2732. const byte * ReadGrowingUint32Array(const byte * current, JsUtil::GrowingUint32HeapArray ** arr)
  2733. {
  2734. int count = 0;
  2735. current = ReadInt32(current, &count);
  2736. if (count == 0)
  2737. {
  2738. (*arr) = nullptr;
  2739. return current;
  2740. }
  2741. (*arr) = JsUtil::GrowingUint32HeapArray::Create(/*length=*/count);
  2742. js_memcpy_s((*arr)->GetBuffer(), count * sizeof(uint32), current, count*sizeof(uint32));
  2743. (*arr)->SetCount(count);
  2744. current += count * sizeof(uint32);
  2745. return current;
  2746. }
  2747. // Read a small span sequence
  2748. const byte * ReadSmallSpanSequence(const byte * current, SmallSpanSequence ** smallSpanSequence)
  2749. {
  2750. (*smallSpanSequence) = HeapNew(SmallSpanSequence);
  2751. current = ReadInt32(current, &(*smallSpanSequence)->baseValue);
  2752. current = ReadGrowingUint32Array(current, &(*smallSpanSequence)->pStatementBuffer); // CONSIDER: It would be really nice to change GrowingUint32Array to something with a fixed, readonly layout
  2753. current = ReadGrowingUint32Array(current, &(*smallSpanSequence)->pActualOffsetList);
  2754. return current;
  2755. }
  2756. void ReadSourceInfo(const byte * functionBytes, int& lineNumber, int& columnNumber, bool& m_isEval, bool& m_isDynamicFunction)
  2757. {
  2758. int displayNameId;
  2759. unsigned int bitflags;
  2760. this->ReadFunctionBodyHeader(functionBytes, displayNameId, lineNumber, columnNumber, bitflags);
  2761. m_isEval = (bitflags & ffIsEval) ? true : false;
  2762. m_isDynamicFunction = (bitflags & ffIsDynamicFunction) ? true : false;
  2763. }
  2764. const byte * ReadFunctionBodyHeader(const byte * functionBytes, int& displayNameId, int& lineNumber, int& columnNumber, unsigned int& bitflags)
  2765. {
  2766. serialization_alignment SerializedFieldList* definedFields = (serialization_alignment SerializedFieldList*) functionBytes;
  2767. // Basic function body constructor arguments
  2768. const byte * current = functionBytes + sizeof(serialization_alignment SerializedFieldList);
  2769. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2770. int constant;
  2771. current = ReadInt32(current, &constant);
  2772. Assert(constant == magicStartOfFunctionBody);
  2773. #endif
  2774. current = ReadInt32(current, &displayNameId);
  2775. if (definedFields->has_m_lineNumber)
  2776. {
  2777. current = ReadInt32(current, &lineNumber);
  2778. }
  2779. else
  2780. {
  2781. lineNumber = 0;
  2782. }
  2783. if (definedFields->has_m_columnNumber)
  2784. {
  2785. current = ReadInt32(current, &columnNumber);
  2786. }
  2787. else
  2788. {
  2789. columnNumber = 0;
  2790. }
  2791. current = ReadUInt32(current, &bitflags);
  2792. return current;
  2793. }
  2794. #ifndef TEMP_DISABLE_ASMJS
  2795. const byte * ReadAsmJsFunctionInfo(const byte * current, FunctionBody * function)
  2796. {
  2797. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2798. int constant;
  2799. current = ReadInt32(current, &constant);
  2800. Assert(constant == magicStartOfAsmJsFuncInfo);
  2801. #endif
  2802. AsmJsFunctionInfo* funcInfo = function->AllocateAsmJsFunctionInfo();
  2803. int retVal;
  2804. current = ReadInt32(current, &retVal);
  2805. funcInfo->SetReturnType(AsmJsRetType((AsmJsRetType::Which)retVal));
  2806. int count;
  2807. current = ReadInt32(current, &count);
  2808. funcInfo->SetIntConstCount(count);
  2809. current = ReadInt32(current, &count);
  2810. funcInfo->SetDoubleConstCount(count);
  2811. current = ReadInt32(current, &count);
  2812. funcInfo->SetFloatConstCount(count);
  2813. ArgSlot argCount;
  2814. current = ReadUInt16(current, &argCount);
  2815. funcInfo->SetArgCount(argCount);
  2816. ArgSlot argByteSize;
  2817. current = ReadUInt16(current, &argByteSize);
  2818. funcInfo->SetArgByteSize(argByteSize);
  2819. current = ReadInt32(current, &count);
  2820. funcInfo->SetIntVarCount(count);
  2821. current = ReadInt32(current, &count);
  2822. funcInfo->SetDoubleVarCount(count);
  2823. current = ReadInt32(current, &count);
  2824. funcInfo->SetFloatVarCount(count);
  2825. current = ReadInt32(current, &count);
  2826. funcInfo->SetIntTmpCount(count);
  2827. current = ReadInt32(current, &count);
  2828. funcInfo->SetDoubleTmpCount(count);
  2829. current = ReadInt32(current, &count);
  2830. funcInfo->SetFloatTmpCount(count);
  2831. ArgSlot argSizeArrayLength;
  2832. current = ReadUInt16(current, &argSizeArrayLength);
  2833. funcInfo->SetArgSizeArrayLength(argSizeArrayLength);
  2834. uint* argArray = RecyclerNewArrayLeafZ(scriptContext->GetRecycler(), uint, argSizeArrayLength);
  2835. funcInfo->SetArgsSizesArray(argArray);
  2836. for (int i = 0; i < argSizeArrayLength; i++)
  2837. {
  2838. int32 size;
  2839. current = ReadConstantSizedInt32(current, &size);
  2840. argArray[i] = (uint32)size;
  2841. }
  2842. if (argCount > 0)
  2843. {
  2844. AsmJsVarType::Which * typeArray = RecyclerNewArrayLeaf(scriptContext->GetRecycler(), AsmJsVarType::Which, argCount);
  2845. funcInfo->SetArgTypeArray(typeArray);
  2846. for (uint i = 0; i < argCount; i++)
  2847. {
  2848. current = ReadByte(current, (byte*)&typeArray[i]);
  2849. }
  2850. }
  2851. current = ReadInt32(current, &count);
  2852. funcInfo->SetIntByteOffset(count);
  2853. current = ReadInt32(current, &count);
  2854. funcInfo->SetDoubleByteOffset(count);
  2855. current = ReadInt32(current, &count);
  2856. funcInfo->SetFloatByteOffset(count);
  2857. bool boolVal;
  2858. current = ReadBool(current, &boolVal);
  2859. funcInfo->SetIsHeapBufferConst(boolVal);
  2860. current = ReadBool(current, &boolVal);
  2861. funcInfo->SetUsesHeapBuffer(boolVal);
  2862. current = ReadInt32(current, &count);
  2863. funcInfo->SetSimdConstCount(count);
  2864. current = ReadInt32(current, &count);
  2865. funcInfo->SetSimdVarCount(count);
  2866. current = ReadInt32(current, &count);
  2867. funcInfo->SetSimdTmpCount(count);
  2868. current = ReadInt32(current, &count);
  2869. funcInfo->SetSimdByteOffset(count);
  2870. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2871. current = ReadInt32(current, &constant);
  2872. Assert(constant == magicEndOfAsmJsFuncInfo);
  2873. #endif
  2874. return current;
  2875. }
  2876. const byte * ReadAsmJsModuleInfo(const byte * current, FunctionBody * function)
  2877. {
  2878. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  2879. int constant;
  2880. current = ReadInt32(current, &constant);
  2881. Assert(constant == magicStartOfAsmJsModuleInfo);
  2882. #endif
  2883. AsmJsModuleInfo* moduleInfo = function->AllocateAsmJsModuleInfo();
  2884. int count;
  2885. current = ReadInt32(current, &count);
  2886. moduleInfo->SetArgInCount(count);
  2887. int exportsCount;
  2888. current = ReadInt32(current, &exportsCount);
  2889. moduleInfo->SetExportsCount(exportsCount);
  2890. current = ReadInt32(current, &count);
  2891. moduleInfo->InitializeSlotMap(count);
  2892. current = ReadInt32(current, &count);
  2893. moduleInfo->SetSimdRegCount(count);
  2894. int id;
  2895. if (exportsCount > 0)
  2896. {
  2897. PropertyIdArray * propArray = moduleInfo->GetExportsIdArray();
  2898. bool boolVal;
  2899. current = ReadBool(current, &boolVal);
  2900. propArray->hadDuplicates = boolVal;
  2901. current = ReadBool(current, &boolVal);
  2902. propArray->has__proto__ = boolVal;
  2903. current = ReadInt32(current, &count);
  2904. propArray->count = count;
  2905. for (uint i = 0; i < propArray->count; i++)
  2906. {
  2907. current = ReadInt32(current, &id);
  2908. PropertyId propertyId = function->GetByteCodeCache()->LookupPropertyId(id);
  2909. propArray->elements[i] = propertyId;
  2910. }
  2911. RegSlot* exportLocations = moduleInfo->GetExportsFunctionLocation();
  2912. for (int i = 0; i < exportsCount; i++)
  2913. {
  2914. int32 loc;
  2915. current = ReadConstantSizedInt32(current, &loc);
  2916. exportLocations[i] = (uint32)loc;
  2917. }
  2918. }
  2919. RegSlot regSlot;
  2920. current = ReadUInt32(current, &regSlot);
  2921. moduleInfo->SetExportFunctionIndex(regSlot);
  2922. current = ReadInt32(current, &count);
  2923. moduleInfo->SetVarCount(count);
  2924. for (int i = 0; i < count; i++)
  2925. {
  2926. serialization_alignment AsmJsModuleInfo::ModuleVar * modVar = (serialization_alignment AsmJsModuleInfo::ModuleVar*)current;
  2927. moduleInfo->SetVar(i, *modVar);
  2928. current = current + sizeof(serialization_alignment AsmJsModuleInfo::ModuleVar);
  2929. }
  2930. current = ReadInt32(current, &count);
  2931. moduleInfo->SetVarImportCount(count);
  2932. AsmJsModuleInfo::ModuleVarImport varImport;
  2933. for (int i = 0; i < count; i++)
  2934. {
  2935. current = ReadUInt32(current, &varImport.location);
  2936. current = ReadByte(current, (byte*)&varImport.type);
  2937. current = ReadInt32(current, &id);
  2938. varImport.field = function->GetByteCodeCache()->LookupPropertyId(id);
  2939. moduleInfo->SetVarImport(i, varImport);
  2940. }
  2941. current = ReadInt32(current, &count);
  2942. moduleInfo->SetFunctionImportCount(count);
  2943. AsmJsModuleInfo::ModuleFunctionImport funcImport;
  2944. for (int i = 0; i < count; i++)
  2945. {
  2946. current = ReadUInt32(current, &funcImport.location);
  2947. current = ReadInt32(current, &id);
  2948. funcImport.field = function->GetByteCodeCache()->LookupPropertyId(id);
  2949. moduleInfo->SetFunctionImport(i, funcImport);
  2950. }
  2951. current = ReadInt32(current, &count);
  2952. moduleInfo->SetFunctionCount(count);
  2953. AsmJsModuleInfo::ModuleFunction modFunc;
  2954. for (int i = 0; i < count; i++)
  2955. {
  2956. current = ReadUInt32(current, &modFunc.location);
  2957. moduleInfo->SetFunction(i, modFunc);
  2958. }
  2959. current = ReadInt32(current, &count);
  2960. moduleInfo->SetFunctionTableCount(count);
  2961. AsmJsModuleInfo::ModuleFunctionTable funcTable;
  2962. for (int i = 0; i < count; i++)
  2963. {
  2964. current = ReadUInt32(current, &funcTable.size);
  2965. if (funcTable.size > 0)
  2966. {
  2967. funcTable.moduleFunctionIndex = RecyclerNewArray(this->scriptContext->GetRecycler(), RegSlot, funcTable.size);
  2968. }
  2969. else
  2970. {
  2971. funcTable.moduleFunctionIndex = nullptr;
  2972. }
  2973. for (uint j = 0; j < funcTable.size; j++)
  2974. {
  2975. current = ReadConstantSizedInt32(current, (int32*)&funcTable.moduleFunctionIndex[j]);
  2976. }
  2977. moduleInfo->SetFunctionTable(i, funcTable);
  2978. }
  2979. serialization_alignment AsmJsModuleMemory * modMem = (serialization_alignment AsmJsModuleMemory*)current;
  2980. moduleInfo->SetModuleMemory(*modMem);
  2981. current = current + sizeof(serialization_alignment AsmJsModuleMemory);
  2982. current = ReadInt32(current, &count);
  2983. for (int i = 0; i < count; i++)
  2984. {
  2985. current = ReadInt32(current, &id);
  2986. PropertyId key = function->GetByteCodeCache()->LookupPropertyId(id);
  2987. serialization_alignment AsmJsSlot * slot = (serialization_alignment AsmJsSlot*)current;
  2988. current = current + sizeof(serialization_alignment AsmJsSlot);
  2989. // copy the slot to recycler memory
  2990. AsmJsSlot * recyclerSlot = RecyclerNew(scriptContext->GetRecycler(), AsmJsSlot);
  2991. *recyclerSlot = *slot;
  2992. moduleInfo->GetAsmJsSlotMap()->Add(key, recyclerSlot);
  2993. }
  2994. serialization_alignment BVStatic<ASMMATH_BUILTIN_SIZE> * mathBV = (serialization_alignment BVStatic<ASMMATH_BUILTIN_SIZE>*)current;
  2995. current = current + sizeof(serialization_alignment BVStatic<ASMMATH_BUILTIN_SIZE>);
  2996. moduleInfo->SetAsmMathBuiltinUsed(*mathBV);
  2997. serialization_alignment BVStatic<ASMARRAY_BUILTIN_SIZE> * arrayBV = (serialization_alignment BVStatic<ASMARRAY_BUILTIN_SIZE>*)current;
  2998. current = current + sizeof(serialization_alignment BVStatic<ASMARRAY_BUILTIN_SIZE>);
  2999. moduleInfo->SetAsmArrayBuiltinUsed(*arrayBV);
  3000. serialization_alignment BVStatic<ASMSIMD_BUILTIN_SIZE> * simdBV = (serialization_alignment BVStatic<ASMSIMD_BUILTIN_SIZE>*)current;
  3001. current = current + sizeof(serialization_alignment BVStatic<ASMSIMD_BUILTIN_SIZE>);
  3002. moduleInfo->SetAsmSimdBuiltinUsed(*simdBV);
  3003. uint maxAccess;
  3004. current = ReadUInt32(current, &maxAccess);
  3005. moduleInfo->SetMaxHeapAccess(maxAccess);
  3006. bool usesChangeHeap;
  3007. current = ReadBool(current, &usesChangeHeap);
  3008. moduleInfo->SetUsesChangeHeap(usesChangeHeap);
  3009. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3010. current = ReadInt32(current, &constant);
  3011. Assert(constant == magicEndOfAsmJsModuleInfo);
  3012. #endif
  3013. return current;
  3014. }
  3015. #endif
  3016. // Read a function body
  3017. HRESULT ReadFunctionBody(const byte * functionBytes, FunctionProxy ** functionProxy, Utf8SourceInfo* sourceInfo, ByteCodeCache * cache, NativeModule *nativeModule, bool deserializeThis, bool deserializeNested = true, Js::DeferDeserializeFunctionInfo* deferDeserializeFunctionInfo = NULL)
  3018. {
  3019. Assert(sourceInfo->GetSrcInfo()->moduleID == kmodGlobal);
  3020. int displayNameId;
  3021. int lineNumber;
  3022. int columnNumber;
  3023. unsigned int bitflags;
  3024. const byte * current = this->ReadFunctionBodyHeader(functionBytes, displayNameId, lineNumber, columnNumber, bitflags);
  3025. serialization_alignment SerializedFieldList* definedFields = (serialization_alignment SerializedFieldList*) functionBytes;
  3026. auto displayName = deferDeserializeFunctionInfo != nullptr ?
  3027. deferDeserializeFunctionInfo->GetDisplayName() :
  3028. GetString16ById(displayNameId);
  3029. uint displayNameLength = deferDeserializeFunctionInfo ? deferDeserializeFunctionInfo->GetDisplayNameLength() : GetString16LengthById(displayNameId);
  3030. uint displayShortNameOffset = deferDeserializeFunctionInfo ? deferDeserializeFunctionInfo->GetShortDisplayNameOffset() : 0;
  3031. int functionId;
  3032. current = ReadInt32(current, &functionId);
  3033. int serializationIndex;
  3034. current = ReadInt32(current, &serializationIndex);
  3035. int32 attributes;
  3036. current = ReadInt32(current, &attributes);
  3037. uint32 offsetIntoSource = 0;
  3038. current = ReadUInt32(current, &offsetIntoSource);
  3039. int nestedCount = 0;
  3040. if (definedFields->has_m_nestedCount)
  3041. {
  3042. current = ReadInt32(current, &nestedCount);
  3043. }
  3044. if (!deserializeThis)
  3045. {
  3046. Assert(sourceInfo->GetSrcInfo()->moduleID == kmodGlobal);
  3047. Assert(!deserializeNested);
  3048. *functionProxy = DeferDeserializeFunctionInfo::New(this->scriptContext, nestedCount, functionId, cache, functionBytes, sourceInfo, displayName, displayNameLength, displayShortNameOffset, nativeModule, (FunctionInfo::Attributes)attributes);
  3049. return S_OK;
  3050. }
  3051. ParseableFunctionInfo **function = (ParseableFunctionInfo **) functionProxy;
  3052. uint functionNumber;
  3053. if (deferDeserializeFunctionInfo)
  3054. {
  3055. functionNumber = deferDeserializeFunctionInfo->GetFunctionNumber();
  3056. }
  3057. else
  3058. {
  3059. functionNumber = scriptContext->GetThreadContext()->NewFunctionNumber();
  3060. }
  3061. if (definedFields->has_m_constCount)
  3062. {
  3063. FunctionBody **functionBody = (FunctionBody **) function;
  3064. *functionBody = FunctionBody::NewFromRecycler(this->scriptContext, nullptr /*displayName*/, 0 /*displayNameLength*/, 0 /*displayShortNameOffset*/, nestedCount,
  3065. sourceInfo,
  3066. functionNumber,
  3067. sourceInfo->GetSrcInfo()->sourceContextInfo->sourceContextId,
  3068. firstFunctionId + functionId, nullptr, (FunctionInfo::Attributes)attributes
  3069. #ifdef PERF_COUNTERS
  3070. , (deferDeserializeFunctionInfo != nullptr)
  3071. #endif
  3072. );
  3073. (*functionBody)->SetDisplayName(displayName, displayNameLength, displayShortNameOffset, FunctionProxy::SetDisplayNameFlags::SetDisplayNameFlagsDontCopy);
  3074. (*functionBody)->serializationIndex = serializationIndex;
  3075. (*functionBody)->byteCodeCache = cache;
  3076. (*functionBody)->m_utf8SourceInfo = utf8SourceInfo; // Set source info
  3077. (*function)->m_utf8SourceHasBeenSet = true;
  3078. }
  3079. else
  3080. {
  3081. *function = ParseableFunctionInfo::New(this->scriptContext, nestedCount, firstFunctionId + functionId, utf8SourceInfo, displayName, displayNameLength, displayShortNameOffset, nullptr, (FunctionInfo::Attributes)attributes);
  3082. }
  3083. // These fields are manually deserialized previously
  3084. (*function)->m_lineNumber = lineNumber;
  3085. (*function)->m_columnNumber = columnNumber;
  3086. (*function)->m_isDeclaration = (bitflags & ffIsDeclaration) ? true : false;
  3087. (*function)->m_hasImplicitArgIns = (bitflags & ffHasImplicitArgsIn) ? true : false;
  3088. (*function)->m_isAccessor = (bitflags & ffIsAccessor) ? true : false;
  3089. (*function)->m_isStaticNameFunction = (bitflags & ffIsStaticNameFunction) ? true : false;
  3090. (*function)->m_isNamedFunctionExpression = (bitflags & ffIsNamedFunctionExpression) ? true : false;
  3091. (*function)->m_isNameIdentifierRef = (bitflags & ffIsNameIdentifierRef ) ? true : false;
  3092. (*function)->m_isGlobalFunc = (bitflags & ffIsGlobalFunc) ? true : false;
  3093. (*function)->m_dontInline = (bitflags & ffDontInline) ? true : false;
  3094. (*function)->m_isStrictMode = (bitflags & ffIsStrictMode) ? true : false;
  3095. (*function)->m_doBackendArgumentsOptimization = (bitflags & ffDoBackendArgumentsOptimization) ? true : false;
  3096. (*function)->m_isEval = (bitflags & ffIsEval) ? true : false;
  3097. (*function)->m_isDynamicFunction = (bitflags & ffIsDynamicFunction) ? true : false;
  3098. // This is offsetIntoSource is the start offset in bytes as well.
  3099. (*function)->m_cbStartOffset = (size_t) offsetIntoSource;
  3100. (*function)->m_sourceIndex = this->sourceIndex;
  3101. #define DEFINE_FUNCTION_PROXY_FIELDS 1
  3102. #define DEFINE_PARSEABLE_FUNCTION_INFO_FIELDS 1
  3103. #define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) \
  3104. if (definedFields->has_##name == true) { \
  3105. current = Read##serializableType(current, &(*function)->##name); \
  3106. }
  3107. #define DECLARE_MANUAL_SERIALIZABLE_FIELD(type, name, serializableType, deserializeHere) \
  3108. if (deserializeHere && definedFields->has_##name == true) { \
  3109. current = Read##serializableType(current, &(*function)->##name); \
  3110. }
  3111. #include "SerializableFunctionFields.h"
  3112. if (definedFields->has_m_constCount)
  3113. {
  3114. FunctionBody **functionBody = (FunctionBody **)function;
  3115. #define DEFINE_FUNCTION_BODY_FIELDS 1
  3116. #define DECLARE_SERIALIZABLE_FIELD(type, name, serializableType) \
  3117. if (definedFields->has_##name == true) { \
  3118. current = Read##serializableType(current, &(*functionBody)->##name); \
  3119. }
  3120. #define DECLARE_MANUAL_SERIALIZABLE_FIELD(type, name, serializableType, deserializeHere) \
  3121. if (deserializeHere && definedFields->has_##name == true) { \
  3122. current = Read##serializableType(current, &(*functionBody)->##name); \
  3123. }
  3124. #include "SerializableFunctionFields.h"
  3125. // TODO-STACK-NESTED-FUNC: Defer deserialize function doesn't have parent pointer, can't do stack nested func yet
  3126. // The flags field is set to by default to Flags_HasNoExplicitReturnValue which means if it's serialized, the field will be set
  3127. // in the definedFields struct. If it's not set, that means that the flag was explicitly set to Flags_None so we'll have to set
  3128. // that here.
  3129. if (definedFields->has_flags == false)
  3130. {
  3131. (*functionBody)->flags = FunctionBody::FunctionBodyFlags::Flags_None;
  3132. }
  3133. else
  3134. {
  3135. (*functionBody)->flags = (FunctionBody::FunctionBodyFlags)((*functionBody)->flags & ~FunctionBody::Flags_StackNestedFunc);
  3136. }
  3137. if (definedFields->has_m_firstTmpReg == false)
  3138. {
  3139. (*functionBody)->m_firstTmpReg = 0;
  3140. }
  3141. if (definedFields->has_m_envDepth == false)
  3142. {
  3143. (*functionBody)->m_envDepth = 0;
  3144. }
  3145. if (deserializeThis && !deserializeNested)
  3146. {
  3147. (*functionBody)->m_isPartialDeserializedFunction = true;
  3148. }
  3149. (*functionBody)->FinishSourceInfo(); // SourceInfo is complete. Register this functionBody to utf8SourceInfo.
  3150. (*functionBody)->m_isFuncRegistered = (bitflags & ffIsFuncRegistered) ? true : false;
  3151. (*functionBody)->m_hasAllNonLocalReferenced = (bitflags & ffhasAllNonLocalReferenced) ? true : false;
  3152. (*functionBody)->m_hasSetIsObject = (bitflags & ffhasSetIsObject) ? true : false;
  3153. (*functionBody)->m_CallsEval = (bitflags & ffhasSetCallsEval) ? true : false;
  3154. (*functionBody)->m_ChildCallsEval = (bitflags & ffChildCallsEval) ? true : false;
  3155. (*functionBody)->m_hasReferenceableBuiltInArguments = (bitflags & ffHasReferenceableBuiltInArguments) ? true : false;
  3156. #ifndef TEMP_DISABLE_ASMJS
  3157. (*functionBody)->m_isAsmJsFunction = (bitflags & ffIsAsmJsFunction) ? true : false;
  3158. (*functionBody)->m_isAsmjsMode = (bitflags & ffIsAsmJsMode) ? true : false;
  3159. #endif
  3160. byte loopHeaderExists;
  3161. current = ReadByte(current, &loopHeaderExists);
  3162. if (loopHeaderExists)
  3163. {
  3164. (*functionBody)->AllocateLoopHeaders();
  3165. for (uint i = 0; i < (*functionBody)->loopCount; ++i)
  3166. {
  3167. uint startOffset, endOffset;
  3168. current = ReadUInt32(current, &startOffset);
  3169. current = ReadUInt32(current, &endOffset);
  3170. (*functionBody)->loopHeaderArray[i].startOffset = startOffset;
  3171. (*functionBody)->loopHeaderArray[i].endOffset = endOffset;
  3172. }
  3173. }
  3174. byte asmJsInfoExists;
  3175. current = ReadByte(current, &asmJsInfoExists);
  3176. #ifndef TEMP_DISABLE_ASMJS
  3177. if (asmJsInfoExists == 1)
  3178. {
  3179. current = ReadAsmJsFunctionInfo(current, *functionBody);
  3180. }
  3181. else if (asmJsInfoExists == 2)
  3182. {
  3183. current = ReadAsmJsModuleInfo(current, *functionBody);
  3184. }
  3185. else
  3186. #endif
  3187. {
  3188. Assert(asmJsInfoExists == 0);
  3189. }
  3190. // Read constants table
  3191. #ifndef TEMP_DISABLE_ASMJS
  3192. if ((*functionBody)->GetIsAsmJsFunction())
  3193. {
  3194. current = ReadAsmJsConstantsTable(current, *functionBody);
  3195. }
  3196. else
  3197. #endif
  3198. {
  3199. current = ReadConstantsTable(current, *functionBody);
  3200. }
  3201. // Byte code
  3202. current = ReadByteBlock(current, &(*functionBody)->byteCodeBlock);
  3203. // Auxiliary
  3204. current = ReadAuxiliary(current, *functionBody);
  3205. // Inline cache
  3206. current = ReadCacheIdToPropertyIdMap(current, *functionBody);
  3207. current = ReadReferencedPropertyIdMap(current, *functionBody);
  3208. (*functionBody)->AllocateInlineCache();
  3209. current = ReadPropertyIdsForScopeSlotArray(current, *functionBody);
  3210. uint debuggerScopeCount = 0;
  3211. current = ReadUInt32(current, &debuggerScopeCount);
  3212. current = ReadSlotArrayDebuggerScopes(current, *functionBody, debuggerScopeCount);
  3213. (*functionBody)->AllocateObjectLiteralTypeArray();
  3214. // Literal regexes
  3215. (*functionBody)->AllocateLiteralRegexArray();
  3216. for (uint i = 0; i < (*functionBody)->literalRegexCount; ++i)
  3217. {
  3218. int length;
  3219. current = ReadInt32(current, &length);
  3220. if (length == -1)
  3221. {
  3222. Assert(!(*functionBody)->GetLiteralRegex(i));
  3223. continue;
  3224. }
  3225. int sourceId;
  3226. current = ReadInt32(current, &sourceId);
  3227. const auto source = GetString16ById(sourceId);
  3228. UnifiedRegex::RegexFlags flags;
  3229. CompileAssert(sizeof(flags) == sizeof(byte));
  3230. current = ReadByte(current, reinterpret_cast<byte *>(&flags));
  3231. (*functionBody)->SetLiteralRegex(i, RegexHelper::CompileDynamic(scriptContext, source, length, flags, true));
  3232. }
  3233. // Read source information
  3234. current = ReadSmallSpanSequence(current, &(*functionBody)->m_sourceInfo.pSpanSequence);
  3235. (*functionBody)->InitializeExecutionModeAndLimits();
  3236. }
  3237. // Read lexically nested functions
  3238. if (nestedCount)
  3239. {
  3240. for(auto i = 0; i<nestedCount; ++i)
  3241. {
  3242. const byte * nestedFunctionBytes;
  3243. current = ReadOffsetAsPointer(current, &nestedFunctionBytes);
  3244. if (nestedFunctionBytes == nullptr)
  3245. {
  3246. (*function)->SetNestedFunc(NULL, i, 0u);
  3247. }
  3248. else
  3249. {
  3250. FunctionProxy* nestedFunction;
  3251. // If we should deserialize nested functions, go ahead and do so
  3252. // If we shouldn't, and we're currently deserializing a function proxy
  3253. // that has been defer-deserialized, simply copy over the function proxy from
  3254. // from the old function- otherwise, create proxies for the nested functions
  3255. auto hr = ReadFunctionBody(nestedFunctionBytes, &nestedFunction, sourceInfo, cache, nativeModule, deserializeNested, deserializeNested);
  3256. if (FAILED(hr))
  3257. {
  3258. Assert(0);
  3259. return hr;
  3260. }
  3261. (*function)->SetNestedFunc(nestedFunction, i, 0u);
  3262. }
  3263. }
  3264. }
  3265. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3266. // Magical ending
  3267. int constant;
  3268. ReadInt32(current, &constant);
  3269. if (constant != magicEndOfFunctionBody)
  3270. {
  3271. Assert(constant == magicEndOfFunctionBody);
  3272. Throw::FatalInternalError();
  3273. }
  3274. #endif
  3275. if (definedFields->has_m_constCount)
  3276. {
  3277. FunctionBody **functionBody = (FunctionBody **) function;
  3278. #if DBG
  3279. if (PHASE_DUMP(Js::DebuggerScopePhase, (*functionBody)))
  3280. {
  3281. (*functionBody)->DumpScopes();
  3282. }
  3283. #endif
  3284. #if ENABLE_NATIVE_CODEGEN
  3285. if ((!PHASE_OFF(Js::BackEndPhase, *functionBody))
  3286. && !this->scriptContext->GetConfig()->IsNoNative()
  3287. && !(*functionBody)->GetIsAsmjsMode())
  3288. {
  3289. GenerateFunction(this->scriptContext->GetNativeCodeGenerator(), *functionBody);
  3290. }
  3291. #endif // ENABLE_NATIVE_CODEGEN
  3292. (*functionBody)->m_isPartialDeserializedFunction = false;
  3293. }
  3294. else
  3295. {
  3296. *function = (*function)->Parse(nullptr, true);
  3297. }
  3298. return S_OK;
  3299. }
  3300. // Read the top function body.
  3301. HRESULT ReadTopFunctionBody(FunctionBody** function, Utf8SourceInfo* sourceInfo, ByteCodeCache * cache, bool allowDefer, NativeModule *nativeModule)
  3302. {
  3303. auto topFunction = ReadInt32(functions, &functionCount);
  3304. firstFunctionId = sourceInfo->GetSrcInfo()->sourceContextInfo->nextLocalFunctionId;
  3305. sourceInfo->GetSrcInfo()->sourceContextInfo->nextLocalFunctionId += functionCount;
  3306. sourceInfo->EnsureInitialized(functionCount);
  3307. sourceInfo->GetSrcInfo()->sourceContextInfo->EnsureInitialized();
  3308. #if ENABLE_NATIVE_CODEGEN && defined(ENABLE_PREJIT)
  3309. bool prejit = false;
  3310. prejit = (!scriptContext->GetConfig()->IsNoNative() && Js::Configuration::Global.flags.Prejit && nativeModule == nullptr);
  3311. allowDefer = allowDefer && !prejit;
  3312. #endif
  3313. FunctionBody* functionBody = NULL;
  3314. auto result = ReadFunctionBody(topFunction, (FunctionProxy **)&functionBody, sourceInfo, cache, nativeModule, true, !allowDefer /* don't deserialize nested if defer is allowed */);
  3315. (*function) = functionBody;
  3316. #if ENABLE_NATIVE_CODEGEN && defined(ENABLE_PREJIT)
  3317. if (prejit)
  3318. {
  3319. Assert(!allowDefer);
  3320. GenerateAllFunctions(scriptContext->GetNativeCodeGenerator(), functionBody);
  3321. }
  3322. #endif
  3323. return result;
  3324. }
  3325. // Deserialize and save a PropertyIdArray
  3326. const byte *
  3327. DeserializePropertyIdArray(ScriptContext * scriptContext, const byte * buffer, ByteBlock * deserializeInto, FunctionBody * functionBody)
  3328. {
  3329. auto serialized = (serialization_alignment const Js::SerializedPropertyIdArray *)buffer;
  3330. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3331. Assert(serialized->magic == magicStartOfAuxPropIdArray);
  3332. #endif
  3333. auto propertyCount = serialized->propertyCount;
  3334. auto extraSlotCount = serialized->extraSlots;
  3335. Assert(serialized->offset + sizeof(PropertyIdArray) < deserializeInto->GetLength());
  3336. auto result = (PropertyIdArray *)(deserializeInto->GetBuffer() + serialized->offset);
  3337. result->count = propertyCount;
  3338. Assert(serialized->offset + result->GetDataSize(extraSlotCount) <= deserializeInto->GetLength());
  3339. result->hadDuplicates = serialized->hadDuplicates;
  3340. result->has__proto__ = serialized->has__proto__;
  3341. auto elements = (PropertyId*)(serialized + 1);
  3342. for(int i=0;i<propertyCount;++i)
  3343. {
  3344. result->elements[i] = functionBody->GetByteCodeCache()->LookupPropertyId(elements[i]);
  3345. }
  3346. for(int i=0;i<extraSlotCount;++i)
  3347. {
  3348. result->elements[propertyCount + i] = elements[propertyCount + i];
  3349. }
  3350. auto current = buffer +
  3351. sizeof(serialization_alignment const Js::SerializedPropertyIdArray) + (propertyCount + extraSlotCount) * sizeof(PropertyId);
  3352. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3353. int magicEnd;
  3354. current = ReadInt32(current, &magicEnd);
  3355. Assert(magicEnd == magicEndOfAuxPropIdArray);
  3356. #endif
  3357. return current;
  3358. }
  3359. // Deserialize and save a FuncInfoArray
  3360. const byte *
  3361. DeserializeFuncInfoArray(ScriptContext * scriptContext, const byte * buffer, ByteBlock * deserializeInto)
  3362. {
  3363. auto serialized = (serialization_alignment const SerializedFuncInfoArray *)buffer;
  3364. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3365. Assert(serialized->magic == magicStartOfAuxFuncInfoArray);
  3366. #endif
  3367. auto count = serialized->count;
  3368. Assert(serialized->offset + sizeof(AuxArray<FuncInfoEntry>) < deserializeInto->GetLength());
  3369. auto result = (AuxArray<FuncInfoEntry> *)(deserializeInto->GetBuffer() + serialized->offset);
  3370. result->count = count;
  3371. Assert(serialized->offset + result->GetDataSize() <= deserializeInto->GetLength());
  3372. auto elements = (int*)(serialized+1);
  3373. for(int i=0;i<count;++i)
  3374. {
  3375. result->elements[i].nestedIndex = elements[i*2];
  3376. result->elements[i].scopeSlot = elements[i*2+1];
  3377. }
  3378. auto current = buffer + sizeof(serialization_alignment const SerializedFuncInfoArray) + (count * 2 * sizeof(int));
  3379. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3380. int magicEnd;
  3381. current = ReadInt32(current, &magicEnd);
  3382. Assert(magicEnd == magicEndOfAuxFuncInfoArray);
  3383. #endif
  3384. return current;
  3385. }
  3386. // Deserialize a var array
  3387. template<typename T>
  3388. const byte * DeserializeVarArray(ScriptContext * scriptContext, const byte * buffer, ByteBlock * deserializeInto)
  3389. {
  3390. auto serialized = (serialization_alignment const Js::SerializedVarArray *)buffer;
  3391. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3392. Assert(serialized->magic == magicStartOfAuxVarArray);
  3393. #endif
  3394. Assert(serialized->offset + sizeof(T) < deserializeInto->GetLength());
  3395. auto result = (T *)(deserializeInto->GetBuffer() + serialized->offset);
  3396. uint count = serialized->varCount;
  3397. result->SetCount(count);
  3398. Assert(serialized->offset + result->GetDataSize() <= deserializeInto->GetLength());
  3399. auto content = (const byte*)(serialized + 1);
  3400. auto current = content;
  3401. for (uint index = 0; index < count; index++)
  3402. {
  3403. byte code;
  3404. current = ReadByte(current, &code);
  3405. switch(code)
  3406. {
  3407. case ctInt:
  3408. {
  3409. int value;
  3410. current = ReadConstantSizedInt32(current, &value);
  3411. result->elements[index] = Js::TaggedInt::ToVarUnchecked(value);
  3412. break;
  3413. }
  3414. case ctNumber:
  3415. {
  3416. double value;
  3417. current = ReadDouble(current, &value);
  3418. const auto number = Js::JavascriptNumber::New(value, scriptContext);
  3419. #if !FLOATVAR
  3420. scriptContext->BindReference(number);
  3421. #endif
  3422. result->elements[index] = number;
  3423. break;
  3424. }
  3425. default:
  3426. AssertMsg(UNREACHED, "Unexpected object type in VarArray");
  3427. Throw::FatalInternalError();
  3428. }
  3429. }
  3430. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3431. int magicEnd;
  3432. current = ReadInt32(current, &magicEnd);
  3433. Assert(magicEnd == magicEndOfAuxVarArray);
  3434. #endif
  3435. return current;
  3436. }
  3437. const byte * DeserializeIntArray(ScriptContext * scriptContext, const byte * buffer, ByteBlock * deserializeInto)
  3438. {
  3439. auto serialized = (serialization_alignment const Js::SerializedIntArray *)buffer;
  3440. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3441. Assert(serialized->magic == magicStartOfAuxIntArray);
  3442. #endif
  3443. Assert(serialized->offset + sizeof(AuxArray<int>) < deserializeInto->GetLength());
  3444. auto result = (AuxArray<int> *)(deserializeInto->GetBuffer() + serialized->offset);
  3445. uint count = serialized->intCount;
  3446. result->count = count;
  3447. Assert(serialized->offset + result->GetDataSize() <= deserializeInto->GetLength());
  3448. auto content = (const byte*)(serialized + 1);
  3449. auto current = content;
  3450. for (uint index = 0; index < count; index++)
  3451. {
  3452. int32 value;
  3453. current = ReadConstantSizedInt32(current, &value);
  3454. result->elements[index] = value;
  3455. }
  3456. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3457. int magicEnd;
  3458. current = ReadInt32(current, &magicEnd);
  3459. Assert(magicEnd == magicEndOfAuxIntArray);
  3460. #endif
  3461. return current;
  3462. }
  3463. const byte *
  3464. DeserializeFloatArray(ScriptContext * scriptContext, const byte * buffer, ByteBlock * deserializeInto)
  3465. {
  3466. auto serialized = (serialization_alignment const SerializedFloatArray *)buffer;
  3467. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3468. Assert(serialized->magic == magicStartOfAuxFltArray);
  3469. #endif
  3470. Assert(serialized->offset + sizeof(AuxArray<double>) < deserializeInto->GetLength());
  3471. auto result = (AuxArray<double> *)(deserializeInto->GetBuffer() + serialized->offset);
  3472. uint count = serialized->floatCount;
  3473. result->count = count;
  3474. Assert(serialized->offset + result->GetDataSize() <= deserializeInto->GetLength());
  3475. auto content = (const byte*)(serialized + 1);
  3476. auto current = content;
  3477. for (uint index = 0; index < count; index++)
  3478. {
  3479. double value;
  3480. current = ReadDouble(current, &value);
  3481. result->elements[index] = value;
  3482. }
  3483. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3484. int magicEnd;
  3485. current = ReadInt32(current, &magicEnd);
  3486. Assert(magicEnd == magicEndOfAuxFltArray);
  3487. #endif
  3488. return current;
  3489. }
  3490. };
  3491. // Construct the byte code cache. Copy things needed by inline 'Lookup' functions from reader.
  3492. ByteCodeCache::ByteCodeCache(ScriptContext * scriptContext, ByteCodeBufferReader * reader, int builtInPropertyCount)
  3493. : reader(reader), propertyCount(reader->string16Count), builtInPropertyCount(builtInPropertyCount)
  3494. {
  3495. auto alloc = scriptContext->SourceCodeAllocator();
  3496. propertyIds = AnewArray(alloc, PropertyId, propertyCount);
  3497. for (auto i=0; i < propertyCount; ++i)
  3498. {
  3499. propertyIds[i] = -1;
  3500. }
  3501. raw = reader->raw;
  3502. // Read and populate PropertyIds
  3503. for(int i=0; i < propertyCount; ++i)
  3504. {
  3505. PopulateLookupPropertyId(scriptContext, i);
  3506. }
  3507. }
  3508. // Deserialize and save a PropertyId
  3509. void ByteCodeCache::PopulateLookupPropertyId(ScriptContext * scriptContext, int realOffset)
  3510. {
  3511. PropertyId idInCache = realOffset + this->builtInPropertyCount;
  3512. bool isPropertyRecord;
  3513. auto propertyName = reader->GetString16ById(idInCache, &isPropertyRecord);
  3514. if(isPropertyRecord)
  3515. {
  3516. auto propertyNameLength = reader->GetString16LengthById(idInCache);
  3517. const Js::PropertyRecord * propertyRecord = scriptContext->GetThreadContext()->GetOrAddPropertyRecordBind(
  3518. JsUtil::CharacterBuffer<wchar_t>(propertyName, propertyNameLength));
  3519. propertyIds[realOffset] = propertyRecord->GetPropertyId();
  3520. }
  3521. }
  3522. // Serialize function body
  3523. HRESULT ByteCodeSerializer::SerializeToBuffer(ScriptContext * scriptContext, ArenaAllocator * alloc, DWORD sourceByteLength, LPCUTF8 utf8Source, DWORD dwFunctionTableLength, BYTE * functionTable, FunctionBody * function, SRCINFO const* srcInfo, bool allocateBuffer, byte ** buffer, DWORD * bufferBytes, DWORD dwFlags)
  3524. {
  3525. int builtInPropertyCount = (dwFlags & GENERATE_BYTE_CODE_BUFFER_LIBRARY) != 0 ? PropertyIds::_countJSOnlyProperty : TotalNumberOfBuiltInProperties;
  3526. Utf8SourceInfo *utf8SourceInfo = function->GetUtf8SourceInfo();
  3527. HRESULT hr = utf8SourceInfo->EnsureLineOffsetCacheNoThrow();
  3528. if (FAILED(hr))
  3529. {
  3530. return hr;
  3531. }
  3532. int32 sourceCharLength = utf8SourceInfo->GetCchLength();
  3533. ByteCodeBufferBuilder builder(sourceByteLength, sourceCharLength, utf8Source, dwFunctionTableLength, functionTable, utf8SourceInfo, scriptContext, alloc, dwFlags, builtInPropertyCount);
  3534. hr = builder.AddTopFunctionBody(function, srcInfo);
  3535. if (SUCCEEDED(hr))
  3536. {
  3537. hr = builder.Create(allocateBuffer, buffer, bufferBytes);
  3538. }
  3539. #if INSTRUMENT_BUFFER_INTS
  3540. for (int i = 0; i < 4; i++)
  3541. {
  3542. printf("[BCGENSTATS] %d, %d\n", i, Counts[i]);
  3543. }
  3544. #endif
  3545. return hr;
  3546. }
  3547. HRESULT ByteCodeSerializer::DeserializeFromBuffer(ScriptContext * scriptContext, ulong scriptFlags, LPCUTF8 utf8Source, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, FunctionBody** function, uint sourceIndex)
  3548. {
  3549. return ByteCodeSerializer::DeserializeFromBufferInternal(scriptContext, scriptFlags, utf8Source, /* sourceHolder */ nullptr, srcInfo, buffer, nativeModule, function, sourceIndex);
  3550. }
  3551. // Deserialize function body from supplied buffer
  3552. HRESULT ByteCodeSerializer::DeserializeFromBuffer(ScriptContext * scriptContext, ulong scriptFlags, ISourceHolder* sourceHolder, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, FunctionBody** function, uint sourceIndex)
  3553. {
  3554. AssertMsg(sourceHolder != nullptr, "SourceHolder can't be null, if you have an empty source then pass ISourceHolder::GetEmptySourceHolder()");
  3555. return ByteCodeSerializer::DeserializeFromBufferInternal(scriptContext, scriptFlags, /* utf8Source */ nullptr, sourceHolder, srcInfo, buffer, nativeModule, function, sourceIndex);
  3556. }
  3557. HRESULT ByteCodeSerializer::DeserializeFromBufferInternal(ScriptContext * scriptContext, ulong scriptFlags, LPCUTF8 utf8Source, ISourceHolder* sourceHolder, SRCINFO const * srcInfo, byte * buffer, NativeModule *nativeModule, FunctionBody** function, uint sourceIndex)
  3558. {
  3559. //ETW Event start
  3560. JS_ETW(EventWriteJSCRIPT_BYTECODEDESERIALIZE_START(scriptContext, 0));
  3561. auto alloc = scriptContext->SourceCodeAllocator();
  3562. bool isLibraryCode = ((scriptFlags & fscrIsLibraryCode) == fscrIsLibraryCode);
  3563. int builtInPropertyCount = isLibraryCode ? PropertyIds::_countJSOnlyProperty : TotalNumberOfBuiltInProperties;
  3564. auto reader = Anew(alloc, ByteCodeBufferReader, scriptContext, buffer, isLibraryCode, builtInPropertyCount);
  3565. auto hr = reader->ReadHeader();
  3566. if (FAILED(hr))
  3567. {
  3568. return hr;
  3569. }
  3570. ENTER_PINNED_SCOPE(Js::Utf8SourceInfo, sourceInfo);
  3571. ENTER_PINNED_SCOPE(SRCINFO const, pinnedSrcInfo);
  3572. pinnedSrcInfo = srcInfo;
  3573. if(sourceIndex == Js::Constants::InvalidSourceIndex)
  3574. {
  3575. if (sourceHolder == nullptr)
  3576. {
  3577. sourceHolder = utf8Source == nullptr ? ISourceHolder::GetEmptySourceHolder() : RecyclerNew(scriptContext->GetRecycler(), SimpleSourceHolder, utf8Source, reader->sourceSize);
  3578. }
  3579. sourceInfo = Js::Utf8SourceInfo::NewWithHolder(scriptContext, sourceHolder, reader->sourceCharLength, pinnedSrcInfo);
  3580. reader->utf8SourceInfo = sourceInfo;
  3581. reader->sourceIndex = scriptContext->SaveSourceNoCopy(sourceInfo, reader->sourceCharLength, false);
  3582. if(isLibraryCode)
  3583. {
  3584. sourceInfo->SetIsLibraryCode();
  3585. }
  3586. sourceInfo->CreateLineOffsetCache(reader->lineInfoCache, reader->lineInfoCacheCount);
  3587. }
  3588. else
  3589. {
  3590. Assert(CONFIG_FLAG(ForceSerialized));
  3591. sourceInfo = scriptContext->GetSource(sourceIndex);
  3592. reader->utf8SourceInfo = sourceInfo;
  3593. reader->sourceIndex = sourceIndex;
  3594. }
  3595. auto cache = Anew(alloc, ByteCodeCache, scriptContext, reader, builtInPropertyCount);
  3596. hr = reader->ReadTopFunctionBody(function, sourceInfo, cache, ((scriptFlags & fscrAllowFunctionProxy) == fscrAllowFunctionProxy), nativeModule);
  3597. //ETW Event stop
  3598. JS_ETW(EventWriteJSCRIPT_BYTECODEDESERIALIZE_STOP(scriptContext,0));
  3599. LEAVE_PINNED_SCOPE();
  3600. LEAVE_PINNED_SCOPE();
  3601. return hr;
  3602. }
  3603. void ByteCodeSerializer::ReadSourceInfo(const DeferDeserializeFunctionInfo* deferredFunction, int& lineNumber, int& columnNumber, bool& m_isEval, bool& m_isDynamicFunction)
  3604. {
  3605. ByteCodeCache* cache = deferredFunction->m_cache;
  3606. ByteCodeBufferReader* reader = cache->GetReader();
  3607. reader->ReadSourceInfo(deferredFunction->m_functionBytes, lineNumber, columnNumber, m_isEval, m_isDynamicFunction);
  3608. }
  3609. FunctionBody* ByteCodeSerializer::DeserializeFunction(ScriptContext* scriptContext, DeferDeserializeFunctionInfo* deferredFunction)
  3610. {
  3611. FunctionBody* deserializedFunctionBody = nullptr;
  3612. ByteCodeCache* cache = deferredFunction->m_cache;
  3613. ByteCodeBufferReader* reader = cache->GetReader();
  3614. HRESULT hr = reader->ReadFunctionBody(deferredFunction->m_functionBytes, (FunctionProxy **)&deserializedFunctionBody, deferredFunction->m_utf8SourceInfo, cache, deferredFunction->m_nativeModule, true /* deserialize this */, false /* deserialize nested functions */, deferredFunction);
  3615. if (FAILED(hr))
  3616. {
  3617. // This should never happen as the code is currently
  3618. // structured since we validate the serialized bytecode during creation
  3619. // of function proxies. In the future though, when we reorganize the byte
  3620. // code file format, we could hit this error, in which case we
  3621. // need a strategy to deal with this.
  3622. Assert(false);
  3623. Js::Throw::InternalError();
  3624. }
  3625. return deserializedFunctionBody;
  3626. }
  3627. SerializedAuxiliary::SerializedAuxiliary( uint offset, SerializedAuxiliaryKind kind ) :
  3628. offset(offset), kind(kind)
  3629. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3630. , auxMagic(magicStartOfAux)
  3631. #endif
  3632. {
  3633. }
  3634. SerializedVarArray::SerializedVarArray( uint offset, bool isVarCount, int varCount ) :
  3635. SerializedAuxiliary(offset, isVarCount ? sakVarArrayVarCount : sakVarArrayIntCount), varCount(varCount)
  3636. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3637. , magic(magicStartOfAuxVarArray)
  3638. #endif
  3639. {
  3640. }
  3641. SerializedIntArray::SerializedIntArray( uint offset, int intCount ) :
  3642. SerializedAuxiliary(offset, sakIntArray), intCount(intCount)
  3643. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3644. , magic(magicStartOfAuxIntArray)
  3645. #endif
  3646. {
  3647. }
  3648. SerializedFloatArray::SerializedFloatArray( uint offset, int floatCount ) :
  3649. SerializedAuxiliary(offset, sakFloatArray), floatCount(floatCount)
  3650. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3651. , magic(magicStartOfAuxFltArray)
  3652. #endif
  3653. {
  3654. }
  3655. SerializedPropertyIdArray::SerializedPropertyIdArray( uint offset, int propertyCount, int extraSlots, bool hadDuplicates, bool has__proto__) :
  3656. SerializedAuxiliary(offset, sakPropertyIdArray), propertyCount(propertyCount), extraSlots(extraSlots), hadDuplicates(hadDuplicates), has__proto__(has__proto__)
  3657. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3658. , magic(magicStartOfAuxPropIdArray)
  3659. #endif
  3660. {
  3661. }
  3662. SerializedFuncInfoArray::SerializedFuncInfoArray( uint offset, int count ) :
  3663. SerializedAuxiliary(offset, sakFuncInfoArray), count(count)
  3664. #ifdef BYTE_CODE_MAGIC_CONSTANTS
  3665. , magic(magicStartOfAuxFuncInfoArray)
  3666. #endif
  3667. {
  3668. }
  3669. }