ByteCodeSerializer.cpp 180 KB

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